Spring Boot拦截所有异常处理程序

时间:2018-02-14 11:16:42

标签: java spring spring-mvc spring-boot

我正在尝试执行一些适用于代码中所有HandlerInterceptor的常用逻辑。我知道我可以写一个{{1}}来拦截快乐的道路。但我想挂钩异常处理生命周期,以便在呈现错误响应之前执行一些常见的逻辑,例如日志记录。

有没有在Spring Boot / Spring MVC中执行此操作?我想尽可能避免为此目的编写servlet过滤器。

3 个答案:

答案 0 :(得分:3)

@RestControllerAdvice@ExceptionHandler有一种方法,例如:

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(value = {DeniedPermissionException.class})
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public String deniedPermissionException(DeniedPermissionException ex) {
        return "Denied permission";
    }

    @ExceptionHandler(value = {ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String constraintViolationException(ConstraintViolationException ex) {
        return "Bad request";
    }

    @ExceptionHandler(value = {Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String internalServerError(Exception ex) {
         return "Internal error";
    }
}

* DeniedPermissionException是自定义例外。

答案 1 :(得分:2)

我有一个解决方案。它是关于使用HandlerInterceptor.afterCompletion方法的。但是,documentation of this method中有一行说明:

  

注意:只有在此拦截器的preHandle方法成功完成并返回true时才会被调用!

所以诀窍是实现preHandle并让它返回true

现在我的拦截器看起来像这样:

@Component
public class MyInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // perform common logic here
    }
}

有一件事需要注意的是,如果你有一个拦截器链和一个拦截器,在此之前抛出异常,这个拦截器就没有机会执行。因此,如果我们重新排序拦截器链以使MyInterceptor位于顶部,它将拦截所有请求。

答案 2 :(得分:0)

这并不是Spring Boot真正关心的问题。这确实是Spring MVC的关注点。一种好的方法是实现HandlerExceptionResolver或从ExceptionHandlerExceptionResolver之类的东西扩展。与默认异常解析器(所有解析器均以最低优先级运行)相比,需要为实现提供更高的优先级。而且,如果您想保留默认解析器的现有行为,而仅捕获诸如日志记录或跟踪之类的交叉操作的异常,则只需为ModelAndView返回null,Spring将确保像以前一样调用其他默认解析器