spring mvc 中存在2中响应,一个是数据响应(常用于API开发),另一种是页面响应(常用于单体项目的开发)。
JSON的响应
spring boot 中只要引入了 web 启动器,就会自动的引入json的相关功能。在接口上标注@ResponseBody即可。
返回值解析器,一共15中:
处理返回值:
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
//寻找返回值处理器
HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
} else {
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
}
跟参数处理器一样,返回值处理器也是先判断是否支持,然后在调用返回值处理器进行处理。
支持的返回值:
返回值处理,利用MessageConverters进行处理:
@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);
}
内容协商:
- 请求方回根据自己的实际情况,告诉服务器端,需要什么类型的数据。
- 服务器根据自身能力,生成请求方需要的数据
- 根据确定的数据类型,选择对应类型的消息转换器,消息转换器的作用就是是否支持将class类型的对象转换成MediaType类型的数据。
- 默认的消息转换器,有以下几个:
最终使用MappingJackJon2HttpMessageConverter,转换成了json中。注意一点的是MappingJackJon2HttpMessageConverter是可以支持所有的返回值类型。
二、内容协商内容协商就是客户端和服务端根据实际情况,约定双方需要的数据格式。也可能在某种情况下,相同的接口web端需要返回json而手机端需要返回xml,这个时候就可以用到spring mvc的内容协商。
根据客户端接收能力的不同,而返回不同媒体类型的数据。
也可以开启参数方式,参数中包含format=jsonxml 就可以返回不同的模式。当然也可以自定义MediaType,也就是重写 MessageConverter
spring:
mvc:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
接口端会根据 Accept 参数,进行判断返回格式
- application/json 返回json
- application/xml 返回xml
如果同时定义了,就会根据权重进行判断,
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*
public class MgMessageConverter implements HttpMessageConverter 客户端请求: 跟踪源码可以看到,获取客户端的媒体类型为: 服务器可以处理消息的Converter: 以上是使用请求头的方式,下面可以说一下使用参数方式。 因为参数协商策略只支持json和xml,所以就需要自定义策略: 自定义策略也十分的简单: 跟踪代码可以看到,已经从原来的2中支持到现在的3中了: 在自定义功能的时候,小心默认功能失效,这个时候需要dubeg源码,查看哪里出现问题,解决即可。 package com.example.demo.conf;
import com.example.demo.converter.MgMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@Configuration(proxyBeanMethods = false)
public class WebMvcConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configureMessageConverters(List



