只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

85487010 2019-08-22

 只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值

在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。

比较通用的返回值格式如下:

  1. public class Result<T> {  
  2.     // 接口调用成功或者失败  
  3.     private Integer code = 0 
  4.     // 失败的具体code  
  5.     private String errorCode = "" 
  6.     // 需要传递的信息,例如错误信息  
  7.     private String msg;  
  8.     // 需要传递的数据  
  9.     private T data;  
  10.     ...  

最原始的接口如下: 

  1. @GetMapping("/test")  
  2.     public User test() {  
  3.         return new User();  
  4.     } 

当我们需要统一返回值时,可能会使用这样一个办法:

  1. @GetMapping("/test")  
  2.   public Result test() {  
  3.       return Result.success(new User());  
  4.   } 

这个方法确实达到了统一接口返回值的目的,但是却有几个新问题诞生了:

  •  接口返回值不明显,不能一眼看出来该接口的返回值。
  •  每一个接口都需要增加额外的代码量。

所幸Spring Boot已经为我们提供了更好的解决办法,只需要在项目中加上以下代码,就可以无感知的为我们统一全局返回值。

  1. /**  
  2.  * 全局返回值统一封装  
  3.  */  
  4. @EnableWebMvc  
  5. @Configuration  
  6. public class GlobalReturnConfig {  
  7.     @RestControllerAdvice  
  8.     static class ResultResponseAdvice implements ResponseBodyAdvice<Object> {  
  9.         @Override  
  10.         public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {  
  11.             return true;  
  12.         }  
  13.         @Override  
  14.         public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { 
  15.              if (body instanceof Result) {  
  16.                 return body;  
  17.             }  
  18.             return new Result(body);  
  19.         }  
  20.     }  

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

而我们的接口只需要写成最原始的样子就行了。

  1. @GetMapping("/test")  
  2.  public User test() {  
  3.      return new User();  
  4.  } 

统一处理异常

将返回值统一封装时我们没有考虑当接口抛出异常的情况。当接口抛出异常时让用户直接看到服务端的异常肯定是不够友好的,而我们也不可能每一个接口都去try/catch进行处理,此时只需要使用@ExceptionHandler注解即可无感知的全局统一处理异常。

  1. @RestControllerAdvice  
  2. public class GlobalExceptionHandler {  
  3.     private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);  
  4.     /**  
  5.      * 全局异常处理  
  6.      */  
  7.     @ExceptionHandler  
  8.     public JsonData handleException(HttpServletRequest request, HttpServletResponse response, final Exception e) {  
  9.         LOG.error(e.getMessage(), e);  
  10.         if (e instanceof AlertException) {//可以在前端Alert的异常  
  11.             if (((AlertException) e).getRetCode() != null) {//预定义异常  
  12.                 return new Result(((AlertException) e).getRetCode());  
  13.             } else {  
  14.                 return new Result(1, e.getMessage() != null ? e.getMessage() : "");  
  15.             }  
  16.         } else {//其它异常  
  17.             if (Util.isProduct()) {//如果是正式环境,统一提示  
  18.                 return new Result(RetCode.ERROR);  
  19.             } else {//测试环境,alert异常信息 
  20.                  return new Result(1, StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : e.toString());  
  21.             }  
  22.         }  
  23.     }  

相关推荐

victorzhzh / 0评论 2014-08-24