Spring Boot intercept all exception handlers

早过忘川 提交于 2020-05-26 19:19:30

问题


I am trying to perform some common logic that applies to all my @ExceptionHandlers in code. I know I can write a HandlerInterceptor to intercept happy paths. But I would like to hook into the exception handling lifecycle so that I can execute some common logic such as logging, before the error response is rendered.

Is there anyway to do this in Spring Boot / Spring MVC? I would like to avoid having to write a servlet filter for this purpose if possible.


回答1:


There is a way with @RestControllerAdvice and @ExceptionHandler, an example:

@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 is a custom exception.




回答2:


I have a solution. It's about using HandlerInterceptor.afterCompletion method. However, there is a line in the documentation of this method that states that:

Note: Will only be called if this interceptor's preHandle method has successfully completed and returned true!

So the trick is to also implement the preHandle and make it return true.

Now my interceptor looks like this:

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

One thing to be aware of though is that if you have a chain of interceptors and an interceptor before this one throws an exception, this interceptor won't get a chance to execute. So if we reorder the interceptor chain so that MyInterceptor is right at the top, it will intercept all requests.




回答3:


This is not really a Spring Boot concern. This is really a Spring MVC concern. One good approach is to implement the HandlerExceptionResolver or extend from something like ExceptionHandlerExceptionResolver. The implementation needs to be given a higher precedence than the default exception resolvers (which all run with the lowest precedence). And if you want to retain the existing behavior of the default resolvers but only trap the exception for something cross-cutting like logging or tracking, then just return null for the ModelAndView and Spring will ensure other default resolvers are invoked as before.



来源:https://stackoverflow.com/questions/48785878/spring-boot-intercept-all-exception-handlers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!