2012-07-27 14 views
5

Ich habe Spring MVC-Setup zum Protokollieren von Ausnahmen mit commons Protokollierung, aber feststellen, dass einige Laufzeitausnahmen nicht protokolliert werden.Spring MVC protokolliert nicht alle Ausnahmen

Hier ist meine Bean-Konfiguration für die Standard-Exception-Resolver von der Feder:

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

Antwort

4

Um dies zu erhalten meisten Ausnahmen zu protokollieren, hatte ich die folgende Zeile in meine Config hinzuzufügen:

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

So schließlich wurde es folgendes:

<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 ist described in detail here.

+1

Also, welche Ausnahmen werden mit dieser Methode verpasst, und gibt es eine Möglichkeit, diese zu bekommen? –

+0

Guter Punkt. Ich habe Spring seit langer Zeit nicht mehr benutzt und kann mich nicht erinnern. Ich hätte ein bisschen mehr Info oben enthalten sollen. Meine beste Vermutung an dieser Stelle sind Ausnahmen, die von 'RuntimeException' abgeleitet sind, wie ich oben angedeutet habe. –

3

Um zu erweitern, was @Brad Parks sagte, empfehle ich, dass Sie auch einen HttpServlet-Filter erstellen, der zuerst (und zuletzt) ​​ausgeführt wird, um Ausnahmen zu erfassen, die Spring verpassen wird. Auch, weil es Spring-Code gibt, der wie Spring Security ausfallen kann, und benutzerdefinierte HTTP-Interceptors, die außerhalb des SimpleMappingException-Resolvers liegen (dh wenn das DispatchServlet oder die Interceptors fehlschlagen, erhalten Sie keine Ausnahme).

Hier ist ein Beispielfilter, den ich oben auf dem SimpleMappingExceptionResolver verwende.

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); 

} 

Der Grund, warum ich dies empfehlen ist, dass für die meisten Servlet-Container kann abgefangene Ausnahme oder nicht wahrscheinlich nicht die Logging-Framework protokolliert werden kann (für Tomcat seines Juli).

Der Commons-Protokollzugriffsformatierer protokolliert nur die Anforderung ähnlich Apache-Protokolldateien.

+0

Stimmen Sie voll und ganz mit dieser Antwort überein - ** Spring ** hat eine ** schwerwiegende Einschränkung ** - es kann ** nur ** Fälle von ** Exception Klasse ** behandeln, alle ** Fehler ** Instanzen ** werden blind ignoriert ** und an den Standard-Verarbeitungsstapel gesendet. Um diesen ** Spring deficiency ** zu überwinden, sollte man Filter über den gesamten Stack legen und sicherstellen, dass ** ALLE ** Exceptions ** behandelt werden ** – Yura

1

In meinem Test verwenden SimpleMappingExceptionResolver nicht MissingServletRequestParameterException anmelden können, ich kombiniert @ControllerAdvice und Filter melden Sie sich zu tun.

Verwenden Sie ControllerAdvice, um Throwable im Frühjahr angehoben MVC Controller zu fangen.

@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; 
    } 
} 

Verwenden Filter weitere Ausnahme zu fangen.

@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 Konfiguration

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

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

Sie können my gist für vollständigen Code anzeigen.

Verwandte Themen