实现多协议数据兼容。json、xml、x-saving(这个是自定义的)
1、@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
2、Processor 处理方法返回值。通过 MessageConverter处理
3、所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
4、内容协商找到最终的 messageConverter
场景:
1、浏览器发请求直接返回 xml [application/xml] jacksonXmlConverter
2、如果是ajax请求 返回 json [application/json] jacksonJsonConverter
3、如果自定义app发请求,返回自定义协议数据 [appliaction/x-saving] xxxxConverter
属性值1;属性值2;
步骤:
1、添加自定义的MessageConverter进系统底层
2、系统底层就会统计出所有MessageConverter能操作哪些类型
3、客户端内容协商 [saving--->saving]
@ResponseBody//利用返回值处理器里面的消息转换器进行处理
@GetMapping("/test/person")
public Person getPerson(){
Person person = new Person();
person.setAge(21);
person.setBirth(new Date());
person.setName("saving");
return person;
}
内容协商处理器包括两种策略:①基于参数(?format=XXX)
②基于请求头
以下是基于请求头的自定义MessageConverter x-saving数据类型
自定义MessageConverter
/**
* 自定义的converter
*/
public class SavingMessageConverter implements HttpMessageConverter<Person> {
//此例子暂时不read canRead表示在形参列表添加@RequestBody 读取各种类型数据的情况
@Override
public boolean canRead(Class aClass, MediaType mediaType) {
return false;
}
@Override
public boolean canWrite(Class aClass, MediaType mediaType) {
return aClass.isAssignableFrom(Person.class);
}
/**
* 服务器要统计所有MessageConverter都能写出哪些内容类型
*
* application/x-saving
* @return
*/
@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-saving");
}
@Override
public Person read(Class aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public void write(Person person, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
//自定义协议数据的写出
String data = person.getName()+";"+person.getAge()+";"+person.getBirth();
//写出去
OutputStream body = httpOutputMessage.getBody();
body.write(data.getBytes());
}
}
将自定义的MessageConverter引入config文件中
@Configuration(proxyBeanMethods = false)//放的组件没有依赖 用false快速
public class WebConfig{
@Bean//注册到容器中
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
//引入自定义的converter
//extendMessageConverters表示扩展converter,还有一个方法表示覆盖
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new SavingMessageConverter());
}
}
测试:
以下是基于请求参数的自定义MessageConverter x-saving数据类型
@Configuration(proxyBeanMethods = false)//放的组件没有依赖 用false快速
public class WebConfig{
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
/**
* 自定义内容协商策略
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//Map<String, MediaType> mediaTypes
Map<String, MediaType> mediaTypes = new HashMap<>();
mediaTypes.put("json",MediaType.APPLICATION_JSON);
mediaTypes.put("xml",MediaType.APPLICATION_XML);
//自定义媒体类型
mediaTypes.put("saving",MediaType.parseMediaType("application/x-saving"));//对应的是SavingMessageConverter
//指定支持解析哪些参数对应的哪些媒体类型
ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
// parameterStrategy.setParameterName("ff");//也可以改 format ==> ff
//内容协商处理器包括两种策略:①基于参数(?format=XXX) ②基于请求头
//还需添加请求头处理策略,否则accept:application/json、application/xml则会失效
HeaderContentNegotiationStrategy headeStrategy = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(parameterStrategy, headeStrategy));
}
//引入自定义的converter
//extendMessageConverters表示扩展converter,还有一个方法表示覆盖
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new SavingMessageConverter());
}
}
json、xml格式当然也是可以的
日后开发要注意,有可能我们添加的自定义的功能会覆盖默认很多功能,导致一些默认的功能失效。