Spring MVC中日志功能无法正常工作的问题求助
问题描述
我本地运行着一个Spring MVC应用,尝试在AOP切面类中实现日志功能,但运行后无任何日志输出。先后尝试了java.util.logger和Log4j均未成功,只要能正常工作,使用哪种日志框架均可。最终目标是将应用部署到线上后,日志信息能输出到Tomcat服务器日志中。
我的代码与配置
AOP切面类代码
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; public class ApplicationLoggingAspect { //setup logger private Logger logger = LogManager.getLogger(this.getClass().getName()); @Before("forApplication()") public void before(JoinPoint theJoinPoint) { //display name of the method String theMethod = theJoinPoint.getSignature().toString(); logger.info("=======>>in @Before: calling method: " + theMethod) // 这里缺少分号! } }
Log4j2配置文件(log4j2.properties)
# LOG4J configuration status = info dest = err name = PropertiesConfig filter.threshold.type = ThresholdFilter filter.threshold.level = all appender.console.type = Console appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %m%n appender.console.filter.threshold.type = ThresholdFilter appender.console.filter.threshold.level = all rootLogger.level = all rootLogger.appenderRef.stdout.ref = STDOUT log4j2.debug
排查与解决方案
我帮你梳理几个关键的排查和解决步骤,按顺序来应该能搞定这个问题:
1. 先修复切面代码的基础问题
首先,你的切面代码有两个明显的问题:
- 语法错误:
before方法最后一行的logger.info语句末尾缺少分号,这会导致编译失败,切面类无法正常加载,自然不会有日志输出,先补上这个分号。 - 切点未定义:你在
@Before注解里引用了forApplication(),但没有定义这个切点方法!这会导致AOP无法识别要拦截的目标方法,切面逻辑根本不会触发。
修复后的切面类代码示例:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; // 加上@Component让Spring扫描到这个切面类 @Component // 加上@Aspect标记这是一个切面类 @Aspect public class ApplicationLoggingAspect { //setup logger private Logger logger = LogManager.getLogger(this.getClass().getName()); // 定义切点:替换成你实际要拦截的包/方法路径,这里示例是拦截com.yourpackage下所有类的所有方法 @Pointcut("execution(* com.yourpackage..*(..))") public void forApplication() {} @Before("forApplication()") public void before(JoinPoint theJoinPoint) { //display name of the method String theMethod = theJoinPoint.getSignature().toString(); logger.info(">>>>>in @Before: calling method: " + theMethod); // 补上分号 } }
2. 确保Spring开启了AOP支持
光有切面类还不够,需要告诉Spring启用AspectJ自动代理:
- 如果是注解配置:在你的Spring配置类上添加
@EnableAspectJAutoProxy注解 - 如果是XML配置:在Spring的配置文件中添加
<aop:aspectj-autoproxy/>标签(记得引入aop命名空间)
3. 检查Log4j2的依赖是否齐全且无冲突
如果是Maven项目,确保你引入了正确的Log4j2依赖,并且排除了可能冲突的日志框架(比如SLF4J的其他绑定):
<dependencies> <!-- Log4j2核心API和实现 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.20.0</version> <!-- 建议使用最新稳定版 --> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency> <!-- 如果Spring使用SLF4J作为日志门面,需要这个桥接包 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.20.0</version> </dependency> </dependencies>
4. 调整Log4j2配置,适配Tomcat日志输出
要让日志输出到Tomcat的服务器日志目录,推荐使用RollingFileAppender替代ConsoleAppender,这样日志会单独存放在Tomcat的logs目录下,方便线上排查和归档。修改后的log4j2.properties示例:
status = warn name = TomcatLogConfig # 输出到Tomcat的logs目录,自定义日志文件名 appender.tomcatFile.type = RollingFile appender.tomcatFile.name = TomcatFile appender.tomcatFile.fileName = ${sys:catalina.base}/logs/your-app.log appender.tomcatFile.filePattern = ${sys:catalina.base}/logs/your-app-%d{yyyy-MM-dd}-%i.log.gz # 日志格式:包含时间、线程、级别、类名、日志内容 appender.tomcatFile.layout.type = PatternLayout appender.tomcatFile.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n # 滚动策略:按天分割,单个文件超过10MB也分割 appender.tomcatFile.policies.type = Policies appender.tomcatFile.policies.time.type = TimeBasedTriggeringPolicy appender.tomcatFile.policies.time.interval = 1 appender.tomcatFile.policies.time.modulate = true appender.tomcatFile.policies.size.type = SizeBasedTriggeringPolicy appender.tomcatFile.policies.size.size = 10MB # 最多保留10个归档日志文件 appender.tomcatFile.strategy.type = DefaultRolloverStrategy appender.tomcatFile.strategy.max = 10 # 根日志级别设为info,输出到上面定义的TomcatFile appender rootLogger.level = info rootLogger.appenderRef.tomcatFile.ref = TomcatFile
注意:${sys:catalina.base}是Tomcat提供的系统变量,会自动指向Tomcat的安装目录,不用硬编码路径。
5. 先验证日志框架本身是否正常工作
在排查AOP问题之前,先单独测试Log4j2是否能正常输出日志,排除日志框架的问题:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class LogTest { private static final Logger logger = LogManager.getLogger(LogTest.class); public static void main(String[] args) { logger.info("测试Log4j2是否正常输出"); logger.debug("测试debug级别日志"); } }
如果这个测试类能正常输出日志,说明Log4j2本身没问题,问题出在AOP的配置上;如果还是没输出,检查配置文件是否放在src/main/resources目录下(确保打包后在classpath中),或者依赖是否有冲突。
6. 线上Tomcat日志的额外检查
部署到线上Tomcat后,确保:
- Tomcat的
conf/logging.properties没有限制日志级别(比如不要把级别设为只允许ERROR) - Tomcat的
logs目录有写入权限,避免日志无法写入 - 如果还是想把日志输出到
catalina.out,可以保留ConsoleAppender,因为Tomcat默认会把System.out重定向到catalina.out
内容的提问来源于stack exchange,提问作者W. Wuffley
相关产品推荐
相关产品推荐

