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 处理全局异常的流程图:

springboot全局处理响应数据 springboot全局异常处理service层_System