SpringBoot2.x系列教程(十八)HttpMessageConverter实战及经验
在篇文章中介绍了自定义HttpMessageConverter的使用,其中我们通过实现WebMvcConfigurer接口来完成自定义HttpMessageConverter并向spring容器中添加的操作。本篇文章我们就通过集成fastjson这个实例,来汇总一下将HttpMessageConverter添加到容器中的集中操作。
通过@Configuration添加
我们已经知道,通过@Configuration可以将其内部定义的@Bean的特定方法注入到容器当中。首先,我们可以通过将HttpMessageConverters(注意多个s)实例化并注入到容器当中。
而在创建HttpMessageConverters时,指定我们所使用的HttpMessageConverter。
这里以集成fastjson为例来进行演示。在使用之前,首先在项目中引入相关依赖。
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency>
然后通过下面的配置类来进行fastjson的集成配置。
@Configuration public class FastJsonConfiguration { @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { // 定义一个convert转换消息的对象 FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); // 添加fastJson的配置信息 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); // 处理中文乱码问题 List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON); // 在convert中添加配置信息 converter.setSupportedMediaTypes(fastMediaTypes); converter.setFastJsonConfig(fastJsonConfig); return new HttpMessageConverters(converter); } }
关于上面的代码不作过多解释,其中FastJsonHttpMessageConverter是fastjson与spring进行集成的支持包下面的类。通过该类由fastjson实现,本质上也是一个HttpMessageConverter的实现。
上述代码中配置了FastJsonHttpMessageConverter的一些配置项,比如序列化配置、MediaTypes的配置。最后将FastJsonHttpMessageConverter的对象作为参数传递给HttpMessageConverters。
相关Controller代码如下:
@RestController public class OrderController { @GetMapping public Order getOrderInfo() { Order order = new Order(); order.setOrderNo("NO10000"); order.setAmount(new BigDecimal("100")); return order; } }
实体类代码如下:
@Data public class Order { private String orderNo; private BigDecimal amount; }
单元测试代码如下:
@Slf4j @SpringBootTest @AutoConfigureMockMvc class OrderControllerTest { @Autowired private MockMvc mockMvc; @Test void getOrderInfo() throws Exception { MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/")).andReturn(); log.info("result={}", mvcResult.getResponse().getContentAsString()); } }
执行单元测试,会发现输出了预期的结果。
result={ "amount":100, "orderNo":"NO10000" }
我们发现打印的json字符串已经与之前默认的不同了,被格式化了。说fastjson配置生效了。
继承WebMvcConfigurerAdapter
第二种配置方法和第三种配置方法都是继承WebMvcConfigurerAdapter,只不过分别通过:extendMessageConverters方法和configureMessageConverters方法来实现的。
@Slf4j @Configuration public class WebMvcConfiguration implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // TODO 同样可在此处添加converter } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // TODO 同样可在此处添加converter } private void print(List<HttpMessageConverter<?>> converters){ converters.forEach((converter) -> log.info("converter:{}", converter)); } }
这里WebMvcConfiguration中展示了对应的两个实现方法。具体的实现步骤与第一种基本相同。也是先创建FastJsonHttpMessageConverter,然后添加到converters当中。具体操作就是将上面的代码复制过来,调用converters的add方法把FastJsonHttpMessageConverter对象添加进去。
具体示例如下:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 定义一个convert转换消息的对象 FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); // 添加fastJson的配置信息 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); // 处理中文乱码问题 List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON); // 在convert中添加配置信息 converter.setSupportedMediaTypes(fastMediaTypes); converter.setFastJsonConfig(fastJsonConfig); converters.add(converter); }
但是这两个方法和之前的方法又有所不同。在configureMessageConverters方法中,如果未添加任何转换器,则会注册默认的转换器列表。如果添加,则默认的转换器则关闭。
如果是简单地添加一个转换器而不影响默认注册,则可考虑使用extendMessageConverters方法代替。extendMessageConverters方法是一个钩子函数,当配置完转换器后才会调用该方法,可进行扩展和修改,允许注册默认转换器,然后通过此方法插入自定义转换器。
针对在configureMessageConverters方法需要注意的是,默认情况上述代码添加的FastJsonHttpMessageConverter并不会生效,因为它的优先级在最后,依旧会采用默认的Jackson进行转换。同时,上述代码在springboot中执行时你会发现并没有像上面描述的那样会关闭默认转换器。
这是为什么呢?Springboot与普通springmvc项目的不同在于springboot有默认的springmvc配置,比如WebMvcAutoConfigurationAdapter等。
因此,默认的mvc配置会调用WebMvcConfigurationSupport的addDefaultHttpMessageConverters方法,会添加上面的默认HttpMessageConverter。所以,如果仅仅通过@Configuration注解是无法覆盖掉所有的HttpMessageConverters的。
如果想要屏蔽掉,则需在Configration类上面增加@EnableWebMvc注解,但不推荐如此,因为会同时屏蔽掉其他功能的默认配置。
拓展
关于上述三种形式,还有一些拓展相关的小经验。
通过第一种方式可以重新定义Json的转换器并获得高优先级;
通过第二种形式(configureMessageConverters方法)默认情况下虽然可以添加转换器,但是由于优先级较低,会被Jackson的优先处理,可以遍历列表移除默认的Jackson;
使用如下操作:
// 清除默认Json转换器 converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter);
第三中方式(extendMessageConverters方法)也可以添加,但默认优先级也较低,同样可以通过遍历移除默认Jackson的转换器。官方建议extendMessageConverters优先于configureMessageConverters方法。
更多本系列课程学习:https://blog.csdn.net/wo541075754/category_9622539.html?utm_source=ffzl_BWzd
SpringBoot技术视频
CSDN学院:《Spring Boot 视频教程全家桶》
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2020/01/07/springboot2-x-httpmessageconverter/