Spring boot集中异常处理方法实例

来自:互联网
时间:2020-05-26
阅读:
免费资源网 - https://freexyz.cn/

集中异常处理

以下代码可在github获取:https://github.com/Syske/learning-dome-code/tree/master/springboot-learning

方式一:ExceptionHandle

定义自己的异常类型,根据不同类型做不同处理,比如我定义的MyException:

public class MyException extends RuntimeException {
  public MyException(String msg) {
    super(msg);
  }
}

然后通过MyExceptionHandle处理该异常,需要注意的是异常不能在filter中抛出,抛出也没法捕获

	
@RestControllerAdvice
public class MyExceptionHandle {
 
  @ExceptionHandler(MyException.class)
  public Result exceptionHandle(MyException e) {
    return Result.getFailed( "system error:MyException" + e.getMessage());
  }
}

在controller、service以及拦截器的预处理方法中都可以完美捕获,这里特殊说下拦截器:

	
public class MyInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    //throw new MyException("拦截器错误:MyInterceptor");
    // 这里的异常会完美捕获,并返回
    return true;
  }
 
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    throw new MyException("拦截器错误:MyInterceptor");
    /** 能捕获异常信息并返回给客户端,但并不会覆盖已经请求成功的返回结果,但会包含在返回结果中,比如我的返回结果:
     {"code":1,"success":true,"msg":"请求成功","result":true}{"code":0,"success":false,"msg":"system error:MyException拦截器错误:MyInterceptor","result":null}
     */
  }
 
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    throw new MyException("拦截器错误:MyInterceptor");
    // 这里抛出的异常并不能被捕获,会直接在后台抛出,相当于回掉函数,请求结果已经返回
  }
}

上面的解释已经够清楚了,就不做过多说明了。刚刚我们说了,上面的这种方式,对于filter是不起作用的,下面我们说的这种方式,主要就是针对filter来说的

方式二:ExceptionFilter

定义一个controller,请求路径可以自己指定,比如/error/exthrow:

	
@Controller
public class ExceptionController {
 
  @RequestMapping("/error/exthrow")
  public void rethrow(HttpServletRequest request) throws Exception {
    throw ((Exception) request.getAttribute("filter.error"));
  }
}

再定义一个异常拦截器,在需要抛出异常的拦截器中直接抛出异常,然后在异常拦截器中try-catch,发生异常时直接转发至前面定义的异常controller,这里需要注意的是,如果你的filter是实现Filter或者继承OncePerRequestFilter,那你不需要任何处理,直接request.setAttribute("filter.error", e)就可以了。

由于我把自己的filter交给shiro管理,而且是继承BasicHttpAuthenticationFilter的,不知到什么原因,直接catch到的异常类型是ServletException,为了拿到真正的异常信息,我需要通过getCause()方法获取filter中抛出的异常。因为controller抛出的异常最后还是会交给我们定义的MyExceptionHandle去处理,如果获取到的异常不是我们自定义的异常或者他的子类的话,就会返回500错误(在这个示例前,我以为所有的filter都是这样的,后来实践后发现并不是这样

免费资源网 - https://freexyz.cn/
返回顶部
顶部