SpringBoot项目 整合 JacksonXml

一、需求场景:

有个需求场景:同一个请求路径,入参类型分别有“JSON格式”和“XML格式”的入参,需要根据入参类型的不同,处理不同的业务场景,然后返回对应格式的返回。值。比如:

​ JSON格式入参,返回JSON格式的返回值。

​ XML格式入参,返回XML格式的返回值。

印象中是可以区分的,然后网上搜索了资料完善了解决方案,好记性不如烂笔头,现在梳理一下如下:

二、解决方案

第一种方案:SpringMvc 自定义 XML的 HttpMessageConverter 转换器。

自定义转换器的方式本身没有问题,自己写一个 继承 ObjectMapper 类的xmlMapper就能实现。一开始我是用的这个,后来发现这样写很多余,因为 ObjectMapper 我是引用了"com.fasterxml.jackson.dataformat.xml.XmlMapper" ,实际上完全可以不用自己写,原因是 :如果引入了"com.fasterxml.jackson.dataformat.xml.XmlMapper"依赖,SpringMVC会自动加载XML转换器,优先级是XML优先。更优的办法详见第二种方式。

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    /**
     * 新增自定义转换器
     * @param converters {@link List<HttpMessageConverter<?>>}
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2XmlHttpMessageConverter xmlConverter = new MappingJackson2XmlHttpMessageConverter();
        XmlMapper xmlMapper = new XmlMapper();
        xmlConverter.setObjectMapper(xmlMapper);
        //新增 xml转换器,设置顺序为0
        converters.add(0,xmlConverter);
    }
}

第二种方案:直接引入XML 转换器的依赖

SpringBoot项目,可以在 Pom.xml 中直接引入**" jackson-dataformat-xml"** 依赖。

<!-- Springboot默认使用json格式解析参数,如果需要支持xml入参,则需要引入 'jackson-dataformat-xml'依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <!-- 注意版本应该与 Springboot版本匹配。看SpringBoot版本发布日期去Maven找对应的版本号 -->
    <version>${jackson-dataformat-xml.version}</version>
</dependency>

定义同一个名为"/test"的请求,通过指定“consumes” 和“produces”属性区分JSON格式和XML格式的控制,注意方法名要不一样。

      /**
      * 示例:
      * 接收JSON格式的入参,并返回JSON格式的返回值
     * consumes:指入参的 MediaType类型,这里设置为:接收UTF-8的JSON格式,
     * produces:指返回值的MediaType类型,这里设置为:返回UTF-8的JSON格式。
     */
    @PostMapping(value = "/test",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public JSONObject Json(@RequestBody JSONObject requestJsonObject) {
       //业务代码,略
    }

      /**
      * 示例:
      * 接收XML格式的入参,并返回XML格式的返回值
     * consumes:指入参的 MediaType类型,这里设置为:接收XML格式,
     * produces:指返回值的MediaType类型,这里设置为:返回XML格式。
     */
    @PostMapping(value = "/test",consumes = MediaType.APPLICATION_XML_VALUE,produces = MediaType.APPLICATION_XML_VALUE)
    public JSONObject Xml(@RequestBody JSONObject requestJsonObject) {
      //业务代码,略
    }

三、源码分析:SpringMVC ,默认的设置的 MediaType的顺序

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    private static final boolean romePresent =
            ClassUtils.isPresent("com.rometools.rome.feed.WireFeed",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jaxb2Present =
            ClassUtils.isPresent("javax.xml.bind.Binder",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jackson2Present =
            ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
                    WebMvcConfigurationSupport.class.getClassLoader()) &&
            ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jackson2XmlPresent =
            ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jackson2SmilePresent =
            ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jackson2CborPresent =
            ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean gsonPresent =
            ClassUtils.isPresent("com.google.gson.Gson",
                    WebMvcConfigurationSupport.class.getClassLoader());

    private static final boolean jsonbPresent =
            ClassUtils.isPresent("javax.json.bind.Jsonb",
                    WebMvcConfigurationSupport.class.getClassLoader());


    protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316

        messageConverters.add(new ByteArrayHttpMessageConverter());
        messageConverters.add(stringHttpMessageConverter);
        messageConverters.add(new ResourceHttpMessageConverter());
        messageConverters.add(new ResourceRegionHttpMessageConverter());
        messageConverters.add(new SourceHttpMessageConverter<>());
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());

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

        if (jackson2XmlPresent) {
            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }
            // 新增 XML 转换器
            messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
        }
        else if (jaxb2Present) {
            messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
        }

        if (jackson2Present) {
            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }
            // 新增 JSON 转换器
            messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        }
        else if (gsonPresent) {
             // 新增 Gson 转换器
            messageConverters.add(new GsonHttpMessageConverter());
        }
        else if (jsonbPresent) {
            // 新增 Jsonb 转换器
            messageConverters.add(new JsonbHttpMessageConverter());
        }

        if (jackson2SmilePresent) {
            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }
            //新增 Smile 转换器
            messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
        }
        if (jackson2CborPresent) {
            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
            if (this.applicationContext != null) {
                builder.applicationContext(this.applicationContext);
            }
            //新增 Cbor 转换器
            messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
        }
    }
}

从源码看,导入了对应的依赖,比如 “jackson-dataformat-xml” ,依赖包会有 "com.fasterxml.jackson.dataformat.xml.XmlMapper"类被SpringMVC找到,

然后就会自动加到 messageConverters 转换器中,顺序就是代码add的顺序, XML > Json > Gson > Jsonb > Smile > Cbor

参考网站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值