当前位置: 首页 > news >正文

项目日志框架与jar中日志框架冲突 解决

背景

项目用的日志框架是Log4j2,依赖如下:

        <dependency> <!-- 引入log4j2依赖 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>${boot.version}</version></dependency>

第三方日志框架

依赖

    <dependencies><dependency><groupId>${project.groupId}</groupId><artifactId>ctg-mq-common</artifactId><exclusions><exclusion><groupId>io.netty</groupId><artifactId>netty-tcnative</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><scope>test</scope></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></dependency></dependencies>

创建日志方法

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.rocketmq.client.log;import java.lang.reflect.Method;
import java.net.URL;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class ClientLogger {public static final String CLIENT_LOG_ROOT = "rocketmq.client.logRoot";public static final String CLIENT_LOG_MAXINDEX = "rocketmq.client.logFileMaxIndex";public static final String CLIENT_LOG_LEVEL = "rocketmq.client.logLevel";private static Logger log;private static Logger createLogger(String loggerName) {String logConfigFilePath = System.getProperty("rocketmq.client.log.configFile", System.getenv("ROCKETMQ_CLIENT_LOG_CONFIGFILE"));Boolean isloadconfig = Boolean.parseBoolean(System.getProperty("rocketmq.client.log.loadconfig", "true"));String log4JResourceFile = System.getProperty("rocketmq.client.log4j.resource.fileName", "log4j_rocketmq_client.xml");String logbackResourceFile = System.getProperty("rocketmq.client.logback.resource.fileName", "logback_rocketmq_client.xml");String log4J2ResourceFile = System.getProperty("rocketmq.client.log4j2.resource.fileName", "log4j2_rocketmq_client.xml");String clientLogRoot = System.getProperty("rocketmq.client.logRoot", System.getProperty("user.home") + "/logs/rocketmqlogs");System.setProperty("client.logRoot", clientLogRoot);String clientLogLevel = System.getProperty("rocketmq.client.logLevel", "INFO");System.setProperty("client.logLevel", clientLogLevel);String clientLogMaxIndex = System.getProperty("rocketmq.client.logFileMaxIndex", "10");System.setProperty("client.logFileMaxIndex", clientLogMaxIndex);if (isloadconfig) {try {ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory();Class classType = iLoggerFactory.getClass();if (classType.getName().equals("org.slf4j.impl.Log4jLoggerFactory")) {Class<?> domconfigurator = Class.forName("org.apache.log4j.xml.DOMConfigurator");Object domconfiguratorobj = domconfigurator.newInstance();if (null == logConfigFilePath) {Method configure = domconfiguratorobj.getClass().getMethod("configure", URL.class);URL url = ClientLogger.class.getClassLoader().getResource(log4JResourceFile);configure.invoke(domconfiguratorobj, url);} else {Method configure = domconfiguratorobj.getClass().getMethod("configure", String.class);configure.invoke(domconfiguratorobj, logConfigFilePath);}} else if (classType.getName().equals("ch.qos.logback.classic.LoggerContext")) {Class<?> context = Class.forName("ch.qos.logback.core.Context");Class<?> joranConfigurator = Class.forName("ch.qos.logback.classic.joran.JoranConfigurator");Object joranConfiguratoroObj = joranConfigurator.newInstance();Method setContext = joranConfiguratoroObj.getClass().getMethod("setContext", context);setContext.invoke(joranConfiguratoroObj, iLoggerFactory);if (null == logConfigFilePath) {URL url = ClientLogger.class.getClassLoader().getResource(logbackResourceFile);Method doConfigure = joranConfiguratoroObj.getClass().getMethod("doConfigure", URL.class);doConfigure.invoke(joranConfiguratoroObj, url);} else {Method doConfigure = joranConfiguratoroObj.getClass().getMethod("doConfigure", String.class);doConfigure.invoke(joranConfiguratoroObj, logConfigFilePath);}} else if (classType.getName().equals("org.apache.logging.slf4j.Log4jLoggerFactory")) {Class<?> joranConfigurator = Class.forName("org.apache.logging.log4j.core.config.Configurator");Method initialize = joranConfigurator.getDeclaredMethod("initialize", String.class, String.class);if (null == logConfigFilePath) {initialize.invoke(joranConfigurator, "log4j2", log4J2ResourceFile);} else {initialize.invoke(joranConfigurator, "log4j2", logConfigFilePath);}}} catch (Exception e) {System.err.println(e);}}return LoggerFactory.getLogger("RocketmqClient");}public static Logger getLog() {if (log == null) {log = createLogger("RocketmqClient");return log;} else {return log;}}public static void setLog(Logger log) {ClientLogger.log = log;}
}

在不做处理的情况下,调用第三方jar中方法后会提示

2025-08-14 15:31:02,506 main WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender

然后只能输出error日志了

原因

问题是典型的 日志框架冲突日志配置未正确加载 导致的。根据你的描述,问题发生在调用第三方 JAR 中的类时,日志从正常输出 INFO 级别突然只能输出 ERROR 级别,并出现如下警告:

WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender

这说明 Log4j2 没有找到有效的配置文件,使用了默认的错误级别根日志器(Root Logger)

解决方法

问题分析

1. 第三方 JAR 中的日志初始化逻辑

你贴出的 createLogger() 方法是 RocketMQ 客户端或类似中间件的典型日志初始化方式。它通过反射动态判断当前使用的日志实现(Log4j、Logback、Log4j2),然后尝试加载对应的配置文件(如 log4j2_rocketmq_client.xml)。

关键点是:

} else if (classType.getName().equals("org.apache.logging.slf4j.Log4jLoggerFactory")) {Class<?> joranConfigurator = Class.forName("org.apache.logging.log4j.core.config.Configurator");Method initialize = joranConfigurator.getDeclaredMethod("initialize", String.class, String.class);if (null == logConfigFilePath) {initialize.invoke(joranConfigurator, "log4j2", log4J2ResourceFile); // ← 默认加载 log4j2_rocketmq_client.xml} else {initialize.invoke(joranConfigurator, "log4j2", logConfigFilePath);}
}

这段代码会 强制使用 Configurator.initialize() 重新初始化 Log4j2 的配置,而这个方法会 覆盖当前已有的 Log4j2 配置

2. 为什么只输出 ERROR 日志?

因为第三方 JAR 尝试加载的 log4j2_rocketmq_client.xml 文件在你的项目 classpath 中 不存在,导致 Log4j2 初始化失败,进入“默认模式”——只创建一个 ERROR 级别的 Root Logger 并绑定 Console Appender。

这就是警告信息的来源:

WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender

方案一:提供第三方所需的 Log4j2 配置文件(推荐)

推荐

System.setProperty("rocketmq.client.log.loadconfig", "false");
-Drocketmq.client.log.loadconfig=false

http://www.dtcms.com/a/331046.html

相关文章:

  • 《多级缓存架构设计与实现全解析》
  • 自动化测试|持续集成Git使用详解
  • label studio 服务器端打开+xshell端口转发设置
  • 01数据结构-最短路径Dijkstra
  • 【数据结构入门】
  • 移动机器人底盘在高校科研中的AI智能教育应用
  • (第十五期)HTML文本格式化标签详解:让文字更有表现力
  • Flutter GetX 全面指南:状态管理、路由与依赖注入的最佳实践
  • SpringMVC请求与响应
  • 三坐标测量仪:从机械精密到智能协同的技术
  • flutter 开发 鸿蒙 App
  • gitee_配置自动部署vue项目
  • Uniapp 获取系统信息:uni.getSystemInfo 与 uni.getSystemInfoSync
  • vs2022 opencv环境配置(使用相对地址-将依赖都放入项目中)
  • spring boot配置es
  • 开发避坑指南(26):Vue3 input输入框前置后 置元素解决方案
  • 新增和编辑共用弹窗模板
  • .Net Core控制台程序连接HGDB并部署到Linux
  • 【C#】跨平台创建你的WinForms窗体应用(WindowsUbuntu)
  • 上网行为安全概述和组网方案
  • 深入解析 HTTP 协议演进:从 1.0 到 3.0
  • 【web站点安全开发】任务4:JavaScript与HTML/CSS的完美协作指南
  • 嵌入式Linux学习-编译内核源码
  • vscode的ws环境,esp32s3连接wifi
  • 深入解析Python身份切换:安全权限管理实践指南
  • MyBatis缓存模块深度解析
  • dolphinscheduler中任务输出变量的问题出现ArrayIndexOutOfBoundsException
  • MCP和Agent之间的区别和联系
  • vercel部署上线
  • lesson38:MySQL数据库核心操作详解:从基础查询到高级应用