1、响应Json

  • 只要引入Spring-boot-start-web开发场景就帮我们直接引入了Jackson.jar

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-web</artifactId>
    4. </dependency>
  • 自动帮引入了spring-boot-starter-json

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.5.3</version>
        <scope>compile</scope>
      </dependency>
    
  • spring-boot-start-json里面就有jackson相关的依赖

      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-parameter-names</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
      </dependency>
    

    我们开发就只需要加个@ResponseBody注解 就可以直接返回Json格式数据

    @Controller
    public class ResponseTestController {
    
      @ResponseBody
      @GetMapping("/pet")
      public Pet getPet(){
          Pet pet = new Pet();
          pet.setAge(3);
          pet.setName("小花");
          return pet;
      }
    }
    

    1.1、返回值解析器原理

    ```java public interface HandlerMethodReturnValueHandler {

    /* 检查是否支持该类型 */ boolean supportsReturnType(MethodParameter returnType);

    /**

    • 处理值 */ void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
       ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
      

}

RequestResponseBodyMethodProcessor 处理json格式方法
```java
//RequestResponseBodyMethodProcessor    
@Override
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

        mavContainer.setRequestHandled(true);
        ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
        ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

        // Try even with null return value. ResponseBodyAdvice could get involved.
        writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    }
  • 返回值处理器判断是否支持该类型supportsReturnType
  • 支持之后再调用handleReturnValue进行处理值
  • 经过查找最终找到RequestResponseBodyMethodProcessor支持处理方法标了@ResponseBody注解的处理器

    • 通过writeWithMessageConverters来处理转换成json格式数据

      • 内容协商(浏览器默认会以请求头的方式告诉我们服务器他能接受什么样的内容类型)
      • 服务器最终根据自身的能力,决定服务器能生成什么样的格式的数据类型
      • SpringMVC会挨个遍历判断所有容器底层的HttpMessageConverter哪个能处理
      • 最终MappingJackson2HttpMessageConverter把数据转换成JSON写出去

        MappingJackson2HttpMessageConverter利用父类AbstractJackson2HttpMessageConverter中的如下方法写Json
        @Override
        protected void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        
        MediaType contentType = outputMessage.getHeaders().getContentType();
        JsonEncoding encoding = getJsonEncoding(contentType);
        
        Class<?> clazz = (object instanceof MappingJacksonValue ?
                ((MappingJacksonValue) object).getValue().getClass() : object.getClass());
        ObjectMapper objectMapper = selectObjectMapper(clazz, contentType);
        Assert.state(objectMapper != null, "No ObjectMapper for " + clazz.getName());
        
        OutputStream outputStream = StreamUtils.nonClosing(outputMessage.getBody());
        try (JsonGenerator generator = objectMapper.getFactory().createGenerator(outputStream, encoding)) {
            writePrefix(generator, object);
        
            Object value = object;
            Class<?> serializationView = null;
            FilterProvider filters = null;
            JavaType javaType = null;
        
            if (object instanceof MappingJacksonValue) {
                MappingJacksonValue container = (MappingJacksonValue) object;
                value = container.getValue();
                serializationView = container.getSerializationView();
                filters = container.getFilters();
            }
            if (type != null && TypeUtils.isAssignable(type, value.getClass())) {
                javaType = getJavaType(type, null);
            }
        
            ObjectWriter objectWriter = (serializationView != null ?
                    objectMapper.writerWithView(serializationView) : objectMapper.writer());
            if (filters != null) {
                objectWriter = objectWriter.with(filters);
            }
            if (javaType != null && javaType.isContainerType()) {
                objectWriter = objectWriter.forType(javaType);
            }
            SerializationConfig config = objectWriter.getConfig();
            if (contentType != null && contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM) &&
                    config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
                objectWriter = objectWriter.with(this.ssePrettyPrinter);
            }
            objectWriter.writeValue(generator, value);
        
            writeSuffix(generator, object);
            generator.flush();
        }
        catch (InvalidDefinitionException ex) {
            throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
        }
        catch (JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex);
        }
        }
        

        1.2、消息转换器HttpMessageConverter原理

        image.png

  • 看是否支持把Class类型的对象,转换为MediaType类型

  • 例如:对象转JSON 、JSON转对象

    1.2.1、当前支持的消息转换器

    image.png

  • 0:只支持Byte类型

  • 1 :String
  • 2:String
  • 3:Resource
  • 4: ResourceRegion
  • 5: DOMSource
  • 6:MultiValueMap
  • 7:true
  • 8:true
  • 9:支持注解方式XML处理

返回参数处理器

15个返回参数处理器
image.png