在篇文章中介绍了自定义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 视频教程全家桶》



SpringBoot2.x系列教程(十八)HttpMessageConverter实战及经验插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://choupangxia.com/2020/01/07/springboot2-x-httpmessageconverter/