在Spring Boot 中,实现全局异常处理的整体流程:
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 处理全局异常的流程图: