admin管理员组

文章数量:1538170

文章目录

一、何为消息转换器

二、默认的消息转换器

三、SpringBoot配置自定义消息转换器

1. 注册fastjson消息转换器

2. 将消息转换器配置到集合中

四、注意事项

五、总结


一、何为消息转换器

要想理解消息转换器,首先得知道消息是什么,在使用SpringMVC框架时,由前端发请求给后端,请求体中的内容就被称为消息,另外反过来,由后端发给前端的响应数据也是消息,那消息转换器又是来干嘛的呢?其实就是实现消息与Java对象的相互转换,将请求体中的消息转为Java对象,反过来将Java对象转为响应体中的消息,所以其实SpringMVC中的@RequestBody和@ResponseBody注解就是干的这个事。

二、默认的消息转换器

在SpringBoot项目中由于导入了web-start依赖,在org.springframework.web.servlet.config.annotation包下面的WebMvcConfigurationSupport类,在这个下面有个addDefaultHttpMessageConverters方法就是设置默认的消息转换器集合。下面是源码:

    protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        messageConverters.add(new ByteArrayHttpMessageConverter());
        messageConverters.add(new StringHttpMessageConverter());
        messageConverters.add(new ResourceHttpMessageConverter());
        messageConverters.add(new ResourceRegionHttpMessageConverter());
        if (!shouldIgnoreXml) {
            try {
                messageConverters.add(new SourceHttpMessageConverter());
            } catch (Throwable var3) {
            }
        }

        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        if (romePresent) {
            messageConverters.add(new AtomFeedHttpMessageConverter());
            messageConverters.add(new RssChannelHttpMessageConverter());
        }

        Jackson2ObjectMapperBuilder builder;
        if (!shouldIgnoreXml) {
            if (jackson2XmlPresent) {
                builder = Jackson2ObjectMapperBuilder.xml();
                if (this.applicationContext != null) {
                    builder.applicationContext(this.applicationContext);
                }

                messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
            } else if (jaxb2Present) {
                messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
            }
        }

        if (kotlinSerializationJsonPresent) {
            messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
        }

        if (jackson2Present) {
            builder = Jackson2ObjectMapperBuilder.json();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }

            messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        } else if (gsonPresent) {
            messageConverters.add(new GsonHttpMessageConverter());
        } else if (jsonbPresent) {
            messageConverters.add(new JsonbHttpMessageConverter());
        }

        if (jackson2SmilePresent) {
            builder = Jackson2ObjectMapperBuilder.smile();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }

            messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
        }

        if (jackson2CborPresent) {
            builder = Jackson2ObjectMapperBuilder.cbor();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }

            messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
        }

    }

可以发现实际上是默认就添加了添加了以下4种消息转换器:

messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter());

下面还会根据需要添加:

MappingJackson2HttpMessageConverter、Jaxb2RootElementHttpMessageConverter之类的消息转换器

总之来说,根据实际需求添加合适的消息转换器。比如下面这部分代码:

    if (jackson2Present) {
            builder = Jackson2ObjectMapperBuilder.json();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }

            messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        } else if (gsonPresent) {
            messageConverters.add(new GsonHttpMessageConverter());
        } else if (jsonbPresent) {
            messageConverters.add(new JsonbHttpMessageConverter());
        }

该代码段首先检查是否存在Jackson2库。如果存在,则使用Jackson2ObjectMapperBuilder创建一个JSON消息转换器,并将其添加到消息转换器列表中。如果应用程序上下文已经存在,则将其传递给Jackson2ObjectMapperBuilder以便进行进一步的配置。
如果Jackson2库不可用,则检查是否存在Gson库。如果存在,则使用GsonHttpMessageConverter创建一个Gson消息转换器,并将其添加到消息转换器列表中。
如果Gson库也不可用,则检查是否存在JSON-B库。如果存在,则使用JsonbHttpMessageConverter创建一个JSON-B消息转换器,并将其添加到消息转换器列表中。

总结几种常见的消息转换器:

注意这里的读写内容都是指的HTTP消息内容,比如说读写JSON格式数据,就是HTTP消息是JSON格式, 读就是JSON格式字符串转Java对象,写就是Java对象转JSON字符串。

三、SpringBoot配置自定义消息转换器

首先明白,因为是基于SpringBoot进行配置,所以配置都是基于配置类进行配置,配置消息转换器是在WebMvcConfigure接口实现类中重写configureMessageConverters、或者是重写extendMessageConverters方法,具体这两个方法有什么不同,我在下面会进行说明

下面是一个相对简单的配置,如果有其它需求的,需要配置其它序列化特性的,我下面进行简单说明

1. 注册fastjson消息转换器

   @Bean
    public HttpMessageConverter fastJsonHttpMessageConverters() {
        //1.使用FastJson消息转换器对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //2.创建FastJson配置类对象
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        //3.通过配置类对象设置属性
        //"PrettyFormat"特性可以使得输出的JSON格式具有良好的可读性,即每个属性都单独占据一行,
        // 而不是将整个JSON字符串打印在一行中。这样做可以让JSON数据更加易读,方便人工阅读和调试
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //设置日期格式
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        //将Long类型数据转为字符串
        SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance);
        //为FastJson添加序列化配置实例
        fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance);
        //将FastJson配置添加到fastJSON消息转换器中
        fastConverter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter = fastConverter;
        return converter;
    }

2. 将消息转换器配置到集合中

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //将fastJson消息转换器添加到消息转换器集合中
        converters.add(fastJsonHttpMessageConverters());
    }

针对其它需求,还可以设置其它特性
1. 除了"PrettyFormat"特性外,Fastjson库还提供了很多其他的序列化特性,例如:WriteMapNullValue(输出空置字段)、WriteNullStringAsEmpty(String类型的空值输出为"")、WriteNullBooleanAsFalse(Boolean类型的空值输出为false)等等。这些特性可以根据实际情况进行设置,以满足具体的业务需求。

2. 除了ToStringSerializer,fastjson库还提供了其他的序列化方式,例如:

  • LongCodec:将Long类型的数据序列化为数字形式,默认的Long序列化方式。
  • JSONAwareSerializer:将实现了JSONAware接口的Java对象序列化为字符串形式。
  • MapSerializer:将Map类型的数据序列化为JSON对象。
  • ListSerializer:将List类型的数据序列化为JSON数组。
  • ArraySerializer:将数组类型的数据序列化为JSON数组。

四、注意事项

1. 在处理的过程中,一旦发现哪个消息转换器适合当前需求,就会使用这个消息转换器进行读写,就不会再去使用其它消息转换器了,这样做的目的是为了高效,减少无效的转换操作。

2. 如果想要自定义的消息转换器能够生效,就得放到同类型的第一个,理由如上。

3. 注意区分configureMessageConverters和extendMessageConverters方法的不同,前者会覆盖掉原有的消息转换器集合,而只保留当前的集合,因此如果使用了这个方法,就会覆盖掉默认的消息转换器集合,因此这里得注意配置了新的会不会引起功能的缺失,比如说默认的实际上是支持基本的@RequestBody,@ResponseBody功能的,配置了新的也要支持,不能让这两个注解失效。如果担心的化,可以使用extendMessageConverters方法配置消息转换器,这样就不会覆盖,确保了安全。

五、总结

1. 理解消息转换器的含义、作用

2. 学会使用基于SpringBoot方式对消息转换器进行配置

3. 了解基本的序列化特性,其实还是序列化与反序列那里的配置,和消息转换器本身没有关系,比如说ToStringSerializer、WriteNullStringAsEmpty(String类型的空值输出为"")等特性

4. 理解configureMessageConverters和extendMessageConverters方法的不同,选择合适的方法,另外理解执行消息转换器的流程,防止我们自定义的消息转换器失效。

总的来说明白消息转换器就是一种转换工具,其实还是序列化与反序列化的原理,基于这一原理的组件罢了,所以你配置相关序列化的特性,其实还是使用像Jackon、fastjson框架进行相关特性的配置。

本文标签: 转换器消息SpringBoot