在实际开发中并不会为每个异常做单独的处理,而是在出现异常时直接抛出,然后由异常统一处理响应json到响应体当中。本文以上文《拦截器的简单实用(登录拦截器)》为例,采用 @ControllerAdvice注解 记录异常统一处理的使用方法。
涉及的注解:@ControllerAdvice @ExceptionHandler()
为什么要使用异常统一处理
在前后端分离的项目中,如果出现异常我们依然希望能够响应一个json字符串,在字符串内给出异常代码和提示信息等。在前后端不分离的项目中,如果出现异常我们也希望能让页面跳转到错误页,而不是直接抛出异常代码。因此我们需要采用异常统一处理来实现,SpringBoot中异常统一处理也是使用SpringMVC的方案。
异常统一处理的方案
异常统一处理有两个方案,一个是:实现HandlerExceptionResolver接口,另一个是:使用@ControllerAdvice 注解。第一个方案大多用于模板引擎开发中,对于前后端分离的场景我们采用“@ControllerAdvice 注解”方案,来实现异常统一处理。
@ControllerAdvice 注解方案的使用
- 创建异常处理类,类上加入
@ControllerAdvice
注解; - 定义异常处理方法,方法上加入
@ExceptionHandler()
注解,注解属性中指定可以处理的异常 - 方法内进行异常统一处理
(代码示例:异常处理类)1
2
3
4
5
6
7
8
9
10
11
12
13// 标记异常处理类
public class MyControllerAdvice {
// 放入响应体
// 放入响应体
public ResponseResult handlerException(Exception e){
//获取异常信息,存入ResponseResult的msg属性
String msg = e.getMessage();
ResponseResult result = new ResponseResult(300,msg);
//把ResponseResult对象作为返回值返回,要求转化成json存入响应体
return result;
}
} - 在出现异常的地方使用的
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
public class LoginInterceptor implements HandlerInterceptor {
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
放入响应体。