log4j2自定义appender插件源码、配置及采坑说明

Log4j2自定义插件实现自定义日志打印功能(脱敏/加密) *** log4j1.x重写log4j的PatternLayout,实现日志信息中敏感信息的编码或加密* log4j2.x重写log4j的AbstractStringLayout,实现日志信息中敏感信息的编码或加密*/*** 常用正则表达式:https://cloud.tencent.com/developer/article/1751120* 手机号正则匹配式* 实测雪花算法生成的Id可能会被手机号正则匹配到,故加了关键正则过滤:* (?...... 阅读详情

本篇为扩展appender标签,如果需要扩展filer、marker等其他的log4j2提供的扩展方式,可以查看相关的文档:
中文文档:https://www.docs4dev.com/docs/zh/log4j2/2.x/all/javadoc.html
英文文档:http://logging.apache.org/log4j/2.x/
api:http://logging.apache.org/log4j/2.x/log4j-api/apidocs/index.html
通过本篇,你可以看到我在扩展插件时所遇到的问题以及解决方案,根据ApplicationContext获取bean的工具类源码等。

不再是千篇一律的抄袭,真正将解决自己所遇到的问题的代码分享出来。

目录

自定义Appender插件类

关键代码

代码说明:

1.引入log4j2的插件注解,并声明相关属性的值

2.如何自定义变量

3.如何引入原生的插件,如rollingfile和console

4.为何本地自测有效,一到服务器就不生效?

5.我的bean注入是null?明明配置都对

log4j2.xml配置


 

自定义Appender插件类

关键代码

package com.xxx.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.*;
import org.apache.logging.log4j.core.config.AppenderControl;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import java.io.Serializable;

@Slf4j
@Plugin(name = "MyAppender", category = "Core", elementType = "appender", printObject = true)
public class MyAppender extends AbstractAppender {
    private  Configuration configuration;
    private Property[] properties;

    protected MyAppender(String name, Filter filter, Layout<? extends Serializable> layout,
                                  boolean ignoreExceptions, Property[] properties, AppenderRef[] appenderRefs) {
        super(name, filter, layout, ignoreExceptions, properties);
        this.appenderRefs = appenderRefs;
        this.properties = properties;
    }

    @Override
    public void append(LogEvent event) {
        try {
            // 可以增加处理业务日志逻辑
            try {
                callAppender(event);
            } catch (Exception e) {
                log.error("自定义异常信息", e);
            }
            try {
                // 可以根据日志级别处理日志-如写入数据库
                if (event.getLevel().intLevel() <= Level.ERROR.intLevel()) {}
            } catch (Exception e) {
                log.error("自定义异常信息", e);
            }
        } catch (Exception ex) {
            if (!ignoreExceptions()) {
                throw new AppenderLoggingException(ex);
            }
        }
    }

    @PluginFactory
    public static MyAppender createAppender(@PluginAttribute("name") String name,
                                            @PluginElement("Filter") Filter filter,
                                            @PluginElement("Layout") Layout<? extends Serializable> layout,
                                            @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
                                            @PluginElement("property") Property[] properties,
                                            @PluginElement("AppenderRef") AppenderRef[] appenderRefs) {
        if (name == null) {
            log.error("No name provided for MyAppenderImpl");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new MyAppender(name, filter, layout, ignoreExceptions, properties, appenderRefs);
    }

    private void callAppender(LogEvent event) {
        if (null == configuration) {
            refreshLogcontext();
        }
        for (AppenderRef appenderRef : appenderRefs) {
            if (null == configuration.getAppender(appenderRef.getRef())) {
                log.info("appenderRef null {}", appenderRef.getRef());
                continue;
            }
            recursion(event, appenderRef.getRef());
        }
    }

    private void refreshLogcontext() {
        LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
        this.configuration = loggerContext.getConfiguration();
    }

    private void recursion(LogEvent event, String ref) {
        if (configuration.getAppender(ref) instanceof RollingFileAppender) {
            Appender appender = configuration.getAppender(ref);
            AppenderControl control = new AppenderControl(appender, null, null);
            control.callAppender(event);
        } else if (configuration.getAppender(ref) instanceof AsyncAppender) {
            AsyncAppender asyncAppender = configuration.getAppender(ref);
            if (null != asyncAppender.getAppenderRefStrings()) {
                for (int j = 0; j < asyncAppender.getAppenderRefStrings().length; j++) {
                    // 递归
                    recursion(event, asyncAppender.getAppenderRefStrings()[j]);
                }
            }
        } else if (configuration.getAppender(ref) instanceof ConsoleAppender) {
            Appender appender = configuration.getAppender(ref);
            AppenderControl control = new AppenderControl(appender, null, null);
            control.callAppender(event);
        }
    }
}

代码说明:

1.引入log4j2的插件注解,并声明相关属性的值

@Plugin(name = "MyAppender", category = "Core", elementType = "appender", printObject = true)

  • name:插件的名称。请注意,此名称不区分大小写
  • category:用于放置插件的类别。类别名称区分大小写
  • elementType:此插件所属元素的相应类别的名称,当前扩展所属元素的类别是appender。
  • printObject:指示插件类是否实现Object.toString()方法,消息中使用。

2.如何自定义变量

createAppender方法,用于log4j2在扫描到插件之后根据配置文件中的配置穿件自定义的插件对象。

  • @PluginAttribute:是指插件的属性,如@PluginAttribute("name") String name

       <MyAppender name="MyAppenderTest"></Realtimeval>会取标签内name的值

  • @PluginElement:是指插件的子元素,如@PluginElement("AppenderRef") AppenderRef[] appenderRefs

     <MyAppender name="MyAppenderTest">
        <AppenderRef ref="AsyncMqLog"/>
        <AppenderRef ref="AsyncCONSOLE"/>
    </MyAppender>

     会获取标签下AppenderRef 元素的值,如果是多个AppenderRef 子元素,将会获取都一个数组
可以根据业务需要自定义元素或者属性。


3.如何引入原生的插件,如rollingfile和console

本篇中实现了自定义的标签引入log4j2原生的插件rollingfile和console,并控制原生的rollingfile和console向文件写入和控制台打印。
这一点区分于网上大部分的给出的代码示例,记住生产业务系统不能使用System.out.print,而且要注重高效,最好能用到log4j2自己实现的异步机制来完成我们想要的效果。
其实引入原生的插件rollingfile和console,并使它们发挥作用很简单,只需要call一下就可以,关键代码:

Appender appender = configuration.getAppender(ref);
AppenderControl control = new AppenderControl(appender, null, null);
control.callAppender(event);

4.为何本地自测有效,一到服务器就不生效?

本功能在实现的时候遇到一个难以预料的问题,就是本地怎么测试都好用,但是一部署到服务器就不好用,查过很多资料,不得不说国内的资料千篇一律的居多,参考意义不大。无奈自己搭建了xx谷歌了一下,发现如果你的自定义插件失效,可以从三个方面排查:

  • 配置文件configuration的packages属性没有设置或者没有设置成该插件所在的包,注意可以设置多个,用逗号隔开。<configuration monitorInterval="5" status="WARN" name="${app_name}"    packages="com.xxx.log4j2.pattern,com.xxx.util">

  • log4j2的插件是在编译期生成的缓存,而不是启动期间,所以,我们打包的插件需要讲生成的缓存插件.dat打包到jar包中才能生效。关于打包的问题可以自行百度一下,这个问题范围就小多了,一般来说,maven插件都会将插件缓存打包到jar中。用解压缩文件就可以打开jar并查看jar中的文件,该插件缓存在xx.jar\META-INF\org\apache\logging\log4j\core\config\plugins路径下。可以打开文件看到自定义的插件信息:

  • 如果上两个问题都排查过了,而且你也和我一样在代码中用到了logcontext,那么可能的原因是本地的logcontext和服务器上的logcontext加载的顺序不一致,导致服务器上的插件类在加载的时候所获取到的logcontext中的信息是最基础的,只有一个DefaultConsole插件。我的解决思路是调用的时候再去取一次logcontext。

5.我的bean注入是null?明明配置都对

再说一个上下文的问题,log4j2在dao层service层初始化结束之前就已经初始化了,如果采用@Resource这种依赖注入的方式构建bean是行不通的,获取到的只能是null,但是ApplicationContext已经加载(已经扫描哪些带有注解的类),我们可以通过ApplicationContext手动获取bean。
SpringBeanUtil源码:

package com.xxx.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Configuration
public class SpringBeanUtils implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringBeanUtils.applicationContext == null) {
            SpringBeanUtils.applicationContext = applicationContext;
        }
    }
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }
    public static <T> T getBean(String name, Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
    public static <T> T getBean(Class<? extends T> clazz, Class<T> targetClazz){
        return (T)getBean(clazz);
    }
}


用法:
注意第一个入参如果没有指定,默认是小写,这个应该都懂吧,spring的东西了
SpringBeanUtils.getBean("testAppenderDao", TestAppenderDao.class);

log4j2.xml配置

<?xml version="1.0" encoding="utf-8"?>
<configuration monitorInterval="5" status="WARN" name="${app_name}"
               packages="com.xxx.log4j2.pattern,com.xxx.util">
    <properties>
        <property name="LOG_HOME" value="log" />
        <property name="LOG_LEVEL" value="info" />
        <property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} |-%-5level [%thread] %c [%L] -| %msg%n</property>
        <property name="FILE_PATTERN">his/app-%d{MM-dd-yyyy}-%i.log</property>
        <property name="FILE_DEADLINE" value="7d" />
    </properties>
    <appenders>
        <Console name="CONSOLE" target="system_out">
            <PatternLayout pattern="${LOG_PATTERN}" />
        </Console>
        <!-- 滚动文件生成 fileName日志文件名称,filePattern压缩文件路径 -->
        <RollingFile name="MqLog" fileName="${LOG_HOME}/logs/rabbitmq/rabbitmq.log"
            <!-- 过滤日志级别 info及以上 -->
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <!-- 指定日志输出格式 -->
            <PatternLayout pattern="${LOG_PATTERN}" />
            <!-- 新文件生成策略,每100M生成一个新文件 -->
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <!-- 默认过度策略,不设置,则默认为最多同一文件夹下7个文件 大于此值会删除旧的日志文件 -->
            <DefaultRolloverStrategy>
                <!-- 文件删除策略,basePath扫描路径,maxDepth目录的最大级别数,IfFileName文件名称,IfLastModified指定持续时间(7天前)-->
                <Delete basePath="${LOG_HOME}/logs/rabbitmq" maxDepth="2">
                    <IfFileName glob="*.log" />
                    <IfLastModified age="${FILE_DEADLINE}" />
                </Delete>
                <Delete basePath="${LOG_HOME}/logs/rabbitmq" maxDepth="2">
                    <IfFileName glob="*.log" />
                    <IfAccumulatedFileSize exceeds="${FILE_MAX_SIZE}" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <Async name="AsyncCONSOLE">
            <AppenderRef ref="CONSOLE"/>
        </Async>
        <Async name="AsyncMqLog">
            <AppenderRef ref="MqLog"/>
        </Async>
        <MyAppender name="MyAppenderTest">
            <AppenderRef ref="AsyncMqLog"/>
            <AppenderRef ref="AsyncCONSOLE"/>
            <property name="logType" value="1"/>
        </MyAppender >
    </appenders>

    <loggers>
        <AsyncLogger name="com.xxx.mq" level="info" additivity="false">
            <AppenderRef ref="MyAppenderTest" />
        </AsyncLogger>
        <root level="${LOG_LEVEL}">
            <AppenderRef ref="AsyncCONSOLE" />
        </root>
    </loggers>
</configuration>


配置说明:

  • 定义了两个appender:CONSOLE、MqLog
  • 异步:AsyncCONSOLE、AsyncMqLog
  • 引入到我们自己的标签中:

        <MyAppender name="MyAppenderTest">
            <AppenderRef ref="AsyncMqLog"/>
            <AppenderRef ref="AsyncCONSOLE"/>
            <property name="logType" value="1"/>
        </MyAppender >

  • 引入到异步Loggers标签中,只对com.xxx.mq这里路径下的日志起作用:

        <AsyncLogger name="com.xxx.mq" level="info" additivity="false">
            <AppenderRef ref="MyAppenderTest" />
        </AsyncLogger>


我们可以使用自己扩展的标签引入不同的console和rollingfile等标签,可以配置不同的属性和元素,也可以监控不同的项目路径以达到业务需要的效果。

log4j2自定义动态配置日志 项目需求 1.平台日志:Spring Boot项目中接入log4j2日志,公共配置作平台日志。 2.业务日志:为了方便定位业务问题自定义动态日志,根据不同业务输出不同名称的日志文件。 思路分析 第一个需求比较容易,网上教程资料非常多,多注意细节。第二个需求网上资料就很少了,需要去看一些源码信息了解日志打印过程使用的方法,然后根据业务需求做一个公共类:用户调用工具方法输入业务名称、日志路径等参数自定... 阅读详情

相关推荐

java程序如何打包为jar,以及避免log4j2在打包后出现异常

问题描述 将使用log4j2的程序打包后出现如下异常: ERROR StatusLogger Unrecognized format specifier [d] ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern. ERROR StatusLogger Unrecognized format specifier [thread] ERROR StatusL

soulfire的博客 2525

log4j2中的自定义Appender详解

log4j官网提供了很多Appender组件,但是当那些组键不满足日志收集的时候,我们需要自己定义Appender 定点Appender需要处理好两个地方的问题 1.需要在代码中写一个自定义Appender 2.修改log4j.xml文件中的Appenders下面引用的Appender为自定义appender 首先是代码实现主要是继承AbstractAppender这个抽象类,重写append()方法 append方法是我们进行接收日志的方法 createAppender 这个方法可以用来接收页面的传参数

li646495946的博客 8226

log4j初始化失败警告:No appenders could be found原因与根治

Log4j是Java生态中历史悠久的日志框架,其核心机制围绕Logger、Appender和配置加载展开。当出现'No appenders could be found'警告时,本质是log4j 1.x在类加载阶段未能成功挂载任何Appender——既非语法错误,也非类缺失,而是日志输出通道未建立。该问题深层关联log4j.xml或log4j.properties的加载顺序、ClassLoader资源可见性、DOMConfigurator解析容错性等运行时行为。在遗留系统、微服务模块化部署及Spring B

weixin_34327761的博客 425

log4j2实现自定义Appender(输出到文件/RPC服务中)

1、背景 虽然log4j很强大,可以将日志输出到文件、DB、ES等。但是有时候确难免完全适合自己,此时我们就需要自定义Appender,使日志输出到指定的位置上。 本文,将通过两个例子说明自定义APPender,一个是将日志写入文件中,另一个是将日志发送到远程Thrift服务中。 本文代码详见:https://github.com/hawkingfoo/log-demo 2、自定义文件Ap

零度的博客专栏 5292

Apache Log4j 2.13.3源码深度解析与实战

日志记录是现代软件系统中不可或缺的一部分,尤其在复杂的企业级Java应用中,日志系统不仅用于调试和监控,更是系统运维和故障排查的重要依据。Log4j 2作为Apache推出的日志框架,继承并改进了经典的Log4j 1.x版本,同时在性能、可扩展性和线程安全方面进行了全面优化。相较于Logback等同类日志框架,Log4j 2在异步日志处理、配置灵活性、插件化架构等方面展现出明显优势。它支持多种配置格式(如XML、JSON、YAML),并提供强大的过滤机制和动态配置加载能力。

weixin_35756892的博客 661

边缘设备选型指南:从数据采集到AI推理,工业物联网硬件如何匹配你的需求?

本文提供了一份全面的工业物联网边缘设备选型指南,系统性地阐述了如何根据数据采集、协议兼容性、边缘AI推理算力及环境适应性等核心需求匹配硬件。文章深入剖析了从CPU/GPU/NPU选择到MQTT、Sparkplug B等工业协议支持的实战考量,并强调了软件生态与全生命周期成本的重要性,旨在帮助项目负责人在复杂场景中做出明智决策。

weixin_29168813的博客 86

Java日志:log4j2

java日志框架、log4j2

a4453368的博客 1662

傻瓜教程:使用GeoServer发布离线地图服务

一、离线地图下载 离线地图分为两种:一种叫“金字塔瓦片”数据,一种叫“矢量地图数据”。我们看的在线地图比如,百度,谷歌,高德等等网页上的地图,都是金字塔瓦片;另外一种是手机上用来导航的,比如高德地图APP,也可以下载离线地图数据,这个就是矢量的。 卫星影像地图都是金字塔瓦片,无矢量数据。 因此,我们所说的离线地图下载通常都是指离线地图金字塔瓦片数据下载。 离线地图金字塔瓦片搭建的离线地图服务分很多种:一般有WEB方式,TMS、WMTS/WMS等等,不同的应用有不同...

米兰的小码农的博客 1万+

CAT 日志异常上报集成指南:Log4j / Log4j2 / Logback 接入 CAT 的 error 级别异常监控

CAT(Central Application Tracking)作为美团点评开源的实时监控平台,除了通过 `Cat.logError`、`Cat.newTransaction` 等 API 埋点外,还提供了与主流 Java 日志框架(Log4j、Log4j2、Logback)的零侵入集成方案:只要在日志框架配置中挂载一个 CAT 专用 Appender,业务代码中所有 error 级别且携带异常

gitblog_00091的博客 460

小红书urlscheme和Activity

本文档详细介绍了小红书App的Deeplink跳转规范,涵盖了多个功能模块的跳转协议。主要内容包括:主页各Tab(关注、发现、购买)的跳转方式;不同类型笔记(图文/视频/长笔记)的详情页跳转参数;用户相关页面(主页/绑定/资料/消息等)的跳转协议;搜索功能(输入页/结果页)的跳转方式;以及话题、标签、专辑、H5页面等特殊场景的跳转实现。文档还提供了各跳转协议所需的参数说明,包括参数类型、默认值、是否必填等详细信息,并标注了不同版本和平台的兼容性要求。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 779

CMake入门教程【基础篇】在Windows、Linux上安装CMake

CMake如何下载与安装

小鱼酱的博客 2717

CAT 集成 Log4j2:CatAppender 配置与错误日志上报原理详解

CAT(Central Application Tracking)是服务端项目的基础监控组件,为 Java、C/C++、Node.js、Python、Go 等多语言客户端提供统一埋点与上报能力。本文聚焦当前仓库中 Log4j2 日志框架的官方集成方案,讲解如何在 `log4j2.xml` 中配置 CAT 自定义 Appender,并深入其源码实现,说明 ERROR 日志如何自动转换为 CAT 的

gitblog_00885的博客 99

【虚幻引擎UE】UE5 四步骤实现AI漫游与对话行为(含工程源码)

【虚幻引擎UE】UE5 四步骤实现AI漫游与对话行为(含工程源码)

灵境引路人 3222

MCreator 实体动画振幅(Animation Amplitude)参数详解:控制步行动画效果强度

本篇指南围绕 MCreator「生物实体(Living Entity)」元素中动画列表的 **Amplitude(振幅)** 参数展开。该参数用于控制实体播放动画时效果的强弱,且仅对**步行动画(Walking Animation)**生效。读完本文,你将掌握振幅参数的准确语义、取值范围与 UI 交互规则,并通过仓库源码理解它在动画渲染流程中的底层作用方式,从而在制作 Mod 实体动画时获得更精细

gitblog_00990的博客 231

46、聚类算法在智能交通数据分析中的应用

本文探讨了聚类算法在智能交通数据分析中的应用,介绍了K-均值算法、K-中心点算法和基于模型的聚类算法的基本原理及特点,并结合实际交通数据讨论了其应用场景与挑战。通过聚类分析,能够从海量交通数据中发现隐藏模式,为交通管理和规划提供科学依据。文章还展示了具体的案例分析和实现流程,为未来智能交通系统的发展提供了参考。

zz67890的博客 127

MATLAB之把多个小cell拼成一个数组

问题描述 现有一个cell向量 L (90000,1),每个元素都是由一个(100X9)的double数组组成的.如图. 其中, 每个cell元素都是一个单独的数据, 我们要把它转换成(90000, 19, 100)的三维数组. cell2mat, 但是所有的数据会堆叠起来 L2=cell2mat(L); % (90000, 19) reshape, 变成三维数组 reshape的原理是从上到下, 从左往右拆开重组. 目前只有19这一维数据与要求一致, 那就以这个为突破口. L2=L2'; %

落日之城 9245

Apereo CAS 日志路由到 AWS SQS:SQSAppender 配置详解与底层实现剖析

本篇技术指南聚焦 Apereo CAS 的 AWS SQS 日志集成能力:通过 `cas-server-support-logging-config-sqs` 模块与 Log4j2 自定义 Appender,将 CAS 运行日志实时投递到 Amazon SQS 队列,实现集中式日志采集与下游消费。读完本文,你将掌握 SQSAppender 的完整配置方法、队列自动创建与凭据解析机制,并能从源码层面

gitblog_01098的博客 329

微信小程序 - 实现仿小红书轮播图组件功能,类似小红书笔记页面图片展示播放效果,微信小程序仿小红书幻灯片轮播支持视频播放、图片预览,自动适应图片或视频大小可左右滑动切换(小程序精美轮播图,丝滑切换)

微信小程序,轮播图组件,微信小程序仿小红书轮播图,小红书轮播图仿造,微信小程序轮播图,微信小程序幻灯片,微信小程序高仿小红书轮播图实现,小程序实现类似小红书一样的轮播图组件,轮播图插件,精致轮播图,精美丝滑流畅切换的轮播图,轮播图组件,小红薯轮播图,关于小红书的小程序不同数量的轮播图,展示不一样的轮播指示点的实现,微信小程序仿小红书图片轮播,开发微信小程序模仿小红书,高仿小红书Banner的指示器,小红书小程序笔记详情轮播图指示点的随图片数量的变化动态变化,微信小程序swiper轮播图,js轮播图,html

✅ 精选推荐文章 6921

QtScrcpy 完整指南:Android 免 Root 投屏与控制,从首次连接到按键映射一次搞定

QtScrcpy 是一个免 Root 权限的 Android 投屏与控制工具,通过 USB 或 WiFi 把手机屏幕实时镜像到电脑,并可以用键鼠反向操作设备,支持 Windows、macOS 和 Linux,适合电脑侧处理手机消息、录制手机教程、键鼠玩手游等场景。读完本文,你可以: - 三步连接第一台手机并开始投屏 - 用键盘鼠标控制手机,掌握常用快捷键 - 配置按键映射,用键盘玩手游、刷短视频

gitblog_00053的博客 412

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

log4j 升到 2.25.4 就安全了吗?这批 7 条散在 4 个模块,有 1 条要 2.25.5

这批 7 条公告里 6 条写修复版 2.25.4,第 7 条要 2.25.5,而它的 advisory 没有任何包与版本数据,机器读不到。附零依赖自查工具。全部 medium,无 RCE。

P191117的博客 444

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Apereo CAS 日志接入 AWS CloudWatch:CloudWatchAppender 配置实战与源码解析

> 本文面向需要在 Apereo CAS 中把应用日志实时汇聚到 AWS CloudWatch 的部署与运维场景。你将掌握 `cas-server-support-aws-cloudwatch` 模块的引入方式、log4j2 `CloudWatchAppender` 的完整 XML 配置、资源自动创建开关的优先级语义、AWS 凭证的七级解析链,以及底层的异步投递与 sequence token 机

gitblog_00039的博客 262

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Log4j2入门(1)-控制台日志输出

Log4j2入门(1)-控制台日志输出Log4j2入门1-控制台日志输出 1引入依赖 2构思需求 3Log4j简单的配置文件 4编写demo 刚学习log4j2日志,对于里面的root和logger的继承关系比较迷惑,遂有此文使用控制台输出不同级别的日志,并定义日志的继承关系测试附上demo地址 示例项目使用maven作依赖管理github源码地址:https://github.com/fizzm

fizzblock的博客 2万+

open-source-games:160+ 款开源游戏名录,3 分钟定位你想玩的游戏和它的源码

open-source-games 是一份收录 160 多款开源游戏与经典商业游戏开源复刻版的目录清单。仓库里没有游戏本体,只有一份 README.md,但每条都写清了游戏是什么、源码去哪儿拿。想白玩一款免费开源游戏,或者想扒源码学习,从这份名单入手,三分钟就能开始挑。 ## 名单里有什么:17 个类别、两种游戏 打开 README,开头是一张 17 个游戏类别的目录,从 Action、Adv

gitblog_00552的博客 1069

Apache Pulsar 2.1.1 配置完全指南:BookKeeper、Broker、Client 与各服务配置文件逐项详解

Apache Pulsar 的绝大部分运行行为——端口监听、消息存储策略、配额与保留策略、鉴权与 TLS、负载均衡与日志输出——都可以通过安装目录下 `conf` 目录中的一系列 `.conf` 配置文件进行管理。本文以 Pulsar 2.1.1-incubating 官方参考文档为主体,逐项拆解 BookKeeper、Broker、Client、服务发现、Log4j、Standalone、Web

gitblog_00187的博客 258

mirai-logging 日志转接指南:用 Log4j2、SLF4J、Logback 接管 Mirai 日志系统

mirai 自带一套轻量级内建日志系统([MiraiLogger](https://link.gitcode.com/i/38fb395dc4360f82763e10ad259c7b9e)),但它仅能处理简单的日志任务。当你在生产环境部署 QQ 机器人,需要与项目中的 Log4j2、SLF4J、Logback 等主流日志框架统一管理、统一输出格式时,`mirai-logging` 系列转接模块可以

gitblog_00058的博客 470

log4js-node 核心术语全解:Level、Category、Appender、Logger、Layout 与 LogEvent 的工作原理

log4js-node 是 Java 日志框架 log4j 在 Node.js 生态中的移植实现(项目描述见 [README.md](https://link.gitcode.com/i/ef73667c3356e979884d8bf1a97d5cfe)),其日志体系由六个核心概念构成:Level、Category、Appender、Logger、Layout 与 LogEvent。本文以 [do

gitblog_01057的博客 847
上一篇: Log4j2不同级别的日志写入到不同文件+扩展日志级别实现业务日志分类
下一篇: 日志记录的问题-翻译
Dame Time
博客等级 码龄10年 7粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值