基于Spring与Apache Tomcat的控制台日志最佳打印方式及问题排查
解决Tomcat下Log4j日志时有时无及方法出入参打印问题
我来帮你拆解下你遇到的问题,一步步搞定:
一、先搞定日志“时有时无”的核心问题
你的现有Log4j配置有关键缺失,再加上Tomcat自带日志组件的冲突,才导致日志不稳定。
1. 补全并修正log4j.properties配置
你之前的配置没写完ConsoleAppender的核心配置,下面是完整可用的版本:
# 根日志级别设为debug,输出到控制台 log4j.rootCategory=debug, console # 你的业务包单独设置debug级别,关闭继承避免重复输出 log4j.logger.com.demo.package=debug, console log4j.additivity.com.demo.package=false # 控制台输出器完整配置 log4j.appender.console=org.apache.log4j.ConsoleAppender # 指定日志输出格式,包含时间、线程、级别、类、行号和内容,方便排查问题 log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{1}:%L - %m%n # 解决Tomcat控制台日志乱码问题 log4j.appender.console.encoding=UTF-8
2. 解决Tomcat自带日志的冲突
Tomcat默认用Java Util Logging(JUL),会和Log4j抢控制台输出,导致部分日志被吞。你需要修改Tomcat启动参数:
- Linux/Mac:打开
bin/catalina.sh,在开头添加:
CATALINA_OPTS="$CATALINA_OPTS -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager"
- Windows:打开
bin/catalina.bat,在开头添加:
set CATALINA_OPTS=%CATALINA_OPTS% -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
二、实现方法出入参日志打印
只靠Log4j配置没法自动打出入参,得结合代码或者AOP来做,给你两种方案:
方案1:手动添加日志(简单直接,适合少量方法)
在需要追踪的方法里直接加日志:
public User getUserById(Long id) { // 打印入参 logger.debug("getUserById 方法入参:id={}", id); User user = userDao.selectById(id); // 打印出参 logger.debug("getUserById 方法出参:user={}", user); return user; }
方案2:AOP全局拦截(适合批量处理所有方法)
如果你的项目用Spring,用AOP可以一次性给所有业务方法加出入参日志:
- 写一个切面类:
@Component @Aspect public class MethodLogAspect { private static final Logger logger = LoggerFactory.getLogger(MethodLogAspect.class); // 拦截com.demo.package下所有类的所有方法 @Pointcut("execution(* com.demo.package..*.*(..))") public void methodPointcut() {} @Around("methodPointcut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { // 获取方法和类信息 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); String className = signature.getDeclaringTypeName(); String methodName = signature.getMethod().getName(); // 获取入参 Object[] args = joinPoint.getArgs(); // 打印入参 logger.debug("【{}】类的【{}】方法入参:{}", className, methodName, Arrays.toString(args)); // 执行原方法 Object result = joinPoint.proceed(); // 打印出参 logger.debug("【{}】类的【{}】方法出参:{}", className, methodName, result); return result; } }
- 开启Spring AOP:如果是注解配置,在启动类加
@EnableAspectJAutoProxy;如果是XML配置,加<aop:aspectj-autoproxy/>。
三、验证步骤
- 替换你的
log4j.properties为上面的完整配置; - 修改Tomcat的启动参数;
- 重启Tomcat,测试接口,观察控制台日志是否稳定输出,方法出入参是否正常打印。
内容的提问来源于stack exchange,提问作者user6709592




