当前位置: 首页> 科技> 互联网 > SpringBoot统一功能处理——统一数据返回格式

SpringBoot统一功能处理——统一数据返回格式

时间:2025/7/15 1:02:11来源:https://blog.csdn.net/m0_60462557/article/details/141018885 浏览次数:0次

目录

一、简单使用

二、存在的问题描述

三、优点


一、简单使用

统一的数据返回格式使用  @ControllerAdvice ResponseBodyAdvice 的方式实现 @ControllerAdvice 表示控制器通知类。
添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接口,并在类上添加 @ControllerAdvice 注解。
import com.example.demo.model.Result;
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.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {return Result.success(body);}
}
supports方法: 判断是否要执行beforeBodyWrite方法。true为执行,false不执行。 通过该方法可以选择哪些类或哪些方法的response要进行处理, 其他的不进行处理。
从returnType获取类名和方法名:
//获取执行的类
Class<?> declaringClass = returnType.getMethod().getDeclaringClass();
//获取执行的方法
Method method = returnType.getMethod();
beforeBodyWrite方法: 对response方法进行具体操作处理。

二、存在的问题描述

SpringMVC默认会注册一些自带的 HttpMessageConverter (从先后顺序排列分别为):
  • ByteArrayHttpMessageConverter 
  • StringHttpMessageConverter 
  • SourceHttpMessageConverter 
  • SourceHttpMessageConverter 
  • AllEncompassingFormHttpMessageConverter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {//...public RequestMappingHandlerAdapter() {this.messageConverters = new ArrayList<>(4);this.messageConverters.add(new ByteArrayHttpMessageConverter());this.messageConverters.add(new StringHttpMessageConverter());if (!shouldIgnoreXml) {try {this.messageConverters.add(new SourceHttpMessageConverter<>());}catch (Error err) {// Ignore when no TransformerFactory implementation is available}}this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());}//...
}
其中AllEncompassingFormHttpMessageConverter 会根据项目依赖情况添加对应的HttpMessageConverter:
public AllEncompassingFormHttpMessageConverter() {if (!shouldIgnoreXml) {try {addPartConverter(new SourceHttpMessageConverter<>());}catch (Error err) {// Ignore when no TransformerFactory implementation is available}if (jaxb2Present && !jackson2XmlPresent) {addPartConverter(new Jaxb2RootElementHttpMessageConverter());}}if (kotlinSerializationJsonPresent) {addPartConverter(new KotlinSerializationJsonHttpMessageConverter());}if (jackson2Present) {addPartConverter(new MappingJackson2HttpMessageConverter());}else if (gsonPresent) {addPartConverter(new GsonHttpMessageConverter());}else if (jsonbPresent) {addPartConverter(new JsonbHttpMessageConverter());}if (jackson2XmlPresent && !shouldIgnoreXml) {addPartConverter(new MappingJackson2XmlHttpMessageConverter());}if (jackson2SmilePresent) {addPartConverter(new MappingJackson2SmileHttpMessageConverter());}
}
在依赖中引入jackson包后,容器会把 MappingJackson2HttpMessageConverter 自 动注册到messageConverters 链的末尾。
Spring会根据返回的数据类型, 从 messageConverters 链选择合适的 HttpMessageConverter :
  • 当返回的数据是非字符串时, 使用的 MappingJackson2HttpMessageConverter 写入返回对象。
  • 当返回的数据是字符串时,StringHttpMessageConverter 会先被遍历到,这时会认为 StringHttpMessageConverter 可以使用。
public abstract class AbstractMessageConverterMethodProcessor extends
AbstractMessageConverterMethodArgumentResolver
implements HandlerMethodReturnValueHandler {//...代码省略
protected <T> void writeWithMessageConverters(@Nullable T value,
MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse
outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException,
HttpMessageNotWritableException {//...代码省略
if (selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
for (HttpMessageConverter<?> converter : this.messageConverters) {
GenericHttpMessageConverter genericConverter = (converter
instanceof GenericHttpMessageConverter ?
(GenericHttpMessageConverter<?>) converter : null);
if (genericConverter != null ?
((GenericHttpMessageConverter)
converter).canWrite(targetType, valueType, selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {//getAdvice().beforeBodyWrite 执⾏之后, body转换成了Result类型的结果
body = getAdvice().beforeBodyWrite(body, returnType,
selectedMediaType,
(Class<? extends HttpMessageConverter<?>>)
converter.getClass(),
inputMessage, outputMessage);
if (body != null) {
Object theBody = body;
LogFormatUtils.traceDebug(logger, traceOn ->"Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");
addContentDispositionHeader(inputMessage, outputMessage);if (genericConverter != null) {genericConverter.write(body, targetType, 
selectedMediaType, outputMessage);}else {//此时cover为StringHttpMessageConverter((HttpMessageConverter) converter).write(body, 
selectedMediaType, outputMessage);}}else {if (logger.isDebugEnabled()) {logger.debug("Nothing to write: null body");}}return;}}}//...代码省略}//...代码省略
}
((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage) 的处理中, 调用父类的write方法。由于 StringHttpMessageConverter 重写了addDefaultHeaders方法,所以会执行子类的方法。
然而子类 StringHttpMessageConverter 的addDefaultHeaders方法定义接收参数为String,此时 t 为 Result 类型,,所以出现类型不匹配"Result cannot be cast to java.lang.String"的异常。

三、优点

  1. 方便前端程序员更好的接收和解析后端数据接口返回的数据;
  2. 降低前端程序员和后端程序员的沟通成本, 按照某个格式实现就可以了, 因为所有接口都是这样返回的;
  3. 有利于项目统一数据的维护和修改;
  4. 有利于后端技术部门的统一规范的标准制定, 不会出现稀奇古怪的返回内容。
关键字:SpringBoot统一功能处理——统一数据返回格式

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: