1.首先我们需要定义一个全局异常处理类,并且标注上@ControllerAdvice注解:
@ControllerAdvice//声明当前类是全局异常处理类
public class GlobalExceptionAdvice {
@Autowired
private ExceptionCodesConfiguration codesConfiguration;
/**
* 该注解表示一个处理异常的执行器,内部的value表示当前方法处理异常的类型,Exception表示
* 通用异常类型,当前方法不仅仅可以拦截抛出的exception类型,还可以拦截Exception的子类
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
//该注解可以返回自定义的服务器响应的状态码,如果不添加该注解,那么有可能服务器发生异常,但是
//前端收到的响应状态码还是200,这样是不对的
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public UnifyResponse handlerException(HttpServletRequest req,Exception e) {
System.out.println("exception 未知异常");
String method = req.getMethod();
String uri = req.getRequestURI();
System.out.println(e);
/**
* 如果不在Unify类中添加Getter();那么message对象在返回到前端数据时,就得不到需要序列化的
* 对象,所以就会报错
*/
UnifyResponse message = new UnifyResponse(9999,"服务器异常",method+" "+uri);
return message;
}
/**
* 如果同一个异常,同时属于多个异常拦截器的范围内,那么如果第一个拦截器已经拦截并处理了,
* 那么其他的拦截器就不会拦截
* 当前方法是处理已知异常的处理器
*/
@ExceptionHandler(value = HttpException.class)
public ResponseEntity<UnifyResponse> handlerHttpException(HttpServletRequest req, HttpException e) {
System.out.println("httpException");
String method = req.getMethod();
String uri = req.getRequestURI();
System.out.println(e);
/*ResponseEntity不仅可以返回自定义的状态码,还可以返回HttpHeaders(请求头和响应头)
在ResponseEntity中我们需要传入三个参数:(1)UnifyResponse (2)HttpHeaders(3)
*/
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
UnifyResponse message = new UnifyResponse(e.getCode(),codesConfiguration.getMessage(e.getCode()),method+" "+uri);
HttpStatus status = HttpStatus.resolve(e.getHttpStatusCode());
ResponseEntity<UnifyResponse> entity = new ResponseEntity(message,headers,status);
return entity;
}
2.我们需要自定义一个读取配置文件的配置类:
//当前注解表示可以读取到的配置文件,让配置文件与当前类相对应
@PropertySource(value = "classpath:config/exception-code.properties")
//该注解表示当前类与配置文件的哪一个前缀相匹配,然后codes会自动匹配前缀后面的
@ConfigurationProperties(prefix = "lin")
//如果想让当前类与配置文件相对应,那么当前类必须被IOC容器所管理
@Component
public class ExceptionCodesConfiguration {
private Map<Integer,String> codes = new HashMap<>();
/**
* 在项目初始化阶段,如果不加getCodes();那么当前类的codes对象,就不会读取到配置文件中的数据,这个本人还在考虑中
*/
public Map<Integer, String> getCodes() {
return codes;
}
public void setCodes(Map<Integer, String> codes) {
this.codes = codes;
}
/**
* 根据code码,获取配置文件中的异常信息
* @param code 异常信息码
* @return 异常信息
*/
public String getMessage(int code) {
String message = codes.get(code);
System.out.println("查找到的message : "+message);
return message;
}
3.编写测试类:
@GetMapping("/test")
public String test() throws Exception {
kill.r();
//在此处抛出一个继承于HttpException类的异常
throw new NotFoundException(10000);
}
4.结果输出:
{
"code": 10000,
"message": "通用异常",
"request": "GET /v1/banner/test"
}
5.以下为Spring Boot 处理全局异常的流程图: