You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:42:15