首先,我已经阅读了以下内容:
Spring引导-设置默认的Content-type头,如果它';s不在请求中
这个旧版本适用于弹簧靴1。然而,当接收到具有以下接受标头Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
的请求时
响应是json格式的。
我已经放了一个类
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_XML);
}
}
我可以看到defaultContentType策略正在设置中。然而,它被AcceptHeaderConfig策略覆盖。
看起来defaultContentType只被用作回退。
请注意,spring-boot 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"
即使XML是默认的,它也默认为json
根据我在下方发布的评论
问题是,对于旧版本的spring,我们可以使用accept头发送,并获取默认为XML的请求。但是JSON仍然受到支持。
因此,当一个accept标头同时支持JSON和XML时,我们需要返回XML。
您的WebMvc
配置和您配置的一样工作。
如果不存在Accept
标头,则使用默认的ContentType
。
要达到您的范围,您必须继续使用内容协商策略,并禁用Accept标头。您的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
使用的代码,我发现它取决于已配置的覆盖器的顺序。
因此,作为一个破解,以下内容在弹簧1和弹簧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在标头中的任何位置指定,那么这仍然是首选。
这仍然感觉像是一次黑客攻击,如果有一种方法可以对首选的mime类型进行排序,而不需要添加或重新排序转换器,那就太好了