繁体   English   中英

如何配置 spring boot 2 默认返回 xml?

[英]How do you configure spring boot 2 to return xml by default?

首先,我读过这个:

Spring 启动 - 如果请求中不存在,则设置默认内容类型 header

旧版本在 spring 启动 1 上工作。但是,当接收到以下请求时,接受 header Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"

响应在 json 中。

我放了一个 class

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void configureContentNegotiation(
            ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_XML);
    }

}

我可以看到正在设置 defaultContentType 策略。 但是它被 AcceptHeaderConfig 策略覆盖。

看起来 defaultContentType 仅用作后备。

请注意,spring 引导 1 中的相同代码有效并且默认为 XML。


完整示例

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.annotation.XmlRootElement;

@SpringBootApplication
@RestController
public class CnApp {

    @RequestMapping("/")
    public Person person(HttpServletRequest request, ModelMap model){
        return new Person();
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(CnApp.class, args);
    }

    @XmlRootElement
    public static class Person {
        public String firstName = "Jon";
        public String lastName = "Doe";
    }

    @Configuration
    public static class ServerConfig implements WebMvcConfigurer {
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.defaultContentType(MediaType.APPLICATION_XML);
        }

    }

}

正如您通过运行curl localhost:8080 -H"Accept: text/html, image/gif, image/jpg;q=0.2, */*;q=0.2"它默认为 json 即使 Z33061BB093D9B363


从我在下面发布的评论中

问题在于旧版本的 spring 我们可以发送接受 header 并获取默认为 XML 的请求。 但是 JSON 仍然受支持。

因此,当接受 header 进来,它同时支持 JSON 和 XML 时,我们需要返回 Z350867093D9BCFED100867B093D3501BB093D363810B671059B9CFED3F8Z。

您的WebMvc配置与您配置的一样正常工作。

如果没有Accept header 存在,则使用默认ContentType

要到达您的 scope,您必须使用内容协商策略打开 go,并禁用接受 header。 您的configureContentNegotiation方法应如下所示:

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false)
    .parameterName("mediaType")
    .ignoreAcceptHeader(true)
    .useJaf(false)
    .defaultContentType(MediaType.APPLICATION_XML)
    .mediaType("xml", MediaType.APPLICATION_XML;
}

您可以查看 Spring 博客上的这篇文章和 Baeldung 上的这篇文章。

对此进行进一步调查。 @thepaoloboi 在他的回答中建议的是正确的 defaultMessageConverter 只有在没有发生其他形式的内容协商时才会发生。

为了解决这个问题,我逐步完成了org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor使用的代码,我看到它依赖于已配置的转换程序的顺序。

因此,作为 hack,以下内容在 spring 1 和 spring 2 中都有效。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2CollectionHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@SpringBootApplication
@RestController
public class CnApp {

    @RequestMapping("/")
    public Person person(HttpServletRequest request, ModelMap model){
        return new Person();
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(CnApp.class, args);
    }

    @XmlRootElement
    public static class Person {
        public String firstName = "Jon";
        public String lastName = "Doe";
    }

    @Configuration
    public static class ServerConfig extends WebMvcConfigurerAdapter {
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.defaultContentType(MediaType.APPLICATION_XML);
        }

        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

            converters.add(0, new Jaxb2CollectionHttpMessageConverter<>());
            converters.add(0, new Jaxb2RootElementHttpMessageConverter());
            System.out.println("Converters:" + converters);
        }
    }

}

其工作原理是设置 Jaxb2 转换器的优先级高于 jackson 转换器。

这可以测试如下

curl localhost:8080 -H"Accept: text/html, image/gif, image/jpg;q=0.2, */*;q=0.2"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><firstName>Jon</firstName><lastName>Doe</lastName></person>%

curl localhost:8080 -H"Accept: text/html, image/gif, image/jpg;q=0.2, application/json, */*;q=0.2"
{"firstName":"Jon","lastName":"Doe"}%            

请注意,如果 application/json 在 header 中的任何位置指定,这仍然是首选。

这仍然感觉像是一种 hack,如果有一种方法可以对首选的 mime 类型进行排序而不求助于添加或重新排序转换器,那就太好了

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM