为了程序返回数据友好,返回给前端的数据信息是可读的,往往会考虑将异常进行封装或者组织为结构化返回。

基于 Spring Boot 体系,原本已经提供了一些方式实现,我们今天主要聊的也是基于 Spring Boot 去解决上述问题。

@ExceptionHandler

@ExceptionHandler 可以作为统一拦截异常方式,对于指定的异常按照你想的方式自由组装返回的数据信息和结构。自由度很高,这里需要注意的一点,往往大家会在这里就直接通过response对象返回响应结果,从而导致ResponseBodyAdvice、HandlerInterceptor之类的后续处理不再触发。 所以在使用该方式时,尽可能不直接使用response.write方式返回,而是使用统一的数据结构作为处理返回值。

// 推荐
    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public Resp<Void> onBadMethodArgumentTypeMismatchException(ConstraintViolationException e) {
        return Resp.badRequest(e.getConstraintViolations().stream().findFirst().get().getMessage());
    }
// 不推荐
    @ExceptionHandler(Exception.class)
    public void exception(Exception e, HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        log.error("系统异常:", e);
        response.getWriter().write($.json.toJsonString(Resp.customize(RpcResult.SERVER_ERROR, "服务器异常,请稍后再试"));
    }

ErrorController

Spring Boot 在发生异常的时候,如果没有异常捕捉器存在,会默认调用/error接口(可以通过server.error.path修改),类似写接口一样,对异常进行捕捉处理。

该方式优先级上会弱一点,但也是一种好方式,还可以自己实现通过配置方式处理异常,可以参考:Dew

课外拓展

执行优先级说明

1、HandlerInterceptor.preHandle()

2、 业务方法

3、@ExceptionHandler

4、ResponseBodyAdvice.supports()

5、ResponseBodyAdvice.beforeBodyWrite()

6、HandlerInterceptor.postHandle()

7、HandlerInterceptor.afterCompletion()

迹_Jason
1k 声望65 粉丝

feeling主义者,追求极致的简约,创造最好的用户体验