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

升级CXF至3.1、Log4j2后Spring Java应用异常日志无法输出至文件及SMTP

问题:升级CXF与Log4j后异常日志无法被RollingFile/SMTP Appender记录

Spring Java应用升级CXF(从2.x到3.1)和Log4j(从1.x到2.x)后,日志功能出现异常:RollingFile Appender和SMTP Appender不再记录异常信息。使用maven-jetty插件运行时,异常能正常打印到控制台,但其他日志都能正常输出,只有异常日志无法被这两个Appender记录。

此前使用的outFaultInterceptors已按团队建议移除,替换为providers中的ExceptionMapper,相关配置如下:

applicationcontext.xml

<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>

<jaxrs:server id="serviceResource" address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="endpoint1"/>
        <ref bean="endpoint2"/>            
    </jaxrs:serviceBeans>

    <!-- this is removed after migrating to new cxf 3 infavor of exception mappers
    <jaxrs:outFaultInterceptors>
        <ref bean="cxfRestFaultInterceptor"/>
    </jaxrs:outFaultInterceptors>
    -->
    
    <jaxrs:inInterceptors>
        <ref bean="logInbound"/>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
        <ref bean="logOutbound"/>
    </jaxrs:outInterceptors>
    <jaxrs:providers>
        <bean id="businessExceptionMapper"
              class="com.commons.interceptors.BusinessExceptionMapper">
            <property name="exceptionMessageSource" ref="exceptionMessageSource"/>
            <property name="exceptionCodeSource" ref="exceptionCodeSource"/>
        </bean>
        <bean id="globalExceptionMapper"
              class="com.common.interceptors.GlobalExceptionMapper">
            <property name="messageSource" ref="messageSource"/>
        </bean>
        <bean id="applicationExceptionMapper"
              class="com.common.interceptors.ApplicationExceptionMapper">
            <property name="messageSource" ref="messageSource"/>
        </bean>
        <ref bean='jacksonProvider'/>
    </jaxrs:providers>
</jaxrs:server>

log4j2.xml

<Configuration>

    <Appenders>
        <RollingFile
                name="fileout"
                fileName="../logs/web.log"
                filePattern="../logs/web.%i.log"
                ignoreExceptions="false"
                append="true">
            <PatternLayout>
                <Pattern>[%d{DATE}] - %X{hostName} - [%-5p][%c{1},%t] - %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="2MB"/>
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>

        <SMTP
                name="mail"
                from="from_email"
                to="to_email"
                subject="APIWebError"
                smtpHost="smtp_host">
            <HtmlLayout/>

        </SMTP>        
    </Appenders>

    <Loggers>        
        <Root level="error">
            <AppenderRef ref="fileout"/>
            <AppenderRef ref="mail"/>
        </Root>
    </Loggers>

</Configuration>

说明:outFaultInterceptors此前被使用,现已移除,替换为providers中的ExceptionMapper,此为团队推荐方案。


解决方案

1. 补全ExceptionMapper的日志输出逻辑

替换outFaultInterceptors后,原拦截器负责的异常日志输出逻辑丢失,需要在三个ExceptionMapper的实现类中主动添加日志记录:
在BusinessExceptionMapper、GlobalExceptionMapper、ApplicationExceptionMapper的toResponse方法中,加入Log4j2日志代码,注意必须传入异常对象以输出堆栈信息:

private static final Logger logger = LogManager.getLogger(GlobalExceptionMapper.class);

@Override
public Response toResponse(Throwable exception) {
    // 记录包含堆栈的异常日志
    logger.error("系统处理异常", exception);
    // 原有构建响应的逻辑
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                   .entity("服务内部错误")
                   .build();
}

2. 修改Log4j2的PatternLayout配置

当前Pattern仅输出日志消息,未包含异常堆栈,需添加%ex参数:

<Pattern>[%d{DATE}] - %X{hostName} - [%-5p][%c{1},%t] - %m%ex%n</Pattern>

3. 优化SMTP Appender配置

确保SMTP Appender能捕获完整异常信息,可明确配置布局和级别过滤:

<SMTP
        name="mail"
        from="from_email"
        to="to_email"
        subject="APIWebError"
        smtpHost="smtp_host">
    <HtmlLayout locationInfo="true">
        <Pattern>%d{ISO8601} %-5p [%t] %c{1} - %m%ex</Pattern>
    </HtmlLayout>
</SMTP>

4. 确认CXF拦截器行为

CXF的LoggingOutInterceptor仅处理正常响应日志,异常响应在使用ExceptionMapper后不会被它处理,必须依赖ExceptionMapper内部的日志逻辑输出异常。


内容的提问来源于stack exchange,提问作者Diablo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:47:44