SpringBoot自定义MessageConvert详细讲解
作者:zoeil 发布时间:2023-04-23 19:24:39
前言
对于页面携带的请求头中的AcceptSpringBoot有对应的10种MessageConvert可以支持写出对应的媒体类型,比如application/xml、application/json……
我们还可以通过向容器放入一个WebMvcConfigurer
实现定制化SpingMVC,自定义一个MessageConvert处理特殊的协议比如application/x-person
实现多协议数据兼容。json、xml、x-person
原理
0、@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
1、Processor 处理方法返回值。通过 MessageConverter 处理
2、所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
3、内容协商找到最终的 messageConverter;
实现
/* 条件
*
* 1、浏览器发请求直接 返回xml [application/xml] jacksonXmlConverter
* 2、如果是ajax请求 返回json [application/json] jacksonJsonConverter
* 3、如果是app发请求,返回自定义协议数据 [application/x-person] xxxxConverter
*
* 步骤:
* 1、添加自定义的MessageConverter进系统底层
* 2、系统底层就会统计出所有MessageConverter能操作哪些类型
* 3、客户端内容协商 [person--->person]
*/
person类
@Data
public class Person {
public String username;
public Integer age;
public Pet pet;
}
pet类
@Data
public class Pet {
public String name;
public Integer age;
}
PersonMessageConvert
/*
* 自定义的Convert
*/
public class PersonMessageConvert 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);
}
/*
* @Description 服务器需要统计所有MessageConvert都能写出哪些类型,我们这里也要自定义
* @Param
**/
@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-person");
}
@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.getPet() + ";";
//写出去
OutputStream body = outputMessage.getBody();
body.write(data.getBytes());
}
}
方法
@ResponseBody
@GetMapping("/test/person")
public Person getPeroson() {
Person person = new Person();
person.setUsername("张三");
person.setAge(18);
person.setPet(new Pet());
return person;
}
WebMvcConfigurer
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new PersonMessageConvert());
}
}
}
测试
拓展
如何实现访问路径携带format参数指明协商协议
比如:http://localhost:8080/test/person?format=x-person
记得先开启基于参数的内容协商
spring:
mvc:
contentnegotiation:
favor-parameter: true
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
/*
* 自定义内容协商策略
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
Map<String, MediaType> mediaTypeMap = new HashMap<>();
mediaTypeMap.put("json", MediaType.APPLICATION_JSON);
mediaTypeMap.put("xml", MediaType.APPLICATION_XML);
mediaTypeMap.put("x-person",MediaType.parseMediaType("application/x-person"));
//指定支持解析那些参数的媒体类型
ParameterContentNegotiationStrategy parametertrategy = new ParameterContentNegotiationStrategy(mediaTypeMap);
HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(parametertrategy, headerStrategy));
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new PersonMessageConvert());
}
};
}
测试
注意:有可能我们添加的自定义的功能会覆盖默认很多功能,导致一些默认的功能失效。比如上面的ContentNegotiationConfigurer 就会覆盖原来的默认ContentNegotiationConfigurer
来源:https://blog.csdn.net/m0_62946761/article/details/128607144


猜你喜欢
- 写Java程序时经常碰到要读如txt或写入txt文件的情况,但是由于要定义好多变量,经常记不住,每次都要查,特此整理一下,简单易用,方便好懂
- Springmvc+hibernate成为现在很多人用的框架整合,最近自己也在学习摸索,由于我们在开发项目中很多项目都用到列表分页功能,在此
- 本文实例为大家分享了Android广播实现App开机自启动的具体代码,供大家参考,具体内容如下一、概括在安卓中,想要实现app开机自动启动,
- 前言在上一篇 Spring boot + LayIM + t-io 文件上传、 监听用户状态的实现 中,已经介绍了两个小细节:用户的在离线状
- 一、项目简述功能包括: 分为管理员及普通业主角色,业主信息,社区房屋,维护 管理,社区车辆,社区投诉,社区缴费,社区业务信息维 护等等功能。
- 写作原因:跨进程通信的实现和理解是Android进阶中重要的一环。下面博主分享IPC一些相关知识、操作及自己在学习IPC过程中的一些理解。这
- 有个网站需要生成静态页。据以往经验,凡比较烂的空间,短时间内运行耗能大的运算,都会出现“service unavailable”,以致网页无
- //截取全屏图象 private void btnFul
- 一、作用和区别 break的作用是跳出当前循环块(for、while、do while)或程序块(switch)。在循环块中的作用
- 方法一:递归算法/// <summary>/// 一列数的规则如下: 1、1、2、3、5、8、13、21、34求第30位数是多少
- UGUI的滑动组件虽然表现上和NGUI的ScrollView一致,但是它更美好的是开放源码的,不了解原理的时候直接查源码就OK。在使用Scr
- 下面是函数定义: NTSTATUS RtlAdjustPrivilege ( ULONG Privilege, BOOLEAN Enable
- 今天看见一个Android 扑克卡片翻转效果的帖子,于是手痒想学一学,由于接触过的Animation动画等比较少,所以感觉很新奇。首先,说一
- Java File类 mkdir 不能创建多层目录File f = new File("/home/jp/Upload"
- 开发过程中,我们往往需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发
- 前言 安卓系统中,Button是程序和用户进行交互的一个重要控件,今天我们就来简单的对Button进行学习,其中Bu
- 有时候,我们的程序需要启动一些子进程,如嵌入的图形程序。当启动一个进程后,获得这个进程信息Process,然后其内部在某个时刻启动了一个子进
- 我想到使用Redis的订阅发布模式是用来解决推送问题的~。对于概念性的叙述,多多少少还是要提一下的:什么是Redis发布订阅?Redis发布
- 一、微服务简介 Ⅰ、我对微服务的理解微服务是软件开发的一种架构方式,由单一的应用小程序构成的小服务;一个软件系统由多个服务组成;在微服务中,
- 近期做简单的新闻客户端界面使用到了Jsoup获取,使用起来特别方便,这也是被我一个学长称为学android网络必学的一个东西,在此也是分享一