zoukankan      html  css  js  c++  java
  • Spring Boot应用的Controller返回的集合类数据是XML格式的可能原因

      今天使用Eureka Client的时候发现Controller打了@RestController注解,对于返回值是集合类的API接口,其数据还是会被系列化成XML格式:

        @GetMapping("/user-instance")
        public List<ServiceInstance> showUserServiceInfo() {
            return this.discoveryClient.getInstances("provider-user-metadata");
        }

      结果:

    <List>
        <item>
            <scheme>http</scheme>
            <host>192.168.0.102</host>
            <port>8000</port>
            <metadata>
                <author>xurm</author>
                <management.port>8000</management.port>
                <age>26</age>
            </metadata>
        </item>
    </List>

      经过排查发现是spring-cloud-starter-netflix-eureka-client的Maven依赖间接引入了jackson-dataformat-xml包,而如果Spring的http消息转换器(HttpMessageConverter)使用了该包会,那么它会根据http请求头上的Accept来决定返回XML还是JSON。然而目前大多数浏览器在没有额外设置的情况下,默认的Accept值都是"text/html,application/xhtml+xml,application/xml",这就使得直接在浏览地址栏访问接口时,我们心里预期要返回JSON的返回了XML,因为JSON和XML格式是可以互转的!

      但是如今应用开发使用JSON方便一些,特别是与前端数据交换的时候,可以直接用上JS与JSON的无缝对接优势,所以得把返回值改成JSON才行,方法有多种,这里介绍两种:

      第一种是:如果你的应用不会再需要返回xml的系列化格式,那么直接在pom.xml文件中将jackson-dataformat-xml这外包排除即可(如果其他包也进行了jackson-dataformat-xml的依赖引用也要视情况排除):

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
                <version>2.2.3.RELEASE</version>
                <exclusions>
                    <exclusion>
                        <groupId>com.fasterxml.jackson.dataformat</groupId>
                        <artifactId>jackson-dataformat-xml</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

      刷新maven,重新启动应用,再次访问相应接口:

    [{
        "scheme": "http",
        "host": "192.168.0.102",
        "port": 8000,
        "secure": false,
        "metadata": {
            "author": "xurm",
            "management.port": "8000",
            "age": "26"
        }
    }]

      第二种是:不排除jackson-dataformat-xml包,而是直接在相应接口方法或Controller上明确指定将返回JSON格式的值:

        @GetMapping(value = "/user-instance", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
        public List<ServiceInstance> showUserServiceInfo() {
            return this.discoveryClient.getInstances("provider-user-metadata");
        }

      从上面的问题原理可知:项目里一个接口是可以同时支持返回XML和JSON的,只要在Accept中声明你要XML(application/xml)还是要JSON(application/json)。当然也有借助第三方包(jackson-jaxrs-xml-provider),然后通过URL后缀是*.json还是*.xml来返回JSON还是XML的做法!如果要让接口同时支持返回XML和JSON,就不能再在接口方法上明确指定将返回什么格式的值了

        @GetMapping(value = "/user-instance")
        public List<ServiceInstance> showUserServiceInfo() {
            return this.discoveryClient.getInstances("provider-user-metadata");
        }

      最后,其实还可以通过添加自定义的Spring的http消息转换器(HttpMessageConverter)的方法来定制返回值的系列化,方法就是实现WebMvcConfigurer,并重写configureMessageConverters方法,例如换用阿里的Fastjson来做http消息转换:

        /**
         * 消息转换器自定义配置,向当前的Http消息转换器列表增加阿里云的FastJson消息转换器
         *
         * @param converters 当前的Http消息转换器列表对象
         */
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
            fastJsonConfig.setCharset(Charset.forName("GB2312"));//解决中文系列化后成乱码
            fastJsonConverter.setFastJsonConfig(fastJsonConfig);
            //converters.add(fastJsonConverter);//这会让fastJsonConverter排在消息转换器管道列表的最后,可能会轮不到它处理消息转换
            converters.add(0, fastJsonConverter);//要显示指明将fastJsonConverter排在消息转换器管道列表的首位
        }

      pom.xml中引入Fastjson的依赖:

            <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.70</version>
            </dependency>
  • 相关阅读:
    robotframework +selenium 自动化测试之浏览器与驱动的兼容问题。
    robotframework+selenium自动化robotramework版本问题
    一个业务逻辑引发的对多表连接的思考
    第一次接触WebSocket遇到的坑以及感受
    关于读写APP.config文件能读却写不了的问题
    poj2392 space elevator
    洛谷P1197 星球大战
    poj3421&poj3292&poj2689 基础数论
    洛谷P1006 传纸条
    挑战程序设计竞赛2.3节习题选解
  • 原文地址:https://www.cnblogs.com/xuruiming/p/13283288.html
Copyright © 2011-2022 走看看