0%

异常统一处理

在实际开发中并不会为每个异常做单独的处理,而是在出现异常时直接抛出,然后由异常统一处理响应json到响应体当中。本文以上文《拦截器的简单实用(登录拦截器)》为例,采用 @ControllerAdvice注解 记录异常统一处理的使用方法。
涉及的注解:@ControllerAdvice @ExceptionHandler()

为什么要使用异常统一处理

在前后端分离的项目中,如果出现异常我们依然希望能够响应一个json字符串,在字符串内给出异常代码和提示信息等。在前后端不分离的项目中,如果出现异常我们也希望能让页面跳转到错误页,而不是直接抛出异常代码。因此我们需要采用异常统一处理来实现,SpringBoot中异常统一处理也是使用SpringMVC的方案。

异常统一处理的方案

异常统一处理有两个方案,一个是:实现HandlerExceptionResolver接口,另一个是:使用@ControllerAdvice 注解。第一个方案大多用于模板引擎开发中,对于前后端分离的场景我们采用“@ControllerAdvice 注解”方案,来实现异常统一处理。

@ControllerAdvice 注解方案的使用

  1. 创建异常处理类,类上加入 @ControllerAdvice 注解;
  2. 定义异常处理方法,方法上加入 @ExceptionHandler() 注解,注解属性中指定可以处理的异常
  3. 方法内进行异常统一处理
    (代码示例:异常处理类)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @ControllerAdvice // 标记异常处理类
    public class MyControllerAdvice {

    @ResponseBody // 放入响应体
    @ExceptionHandler(RuntimeException.class) // 放入响应体
    public ResponseResult handlerException(Exception e){
    //获取异常信息,存入ResponseResult的msg属性
    String msg = e.getMessage();
    ResponseResult result = new ResponseResult(300,msg);
    //把ResponseResult对象作为返回值返回,要求转化成json存入响应体
    return result;
    }
    }
  4. 在出现异常的地方使用的throw方法+匿名内部类 抛出指定异常类型对象
    (代码示例:拦截器类)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    @Component
    public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //获取请求头中的token
    String token = request.getHeader("token");
    //判断token是否为空,如果为空也代表未登录 提醒重新登录
    if(!StringUtils.hasText(token)){
    //// 我们通过异常统一处理,直接抛出异常类对象 response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    throw new RuntimeException("未登录");
    }
    //解析token看看是否成功
    try {
    Claims claims = JwtUtil.parseJWT(token);
    String subject = claims.getSubject();
    System.out.println(subject);
    } catch (Exception e) {
    e.printStackTrace();
    //如果解析过程中出现了异常,说明未登录,提醒重新登录(401)
    //// 我们通过异常统一处理,直接抛出异常
    throw new RuntimeException("未登录");
    }
    return true;
    }
    }

Tip:异常处理方法的返回值类型是自定义的。实际使用,可以将方法的返回值类型定义为ResponeResult(相应格式统一),并加上@ResponeBody放入响应体