Spring Boot 统一定义Resutful接口输出结构
admin 发布于:2022-05-09 10:12:03
阅读:loading
在前面一篇文章《Spring Boot 定义公共结果集输出对象》时列举了Spring Boot内置的统一错误的JSON结构和阿里编码规范中提供的统一JSON结构,同时也提供了本站系统的统一结果集输出的对象类型和数据结构,本次将使用编码来的形式来接管全局的统一JSON格式输出,达到统一输出的目的,即无论在Controller中使用任何类型的返回值,均会被使用内置的输出类型进行包装输出。
在项目中也有实现HandlerMethodReturnValueHandler接口来统一接管Response响应输出的实现,本次提供本站博客系统的实现ResponseBodyAdvice接口来统一输出JSON结构(建站初期时的实现选型),详细介绍如下:
(1)使用@ControllerAdvice和@RestControllerAdvice处理@RestController和@ResponseBody的响应请求输出拦截;
(2)限制仅继承BaseController的类实现统一输出,不排除一些对外部提供接口时个性化输出定制场景;
package cn.chendd.base.handler;
import cn.chendd.base.controller.BaseController;
import cn.chendd.base.result.BaseResult;
import cn.chendd.base.result.SuccessResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.awt.image.BufferedImage;
import java.lang.annotation.Annotation;
/**
* Controller响应结果统一封装,也可以使用 @RestControllerAdvice 注解处理
*
* @author chendd
* @date 2019/9/22 18:03
*/
@ControllerAdvice
@RestControllerAdvice
@Slf4j
public class HandlerResponseBodyAdvice implements ResponseBodyAdvice {
/**
* 必须规则:约定类继承了BaseController,表示为自定义模块
* 可选规则:类被标记有@RestController
* 可选规则:方法被标记有@Response
*/
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
Class<?> containingClass = methodParameter.getContainingClass();
Annotation restController = containingClass.getAnnotation(RestController.class);
ResponseBody responseBody = methodParameter.getMethod().getAnnotation(ResponseBody.class);
boolean rest = restController != null || responseBody != null;
boolean custom = BaseController.class.isAssignableFrom(containingClass);
return rest && custom;
}
@Override
public Object beforeBodyWrite(Object value,
MethodParameter methodParameter,
MediaType mediaType,
Class aClass, ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if(value == null){
return SuccessResult.build();
}
if(value instanceof BaseResult){
return value;
} else if(value instanceof BufferedImage) {
return value;
}
return SuccessResult.build().data(value);
}
}
仅使用上述代码是满足大多数的响应结果输出,需要注意一些特殊场景的细节问题:
(1)当Controller方法返回String类型时会出现类型转换异常,即无法将String类型转换为系统统一的JSON数据类型BaseResult,解决方式是增加String类型的JSON转换器输出即可;
(2)当Controller方法返回为Object、JavaBean等类型时,若返回值为空时则系统统一的JSON输出不会生成期望的BaseResult数据结构,解决方式是设置默认的JSON组件的属性即可;
所以,上述问题的解决可参见项目代码示例的cn.chendd.base.spring.components.WebMvcRegistrationsConfig类。
源码工程下载:源码下载.zip;
点赞