SpringBoot响应处理之以Json数据返回的实现方法

 更新时间:2022年09月29日 16:55:30   作者:刘婉晴  
这篇文章主要介绍了SpringBoot整合Web开发其中Json数据返回的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、示例代码

访问 localhost:8080/jsonTest —— 返回 json 格式的数据

@Controller
public class ResponseTestController {
    @ResponseBody // 标注 —— 自动返回json数据
    @GetMapping("/jsonTest")
    public Person testPerson(){
        Person person = new Person();
        person.setAge(20);
        person.setUserName("Liuwanqing");
        Pet pet = new Pet();
        pet.setName("huahua");
        pet.setAge("五个月");
        person.setPet(pet);
        return person;
    }
}

二、返回值解析原理

SpringBoot 支持的返回值类型是由返回值解析器决定的,SpringBoot 返回值类型如下:

ModelAndView

Model

View

SpringBoot共含15种返回值解析器决定了其支持15种返回值:

三、源代码分析(debug)

设置以下几处断点:

step into —— 返回值处理器逻辑

this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);

1. 先找返回值处理器

HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);

2. 执行下列代码,找到符合要求的返回值处理器

在众多返回值处理器中找到符合要求的 —RequestResponseBodyMethodRrocessor

即 RequestResponseBodyMethodRrocessor 可处理标注了 @ResponseBody 注解的返回值

   private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
        boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
        Iterator var4 = this.returnValueHandlers.iterator();
        HandlerMethodReturnValueHandler handler;
        do {
            do {
                if (!var4.hasNext()) {
                    return null;
                }
                handler = (HandlerMethodReturnValueHandler)var4.next();
            } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
        } while(!handler.supportsReturnType(returnType));
        return handler;
    }

3. 调用返回值处理器(interface HandlerMethodReturnValueHandler)处理:

判断是否支持这种类型的返回值,支持调用返回值处理器,调用 handleReturnValue 进行处理

public interface HandlerMethodReturnValueHandler {
    boolean supportsReturnType(MethodParameter var1);
    void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
}

4. RequestResponseBodyMethodRrocessor工作原理

关键代码:

    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
        mavContainer.setRequestHandled(true);
        ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
        ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
        this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    }

处理返回值的方法

使用消息转换器(涉及内容协商机制,请移步下文内容协商机制)进行写出操作,消息转换器工作过程如下:

  1. 浏览器告知服务器其处理能力
  2. 服务器根据其自身能力,判断服务器能生产什么样的内容
  3. SpringMVC 遍历所有容器的底层 HttpMessageConverter, 看谁能处理

四、内容协商机制

1. 内容协商

浏览器告知服务器其需要什么类型的服务类型

浏览器可接受的类型:

服务器得到浏览器的处理能力:

服务器将返回内容转为浏览器能处理的形式

2. 内容协商原理重点源代码

   protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request, Class<?> valueClass, @Nullable Type targetType) {
        Set<MediaType> mediaTypes = (Set)request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
        if (!CollectionUtils.isEmpty(mediaTypes)) {
            return new ArrayList(mediaTypes);
        } else if (this.allSupportedMediaTypes.isEmpty()) {
            return Collections.singletonList(MediaType.ALL);
        } else {
            List<MediaType> result = new ArrayList();
            Iterator var6 = this.messageConverters.iterator();
            while(true) {
                while(var6.hasNext()) {
                    HttpMessageConverter<?> converter = (HttpMessageConverter)var6.next();
                    if (converter instanceof GenericHttpMessageConverter && targetType != null) {
                        if (((GenericHttpMessageConverter)converter).canWrite(targetType, valueClass, (MediaType)null)) {
                            result.addAll(converter.getSupportedMediaTypes());
                        }
                    } else if (converter.canWrite(valueClass, (MediaType)null)) {
                        result.addAll(converter.getSupportedMediaTypes());
                    }
                }
                return result;
            }
        }
    }

3. HttpMessageConverters消息转换器原理

MessageConverter 规范

默认的MessageConverter

最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)

总结:

  1. 返回值处理器判断是否支持这种类型的返回值( supportsReturnType)
  2. 返回值处理器调用handleReturnValue 进行处理
  3. 以 @ResponseBody 注解为例,RequestResponseBodyMethodProcessor 可以处理返回值标
  4. 最后,利用 MessageConverters 进行处理 将数据写为json

到此这篇关于SpringBoot响应处理之以Json数据返回的实现方法的文章就介绍到这了,更多相关SpringBoot Json数据返回内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring和Websocket相结合实现消息的推送

    Spring和Websocket相结合实现消息的推送

    这篇文章主要介绍了Spring和Websocket相结合实现消息的推送的相关资料,本文介绍的非常详细具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-02-02
  • java 转发和重定向区别及实例代码

    java 转发和重定向区别及实例代码

    这篇文章主要介绍了java 转发和重定向区别及实例代码的相关资料,需要的朋友可以参考下
    2016-11-11
  • Maven导入本地jar包的实现步骤

    Maven导入本地jar包的实现步骤

    本文主要介绍了Maven导入本地jar包的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • MyBatis连接数据库配置的基本步骤和机制

    MyBatis连接数据库配置的基本步骤和机制

    MyBatis 是一个流行的持久层框架,它通过使用XML或注解的方式将SQL语句、存储过程和Java方法进行绑定,从而避免了手写大量的JDBC代码和手动设置参数与结果集,本文给大家介绍了MyBatis连接数据库配置的基本步骤和机制,需要的朋友可以参考下
    2024-05-05
  • Java中的线程同步与ThreadLocal无锁化线程封闭实现

    Java中的线程同步与ThreadLocal无锁化线程封闭实现

    这篇文章主要介绍了Java中的线程同步与ThreadLocal无锁化线程封闭实现,Synchronized关键字与ThreadLocal变量的使用是Java中线程控制的基础,需要的朋友可以参考下
    2016-03-03
  • mybatis-plus 新增/修改如何实现自动填充指定字段

    mybatis-plus 新增/修改如何实现自动填充指定字段

    这篇文章主要介绍了mybatis-plus 新增/修改实现自动填充指定字段方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java用邻接矩阵存储图的示例代码

    Java用邻接矩阵存储图的示例代码

    邻接矩阵通常采用一个一维数组存储图中节点的信息,采用一个二维数组存储图中节点之间的邻接关系。本文将利用Java实现用邻接矩阵存储图,需要的可以参考一下
    2022-06-06
  • Spring事件监听机制ApplicationEvent方式

    Spring事件监听机制ApplicationEvent方式

    这篇文章主要介绍了Spring事件监听机制ApplicationEvent方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • logback-spring.xml的内容格式详解

    logback-spring.xml的内容格式详解

    这篇文章主要介绍了logback-spring.xml的内容格式详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的的朋友参考下吧
    2023-11-11
  • spring data JPA 中的多属性排序方式

    spring data JPA 中的多属性排序方式

    这篇文章主要介绍了spring data JPA 中的多属性排序方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02

最新评论