SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解

目录

1、自定义消息转换器MessageConverter

2、自定义内容协商管理器contentNegotiationManager

1、自定义消息转换器MessageConverter

在WebMvcAutoConfiguration类中有一个方法configureMessageConverters(),它会配置默认的MessageConverter

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.messageConvertersProvider.ifAvailable((customConverters) -> { converters.addAll(customConverters.getConverters()); }); }

假设我们现在有一个新的需求

想要后端返回我们自己定义的格式的数据,就叫x-decade,格式为使用分号拼接Person对象属性值

那么就要新建一个MessageConverter了

package com.decade.converters; import com.decade.pojo.Person; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import java.io.IOException; import java.io.OutputStream; import java.util.List; public class DecadeConverter implements HttpMessageConverter<Person> { // 只考虑写出,所以这里默认写false @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return clazz.isAssignableFrom(Person.class); } /** * 统计当前converter能支持哪些类型 * @return 返回支持的媒体类型 */ @Override public List<MediaType> getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-decade"); } // 只考虑写出,所以这里默认写null @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 result = person.getName() + ";" + person.getAge() + ";" + person.getBirth(); // 写出 final OutputStream body = outputMessage.getBody(); body.write(result.getBytes()); } }

我们发现,WebMvcConfigurer接口类下面有2个关于配置MessageConverter的方法

// 会覆盖默认的MessageConverter default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } // 不会覆盖,只会在默认的MessageConverter后面追加我们自定义的 default void extendMessageConverters(List<HttpMessageConverter<?>> converters) { }

所以,我们选择在自定义配置类中重写extendMessageConverters()方法

package com.decade.config; import com.decade.converters.DecadeConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration(proxyBeanMethods = false) public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer createConvert() { return new WebMvcConfigurer() { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new DecadeConverter()); } }; } }

我们在请求头中设置Accept为我们自定义的格式application/x-decade

验证结果如下

2、自定义内容协商管理器contentNegotiationManager

问题:我们新建的x-decade格式是否只能通过postman调用才会生效呢?如果我们要使用浏览器参数方式,怎么才能生效呢?

因为我们之前的【Spring Boot】响应处理

它默认只能处理xml和json格式,所以为了解决这个问题,我们就要自定义内容协商管理器了

首先我们还是要在自定义配置类中重写相关方法

package com.decade.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.accept.HeaderContentNegotiationStrategy; 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.Map; @Configuration(proxyBeanMethods = false) public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer createConvert() { 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("decade", MediaType.parseMediaType("application/x-decade")); final ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(mediaTypes); // 为了继续支持请求头参数类型,还需要往里面塞请求头内容协商管理器 final HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy(); configurer.strategies(Arrays.asList(strategy, headerContentNegotiationStrategy)); } }; } }

可以看到,系统中的内容协商管理器下面还是原来的2种:获取请求头中的Accept和获取请求参数中的format

但是获取请求参数format,除了能识别原来的json和xml,还能识别我们自定义的application/x-decade,它使用decade与之对应

可以看到,我们自定义的媒体类型成功加入服务器能解析出来的类型

我们写一个接口进行验证

@GetMapping(value = "/testPerson") @ResponseBody public Person testPerson() { Person person = new Person(); person.setName("decade"); person.setAge(24); person.setBirth(new Date()); return person; }

由验证结果可以知道,我们从postman和浏览器都可以获得我们指定格式的数据

到此这篇关于SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解的文章就介绍到这了,更多相关SpringBoot MessageConverter内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    学习写字楼新选择6000元主流配置

    学习写字楼新选择6000元主流配置,,这种配置需要考虑双核心的办公和娱乐平台,充分考虑办公室的办公需求和娱乐需求,以约6000元的预算和cost-e

    酷睿I7 配置

    酷睿I7 配置,配置,玩家国度啦华硕 Rampage II Extreme(3800元)如果米不够,也可以把Extreme改为Gene,不过是小板内存推荐金士顿6G DDR3 2000骇

    提高3A四核羿龙II游戏配置的性能

    提高3A四核羿龙II游戏配置的性能,,以节能环保为主题的IT产业,目前3A低端平台处理器、主板芯片组、独立开发卡性能突出,特别是在与AMD的处理

    opporeno8参数配置及价格

    opporeno8参数配置及价格,面部,亿元,Oppo的荣誉2020年1月4日,接近屏幕关闭传感器是否支持双卡:支持oppor11splus什么时候上市的Oppo R11S P

    查看配置:酷睿i3530集展示办公平台

    查看配置:酷睿i3530集展示办公平台,,由于时间和精力的关系,我们不可能对所有的配置进行评论,希望我们能理解,我希望我们的评论能在那些需要帮

    3500元超额值学生娱乐结构的优化配置

    3500元超额值学生娱乐结构的优化配置,,作为一个DIY的主流用户领域的学生,每个用户51学生攒机的高峰。因为学生用户没有稳定的收入来源,攒机

    电脑配置快捷键|查看电脑配置快捷键

    电脑配置快捷键|查看电脑配置快捷键,,查看电脑配置快捷键1.在win10中,快捷键组合win+E已经变成了“快速访问”,不再是以前的“我的电脑了”2