OncePerRequestFilter - 处理使用@ResponseStatus

时间:2018-06-10 09:33:35

标签: spring spring-boot servlets servlet-filters spring-restcontroller

我正在寻找一种方法来记录数据库中的所有请求和响应(1记录= 1请求+ 1响应)。 我的用例详见:

  1. 使用请求URL,参数,IP,开始日期等记录数据库中的记录。
  2. 更新数据库记录(请求完成时)并保存响应, 例外,结束日期等。
  3. 我尝试使用自定义的OncePerRequestFilter,它的工作几乎没问题。但是我在处理带注释@ResponseStatus注释的异常时遇到问题。这种异常(抛出控制器)我无法在我的自定义doFilter方法中捕获。你知道在过滤器中捕获这些异常的方法吗?除非我以其他方式做到这一点?

    AuditFilter:

    @Component
    public class AuditFilter extends OncePerRequestFilter {
    
        private Logger logger = Logger.getLogger(AuditFilter.class.getName());
        private RequestAuditRepository repository;
    
    
        AuditFilter(RequestAuditRepository repository) {
            this.repository = repository;
        }
    
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            doFilterWrapped(wrapRequest(request), wrapResponse(response), filterChain);
        }
    
        private void doFilterWrapped(ContentCachingRequestWrapper request, ContentCachingResponseWrapper response, FilterChain filterChain)
                throws ServletException, IOException {
    
            RequestAuditLog requestAuditLog = new RequestAuditLog();
            String catchedExceptionMsg = null;
            try {
                beforeRequest(requestAuditLog, request); 
                filterChain.doFilter(request, response);
            }
            catch (Exception e) {
                // Not called when exception with @ResponStatus annotation throwed
                catchedExceptionMsg = e.getMessage();
                throw e;
            }
            finally {
                afterRequest(requestAuditLog, catchedExceptionMsg, request, response);
                response.copyBodyToResponse();
            }
        }
    
        ...
    
    }
    

    BadRequestException:

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public class BadRequestException extends RuntimeException {
        public BadRequestException(String message) {
            super(message);
        }
    }
    

1 个答案:

答案 0 :(得分:1)

我认为BadRequestException甚至在触发自定义过滤器之前就已处理,因此您无法在过滤器中捕获此异常。

您可以做的是,除了在过滤器中编写自己的ExceptionHandler,然后在其中记录内容。

@ControllerAdvice
public class MyExceptionHandler {

  @ExceptionHandler(BadRequestException.class)
  public void handleError(BadRequestException ex) {
     // do your stuff here
  }

}