2012-07-27 9 views
5

Commonsのログを使用して例外を記録するSpring MVCセットアップがありますが、実行時の例外が記録されていないことがわかります。Spring MVCがすべての例外をログに記録しない

ここに私のBean構成は、スプリングによって提供されているデフォルトの例外リゾルバのためです:

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

答えて

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はdescribed in detail hereです。

+1

このメソッドを使用すると、どのような例外が見逃されるのですか。それらを取得する方法はありますか? –

+0

良い点。私は長い間、春を今使っておらず、覚えていません。私は上記のもう少し詳しい情報を含める必要があります。私が上で暗示したように、この時点での私の最高の推測は 'RuntimeException'から派生した例外です。 –

3

@Brad Parksが言ったことを増強するには、Springが見逃している例外をキャッチするために、最初に(最後に終了する)HttpServlet Filterを作成することをお勧めします。 Spring SecurityやSimpleMappingExceptionリゾルバの外にあるカスタムHttpインターセプタのように失敗するSpringコード(DispatchServletやInterceptorsが失敗した場合は例外を取得しない)があるためです。

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そのための)は、おそらくないあなたのロギングフレームワークをログに記録してもしなくてもよいということです。

commons log access formatterは、Apacheログファイルと同様の要求をログに記録します。私のテストで

+0

完全にこの回答に同意します - ** Spring **は**重大な制限を持っています** - **例外クラス**のインスタンスのみを処理できます**すべて** Error **インスタンス**は盲目的に無視されます**標準処理スタックに送信されます。だから、これを克服するために**春の欠点**は、スタック全体の上にFilterを追加し、** ALL **例外**が処理されることを確認する必要があります** – Yura

1

SimpleMappingExceptionResolverMissingServletRequestParameterExceptionをログに記録することはできません使用して、私はログを行うには@ControllerAdviceFilterを組み合わせます。

ControllerAdviceを使用して、Spring MVCコントローラで発生した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; 
     } 
    } 

    ...... 
} 

logback設定

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

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

あなたは完全なコードのためmy gistを表示することができます。

関連する問題