目录
4.2.2、自定义的uclassMessageConverter():
4.2.4、自定义组件有可能会覆盖很多默认功能,导致一些默认的功能失效。
controller层根据页面的请求,进行数据和图片的响应。
1、响应JSON,给前端返回json数据
1.1、引入依赖
pom.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency> 
该场景自动引入了json场景
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-json</artifactId>
   <version>2.3.4.RELEASE</version>
   <scope>compile</scope>
</dependency> 
1.2、映射方法标注@ResponseBody注解
controller层:
@Controller
public class ResponseTestController {
    @ResponseBody
    @GetMapping("/test/person")
    public Person getPerson() {
        Person person = new Person();
        person.setAge(28);
        person.setBirth(new Date());
        person.setUserName("zhangsan");
        return person;
    }
} 
页面响应数据:

1.3、SpringMVC支持的返回值类型
ModelAndView
Model
View
ResponseEntity 
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask
有 @ModelAttribute 注解,且为对象类型的返回值
有 @ResponseBody 注解,利用RequestResponseBodyMethodProcessor处理器进行返回 
2、内容协商
根据客户端接收能力不同,返回不同媒体类型的数据。
2.1、引入xml依赖(支持返回xml格式的数据)
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency> 
前端界面返回值:

2.2、postman分别测试返回json和xml
只需要改变请求头中Accept字段。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。
![]()
对请求头中Accept进行修改:

2.3、 开启浏览器参数方式内容协商功能
- 浏览器请求头无法修改,不能控制返回数据的格式信息
 - 为了方便内容协商,开启基于请求参数的内容协商功能
 - 只需要在请求中加入字段“?format=xxx”,即可改变返回给前端界面的内容格式
 
3.1、配置文件中开启基于浏览器参数方式内容协商功能

3.2、在请求中加入字段“?format=xxx”:
1、http://localhost:8080/test/person?format=json返回json数据给前端

2、http://localhost:8080/test/person?format=xml返回xml数据给前端

4、自定义 MessageConverter
实现多协议数据兼容。json、xml、x-guigu
-  
@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
 -  
Processor 处理方法返回值。通过 MessageConverter 处理
 -  
所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
 -  
内容协商找到最终的 messageConverter;
 
4.1、实例:需求
- 浏览器请求,返回xml;
 - ajax请求返回json;
 - app发送请求,返回自定义协议数据。
 
4.2、解决:
4.2.1步骤:
- 添加自定义的 MessageConverter 进系统底层;
 - 系统底层统计出所有 MessageConverter 能操作的类型;
 - 客户端内容协商。
 
原理:修改SpringMVC的功能。在一个入口,给容器中添加一个 WebMvcConfigurer
@Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new uclassMessageConverter());
            }
        };
    } 
4.2.2、自定义的uclassMessageConverter():
/*
  自定义的converter
* */
public class uclassMessageConverter implements HttpMessageConverter<Person> {
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }
    //服务器统计所有MessageConverter能写出哪些内容
    //自定义数据类型
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-uclass");
    }
    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }
    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //自定义协议数据的写出
        String data = person.getUserName() + ";" + person.getAge() + ";" + person.getBirth();
        //写入输出流
        OutputStream body = outputMessage.getBody();
        body.write(data.getBytes());
    }
}
 
4.2.3、自定义数据的浏览器参数方式内容协商功能
1)基于参数的内容协商策略:默认只有xml和json两种

2)自定义内容协商管理器(包括请求头和请求参数)
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //基于请求参数的内容协商管理器
                Map<String, MediaType> mediaTypes = new HashMap<>();
                mediaTypes.put("json", MediaType.APPLICATION_JSON);
                mediaTypes.put("xml", MediaType.APPLICATION_XML);
                //自定义协议
                mediaTypes.put("uclass", MediaType.parseMediaType("application/x-uclass"));
                //Map<String, MediaType> mediaTypes
                //参数策略,需要指定支持解析url参数对应的媒体类型
                ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(mediaTypes);
                //基于请求头的内容协商管理器
                HeaderContentNegotiationStrategy headStrategy = new HeaderContentNegotiationStrategy();
                configurer.strategies(Arrays.asList(strategy, headStrategy));
            } 
3)页面数据:

4)修改后的基于参数的内容协商策略:包含json、xml和uclass
4.2.4、自定义组件有可能会覆盖很多默认功能,导致一些默认的功能失效。
如上述自定义内容协商管理器中只配置参数管理器时,会导致默认的请求头协商管理器失效
需要对源码的配置和运行流程进行理解。










