2012-07-27 18 views
5

Tengo la instalación de Spring MVC para registrar excepciones mediante el registro de commons, pero creo que algunas excepciones de tiempo de ejecución no se registran.Spring MVC no registra todas las excepciones

Aquí está mi configuración de frijol para la resolución de excepción por defecto proporcionada por el resorte:

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

Respuesta

4

para conseguir que esto ingrese la mayoría de excepciones, he tenido que añadir la siguiente línea a mi config:

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

Así que en última instancia se convirtió en lo siguiente:

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

+1

Entonces, ¿qué excepciones se perderán al usar este método, y hay alguna forma de obtenerlas? –

+0

Buen punto. No he usado Spring ahora en mucho tiempo y no puedo recordar. Debería haber incluido un poco más de información arriba. Mi mejor conjetura en este punto son las excepciones derivadas de 'RuntimeException', como indiqué anteriormente. –

3

Para aumentar lo que @Brad Parks dijo, le recomiendo que también haga un filtro HttpServlet que se ejecutará primero (y finalizará el último) para detectar las excepciones que Spring perderá. También porque hay un código Spring que puede fallar como Spring Security y Http Interceptors personalizados que quedan fuera del SimpleMappingException Resolver (es decir, si el DispatchServlet o Interceptor falla, no obtendrá la excepción).

Aquí hay un filtro de ejemplo que utilizo en la parte superior de 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 razón por la que recomiendo esto es que para la mayoría de contenedores de servlets excepción no detectada puede o no puede iniciar sesión con probablemente no su marco de registro (para Tomcat su JULI).

El formateador de acceso de registro común simplemente registra la solicitud similar a los archivos de registro de Apache.

+0

Totalmente de acuerdo con esta respuesta - ** Spring ** tiene una ** seria limitación ** - puede manejar ** solo ** instancias de ** Exception class **, todas las ** ** instancias ** de error son ignoradas a ciegas ** y enviado a la pila de procesamiento estándar. Por lo tanto, para superar esta ** deficiencia de Spring **, se debe agregar Filter en la parte superior de la pila y asegurarse de que se manejan ** ALL ** excepciones ** – Yura

1

En mi prueba, utilice SimpleMappingExceptionResolver no pueden iniciar sesión MissingServletRequestParameterException, que combinan @ControllerAdvice y Filter hacer log.

Use ControllerAdvice para capturar Throwable raised 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; 
    } 
} 

Uso Filter para coger excepción adicional.

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

    ...... 
} 

configuración logback

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

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

Puede ver my gist de código completo.

Cuestiones relacionadas