irpas技术客

【SpringBoot】响应处理——数据以 json 格式返回的原理_springboot 返回json_刘婉晴

网络投稿 2007

一、示例代码:

访问 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); }

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

浏览器告知服务器其处理能力服务器根据其自身能力,判断服务器能生产什么样的内容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转换的)

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

尾注: 我是真的不想看SpringBoot源码, 属实是有点强人所难了


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #springboot #返回json #SpringBoot响应处理 #返回 #JSON数据的原理