2012-07-27 11 views
5

Ho l'installazione di Spring MVC per registrare le eccezioni utilizzando la registrazione di comuni, ma trovo che alcune eccezioni di runtime non vengono registrate.Spring MVC non registra tutte le eccezioni

Ecco la mia configurazione di fagioli per il resolver eccezione predefinito fornito da primavera:

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

risposta

4

per ottenere questo per accedere maggior parte eccezioni, ho dovuto aggiungere la seguente riga al mio config:

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

Quindi in ultima analisi, è diventato il seguente:

<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

Quindi, quali eccezioni andranno perse con questo metodo e c'è un modo per ottenerle? –

+0

Buon punto. Non ho usato la primavera ora da molto tempo e non ricordo. Avrei dovuto aggiungere qualche informazione in più sopra. La mia ipotesi migliore a questo punto sono le eccezioni derivate da 'RuntimeException', come ho suggerito sopra. –

3

Per aumentare quello che @Brad Parks ha detto, raccomando di creare anche un filtro HttpServlet che verrà eseguito per primo (e terminerà per ultimo) per rilevare le eccezioni che Spring mancherà. Anche perché esiste un codice Spring che può fallire come Spring Security e Http Interceptor personalizzati che non rientrano nel SimpleMappingException Resolver (cioè se DispatchServlet o Interceptors falliscono non si ottiene l'eccezione).

Ecco un filtro di esempio che uso sopra 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); 

} 

La ragione per cui vi consiglio questo è che per la maggior parte servlet container eccezione non rilevata può o non può essere registrato con probabilmente non il vostro quadro di registrazione (per Tomcat sua JULI).

Il programma di formattazione dell'accesso ai registri comuni registra solo la richiesta simile ai file di registro di Apache.

+0

Totalmente d'accordo con questa risposta - ** Spring ** ha una ** limitazione seria ** - può gestire ** solo ** istanze di ** Classe di eccezione **, tutte le ** istanze di ** Errore ** vengono ignorate ciecamente ** e inviato allo stack di elaborazione standard. Quindi, per ovviare a questo ** deficienza di primavera ** si dovrebbe aggiungere il filtro in cima all'intero stack e assicurarsi che ** TUTTE ** le eccezioni ** siano gestite ** – Yura

1

Nella mia prova, utilizzare SimpleMappingExceptionResolver non può accedere MissingServletRequestParameterException, ho combinato @ControllerAdvice e Filter di fare il login.

Utilizzare ControllerAdvice per prendere Throwable sollevato in Spring MVC Controller.

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

Usa Filter per catturare ulteriore eccezione.

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

    ...... 
} 

configurazione logback

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

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

È possibile visualizzare my gist per il codice completo.

Problemi correlati