6

コモンズロギングを使用して例外をログに記録するようにSpringMVCを設定していますが、一部のランタイム例外がログに記録されていないことがわかりました。

Springが提供するデフォルトの例外リゾルバーのBean構成は次のとおりです。

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">error</prop>
        </props>
    </property>
</bean>
4

3 に答える 3

4

これでほとんどの例外をログに記録するには、構成に次の行を追加する必要がありました。

    <property name="warnLogCategory" value="someCategoryStringYouMakeUp" />

したがって、最終的には次のようになりました。

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="warnLogCategory" value="apperror" />
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">error</prop>
        </props>
    </property>
</bean>

warnLogCategoryについて詳しくは、こちらをご覧ください

于 2012-07-27T17:25:41.153 に答える
3

@Brad Parksが言ったことを補強するために、Springが見逃す例外をキャッチするために、最初に実行される(そして最後に終了する)HttpServletフィルターも作成することをお勧めします。また、SpringSecurityやSimpleMappingExceptionResolverの範囲外にあるカスタムHttpインターセプターのように失敗する可能性のあるSpringコードがあるため(つまり、DispatchServletまたはインターセプターが失敗した場合でも例外は発生しません)。

SimpleMappingExceptionResolverの上で使用するフィルターの例を次に示します。

public class ExceptionLoggerServletFilter implements Filter {

    private CommonAccessLogFormatter requestFormat = new CommonAccessLogFormatter();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            StringBuilder sb = new StringBuilder("Very Bad shit has happened:");
            if (request instanceof HttpServletRequest)
                requestFormat.appendLogEntry((HttpServletRequest) request, sb);
            log.fatal(sb.toString(), e);
            throw new ServletException(e);
        }
    }

    @Override
    public void destroy() {
    }


    private static final Logger log = Logger.getLogger(ExceptionLoggerServletFilter.class);

}

私がこれをお勧めする理由は、ほとんどのサーブレットコンテナでは、キャッチされない例外が、おそらくログフレームワーク(Tomcatの場合はJULI)ではログに記録されない場合があるためです。

コモンズログアクセスフォーマッタは、Apacheログファイルと同様にリクエストをログに記録します。

于 2012-07-27T17:32:29.090 に答える
2

私のテストでは、SimpleMappingExceptionResolverログを作成できません。MissingServletRequestParameterException組み合わせ@ControllerAdviceFilterログを作成します。

ControllerAdviceSpringMVCコントローラーで発生したThrowableをキャッチするために使用します。

@ControllerAdvice
public class GlobalDefaultExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger("global_controller_exception_logger");

    @ExceptionHandler(value = Throwable.class)
    public void defaultErrorHandler(Throwable e) throws Throwable {
        // If the exception is annotated with @ResponseStatus rethrow it and let
        // the framework handle it.
        // AnnotationUtils is a Spring Framework utility class.
        if (AnnotationUtils.findAnnotation
                (e.getClass(), ResponseStatus.class) != null) {
            throw e;
        }

        // Otherwise log exception
        logger.error("global controller default exception handler", e);
        throw e;
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public void httpBadRequest(Exception e, HttpServletRequest request) throws Exception {
        StringBuffer requestURL = request.getRequestURL();
        logger.warn("{}   HTTP Status 400 - {}", requestURL, e.getMessage());
        throw e;
    }
}

Filter追加の例外をキャッチするために使用します。

@WebFilter(
        filterName = "ExceptionLogFilter",
        urlPatterns = "/*",
        dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR}
)
public class ExceptionLogFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger("global_filter_exception_logger");


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (IOException | ServletException e) {
            logger.error("bad thing happened during doFilter", e);
            throw e;
        }
    }

    ......
}

ログバック構成

<logger name="global_controller_exception_logger" level="info"/>

<logger name="global_filter_exception_logger" level="info"/>

あなたは完全なコードのために私の要点を見ることができます。

于 2017-02-10T14:39:15.277 に答える