spring boot 统一JSON格式的接口返回结果的实现

下面我来详细讲解一下“Spring Boot 统一 JSON 格式的接口返回结果的实现”攻略。

下面我来详细讲解一下“Spring Boot 统一 JSON 格式的接口返回结果的实现”攻略。

1. 前言

在实际的项目中,我们往往需要为每个接口编写返回数据的格式,这样很浪费时间。而使用统一的 JSON 返回格式,不仅可以减少代码量,还能让前端开发更加便捷。本文将明确探讨在 Spring Boot 中如何实现这一目标。

2. 统一 JSON 格式的接口返回结果的实现

我们可以通过使用 Spring Boot 提供的拦截器、自定义注解、统一异常处理等来实现统一 JSON 格式的接口返回结果。下面分别介绍这三种方式的实现方法。

2.1 使用拦截器

我们可以通过编写拦截器,在接口调用完毕后修改返回的 JSON 格式。具体实现步骤如下:

  1. 创建一个拦截器类,实现 HandlerInterceptor 接口,并在 afterCompletion 方法中对返回结果进行处理,将其封装成统一 JSON 格式。

```java
@Component
public class ResponseHandlerInterceptor implements HandlerInterceptor {

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                               Exception ex) throws Exception {
       if (ex != null) {
           // 异常不处理
           return;
       }
       if (handler instanceof HandlerMethod) {
           HandlerMethod handlerMethod = (HandlerMethod) handler;
           // 获取方法上的注解
           ApiResult apiResult = handlerMethod.getMethod().getAnnotation(ApiResult.class);

           if (apiResult != null) {
               // 获取返回值的类型
               Class<?> returnType = handlerMethod.getReturnType().getParameterType();
               // 判断是否是统一返回格式要求的类型
               if (!ApiResultVO.class.isAssignableFrom(returnType)) {
                   return;
               }
               // 强制类型转换
               ApiResultVO<Object> apiResultVO = (ApiResultVO<Object>) response.getBody();
               // 重新封装
               JsonResult<Object> jsonResult = new JsonResult<>();
               jsonResult.setCode(apiResultVO.getCode());
               jsonResult.setData(apiResultVO.getData());
               jsonResult.setMsg(apiResultVO.getMsg());
               response.setContentType(MediaType.APPLICATION_JSON_VALUE);
               response.setCharacterEncoding(StandardCharsets.UTF_8.name());
               response.getWriter().write(JsonUtils.toJson(jsonResult));
           }
       }
   }

}
```

  1. 创建一个注解 ApiResult,标记需要统一 JSON 格式返回结果的方法。

java
/**
* ApiResult 注解,标记需要统一 JSON 格式返回结果的方法
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiResult {
}

  1. 注册拦截器,放行操作

```java
@Configuration
public class ResponseHandlerConfig implements WebMvcConfigurer {

   @Autowired
   private ResponseHandlerInterceptor responseHandlerInterceptor;

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(responseHandlerInterceptor).addPathPatterns("/**");
   }

   @Override
   public void addCorsMappings(CorsRegistry registry) {
       registry.addMapping("/**")
               .allowedOrigins("*")
               .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
               .allowCredentials(false).maxAge(3600);
   }

}
```

  1. 在需要统一 JSON 格式返回结果的方法上加上 @ApiResult 注解即可。

java
/**
* 测试需要统一 JSON 格式返回结果的方法
* @return 返回 JSON 格式的数据
*/
@ApiResult
@GetMapping("/testJson")
public ApiResultVO<String> testJson() {
return ApiResultVO.success("测试成功");
}

2.2 使用自定义注解

我们可以通过自定义注解来实现简化操作。具体实现步骤如下:

  1. 创建一个注解 JsonResultFormat,标记需要统一 JSON 格式返回结果的类或方法。

java
/**
* JsonResultFormat 注解,标记需要统一 JSON 格式返回结果的类或方法
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonResultFormat {
}

  1. 创建一个拦截器类 JsonResultInterceptor,在接口调用完毕后修改返回的 JSON 格式。

```java
@Component
public class JsonResultInterceptor implements HandlerInterceptor {

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                               Exception ex) throws Exception {
       if (ex != null) {
           // 异常不处理
           return;
       }

       if (handler instanceof HandlerMethod) {
           HandlerMethod handlerMethod = (HandlerMethod) handler;
           Class<?> beanType = handlerMethod.getBeanType();
           JsonResultFormat jsonResultFormat = beanType.getAnnotation(JsonResultFormat.class);
           if (jsonResultFormat == null) {
               jsonResultFormat = handlerMethod.getMethodAnnotation(JsonResultFormat.class);
           }

           if (jsonResultFormat != null) {
               // 获取返回值的类型
               Class<?> returnType = handlerMethod.getReturnType().getParameterType();
               // 判断是否是统一返回格式要求的类型
               if (!ApiResultVO.class.isAssignableFrom(returnType)) {
                   return;
               }
               // 强制类型转换
               ApiResultVO<Object> apiResultVO = (ApiResultVO<Object>) response.getBody();
               // 重新封装
               JsonResult<Object> jsonResult = new JsonResult<>();
               jsonResult.setCode(apiResultVO.getCode());
               jsonResult.setData(apiResultVO.getData());
               jsonResult.setMsg(apiResultVO.getMsg());
               response.setContentType(MediaType.APPLICATION_JSON_VALUE);
               response.setCharacterEncoding(StandardCharsets.UTF_8.name());
               response.getWriter().write(JsonUtils.toJson(jsonResult));
           }
       }
   }

}
```

  1. 注册拦截器

```java
@Configuration
public class JsonResultInterceptorConfig implements WebMvcConfigurer {

   @Autowired
   private JsonResultInterceptor jsonResultInterceptor;

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(jsonResultInterceptor).addPathPatterns("/**");
   }

   @Override
   public void addCorsMappings(CorsRegistry registry) {
       registry.addMapping("/**")
               .allowedOrigins("*")
               .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
               .allowCredentials(false).maxAge(3600);
   }

}
```

  1. 在需要统一 JSON 格式返回结果的方法上加上 @JsonResultFormat 注解即可。

java
/**
* 测试需要统一 JSON 格式返回结果的方法
* @return 返回 JSON 格式的数据
*/
@JsonResultFormat
@GetMapping("/testJson")
public ApiResultVO<String> testJson() {
return ApiResultVO.success("测试成功");
}

2.3 统一异常处理

在项目中,统一异常处理也是非常重要的,我们可以在统一异常处理时,将异常信息封装成统一的 JSON 格式返回给前端。

首先,我们需要自定义一个异常类 JsonException,继承 RuntimeException,并添加需要的属性。

/**
* 统一 JSON 格式异常类
*/
public class JsonException extends RuntimeException {

   /**
    * 状态码
    */
   private Integer code;

   /**
    * 返回消息
    */
   private String msg;

   /**
    * 异常信息
    */
   private String errorMsg;

   /**
    * 构造函数
    * @param code 状态码
    * @param msg 状态消息
    * @param errorMsg 异常信息
    */
   public JsonException(Integer code, String msg, String errorMsg) {
       this.code = code;
       this.msg = msg;
       this.errorMsg = errorMsg;
   }

   public Integer getCode() {
       return code;
   }

   public void setCode(Integer code) {
       this.code = code;
   }

   public String getMsg() {
       return msg;
   }

   public void setMsg(String msg) {
       this.msg = msg;
   }

   public String getErrorMsg() {
       return errorMsg;
   }

   public void setErrorMsg(String errorMsg) {
       this.errorMsg = errorMsg;
   }
}

然后,我们需要自定义一个异常处理器 JsonExceptionHandler,捕获操作过程中可能出现的异常,并将其封装成统一的 JSON 格式返回前端。

@ControllerAdvice
public class JsonExceptionHandler {

   /**
    * 处理业务异常
    * @param e 业务异常
    * @param request 请求体
    * @return JSON 格式结果
    */
   @ExceptionHandler(value = JsonException.class)
   @ResponseBody
   public JsonResult<String> jsonExceptionHandler(JsonException e, HttpServletRequest request) {
       log.error("请求地址:[{}],错误信息:[{}]", request.getRequestURL(), e.getErrorMsg());
       JsonResult<String> result = new JsonResult<>();
       result.setCode(e.getCode());
       result.setMsg(e.getMsg());
       return result;
   }

   /**
    * 处理空指针异常
    * @param e 空指针异常
    * @param request 请求体
    * @return JSON 格式结果
    */
   @ExceptionHandler(value = NullPointerException.class)
   @ResponseBody
   public JsonResult<String> nullPointerExceptionHandler(NullPointerException e, HttpServletRequest request) {
       log.error("请求地址:[{}],错误信息:[{}]", request.getRequestURL(), e.getMessage());
       JsonResult<String> result = new JsonResult<>();
       result.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
       result.setMsg("系统繁忙,请稍后重试");
       return result;
   }

   /**
    * 处理其他错误异常
    * @param e 异常
    * @param request 请求体
    * @return JSON 格式结果
    */
   @ExceptionHandler(value = Exception.class)
   @ResponseBody
   public JsonResult<String> exceptionHandler(Exception e, HttpServletRequest request) {
       log.error("请求地址:[{}],错误信息:[{}]", request.getRequestURL(), e.getMessage());
       JsonResult<String> result = new JsonResult<>();
       result.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
       result.setMsg("系统繁忙,请稍后重试");
       return result;
   }

最后需要注意的是,在 ApiResultVOJsonResult 中,code 字段用于标记接口状态码,一般正常情况下为 0,而 msg 字段用于返回处理结果描述信息,data 字段返回数据内容。

3. 总结

本文介绍了三种实现统一 JSON 格式的接口返回结果的方法,分别是使用拦截器、自定义注解和统一异常处理。通过实现统一的返回格式,可以减少代码量,提升开发效率。同时,通过统一异常处理的方式,还可以将错误信息封装成统一 JSON 格式返回给前端,便于前端程序员查看和处理。

本文标题为:spring boot 统一JSON格式的接口返回结果的实现

基础教程推荐