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

目录

一、简单使用

二、存在的问题描述

三、优点


一、简单使用

统一的数据返回格式使用  @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 {
 @Override
 public boolean supports(MethodParameter returnType, Class converterType) {
 return true;
 }
 
 @Override
 public 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 AbstractHandlerMethodAdapter
 implements 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. 有利于后端技术部门的统一规范的标准制定, 不会出现稀奇古怪的返回内容。
  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot通过使用统一数据返回格式可以提高开发效率和代码的可维护性。返回统一的JSON数据格式可以统一前后端之间的数据交互方式,减少沟通成本,并且提高了代码的可读性和可维护性。 在SpringBoot中,可以定义一个全局异常处理器(GlobalExceptionHandler),用于捕获和处理全局的异常。在异常处理器中,可以定义一个统一数据返回格式,包括状态码、提示信息和返回数据。当发生异常时,异常处理器会将异常信息封装成统一的JSON数据格式返回给前端,以便前端进行处理。 为了实现统一数据返回格式,可以定义一个响应对象(ResponseObject),包含对应的状态码、提示信息和返回数据。在业务逻辑处理中,统一使用ResponseObject来封装返回数据,然后再返回给前端。 在控制器层中,可以使用ResponseEntity对象来返回统一的JSON数据格式。通过使用ResponseEntity.ok()方法可以返回一个状态码为200的成功响应,然后将ResponseObject对象作为响应的数据。这样,无论是成功还是失败,都能以统一的JSON数据格式返回给前端。 在返回数据时,可以添加一些通用的字段,如请求ID、访问时间等,以便用于日志记录和跟踪。 通过采用统一的JSON数据返回格式,可以提高代码的可读性、可维护性和规范性,方便前后端的协作和沟通。同时,也可以方便后期的维护和扩展,减少了代码的冗余和重复编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值