2012-07-27 29 views
5

Tôi có cài đặt Spring MVC để ghi nhật ký ngoại lệ bằng cách sử dụng tính năng ghi nhật ký, nhưng thấy rằng một số ngoại lệ thời gian chạy không được ghi nhật ký.Spring MVC không ghi lại tất cả ngoại lệ

Dưới đây là cấu hình đậu của tôi cho resolver ngoại lệ mặc định được cung cấp bởi mùa xuân:

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

Trả lời

4

Để có được điều này để đăng nhập nhất trường hợp ngoại lệ, tôi đã có thêm dòng sau vào cấu hình của tôi:

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

Vì vậy, cuối cùng nó đã trở thành như sau:

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

+1

Vì vậy, những ngoại lệ nào sẽ bị bỏ qua khi sử dụng phương pháp này và có cách nào để nhận những thứ đó không? –

+0

Điểm tốt. Tôi đã không sử dụng mùa xuân bây giờ trong một thời gian dài và không thể nhớ. Tôi nên có thêm một chút thông tin ở trên. Đoán tốt nhất của tôi vào thời điểm này là ngoại lệ bắt nguồn từ 'RuntimeException', như tôi đã nói ở trên. –

3

Để tăng thêm những gì @Brad Parks nói tôi khuyên bạn cũng nên tạo Bộ lọc HttpServlet sẽ chạy trước (và kết thúc cuối cùng) để bắt ngoại lệ mà Spring sẽ bỏ lỡ. Cũng bởi vì có mã Spring có thể không thành công như Spring Security và các Interceptor HTTP tùy chỉnh nằm ngoài SimpleMappingException Resolver (tức là nếu DispatchServlet hoặc Interceptor thất bại thì bạn sẽ không nhận được ngoại lệ).

Dưới đây là một bộ lọc mẫu mà tôi sử dụng trên đầu trang 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); 

} 

Lý do tôi khuyên bạn nên dùng cho hầu hết các thùng chứa servlet không có ngoại lệ có thể hoặc không thể đăng nhập có thể không phải khung đăng nhập của bạn (đối với Tomcat JULI).

Trình định dạng truy cập nhật ký commons chỉ ghi nhật ký yêu cầu tương tự như tệp nhật ký Apache.

+0

Hoàn toàn đồng ý với câu trả lời này - ** Mùa xuân ** có một ** giới hạn nghiêm trọng ** - nó có thể xử lý ** chỉ ** trường hợp của ** Loại ngoại lệ **, tất cả ** Lỗi ** trường hợp ** bị bỏ qua một cách mù quáng ** và được gửi tới ngăn xếp xử lý chuẩn. Vì vậy, để khắc phục điều này ** Thiếu mùa xuân ** người ta nên thêm Bộ lọc lên trên toàn bộ ngăn xếp và chắc chắn rằng ** TẤT CẢ ** ngoại lệ ** được xử lý ** – Yura

1

Trong thử nghiệm của tôi, sử dụng SimpleMappingExceptionResolver không thể đăng nhập MissingServletRequestParameterException, tôi kết hợp @ControllerAdviceFilter để làm đăng nhập.

Sử dụng ControllerAdvice để bắt Được tăng lên trong Bộ điều khiển MVC Spring.

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

Sử dụng Filter để bắt ngoại lệ bổ sung.

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

    ...... 
} 

cấu hình logback

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

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

Bạn có thể xem my gist cho mã đầy đủ.

Các vấn đề liên quan