spring boot中@restcontroller默认依赖jackson并倾向返回json,但支持xml响应;需引入jackson-dataformat-xml、配置正确注解及避免@enablewebmvc干扰内容协商。

Spring Boot 中 @RestController 默认只返回 JSON?
不是默认只返回 JSON,而是默认依赖 Jackson,且客户端请求头没明确指定时,它倾向用 application/json 响应。但只要客户端发来 Accept: application/xml,Spring Boot 也能自动转成 XML——前提是项目里有 XML 序列化支持(比如 jackson-dataformat-xml 或 spring-boot-starter-web 自带的 JAXB 依赖)。
常见错误现象:406 Not Acceptable 错误,或者返回 JSON 却期望 XML;根本原因是类路径下缺 XML 处理器,或实体类没加必要注解。
- 确保引入了
com.fasterxml.jackson.dataformat:jackson-dataformat-xml(推荐),或保留 JDK 8+ 的javax.xml.bind:jaxb-api(JDK 11+ 需额外加) - 实体类字段必须是 public getter/setter,或加
@JsonProperty(JSON)和@JacksonXmlProperty(XML)显式控制字段名 - 避免混用
@XmlRootElement(JAXB)和 Jackson 注解,容易冲突;统一用 Jackson 的@JacksonXmlRootElement
Content-Type 和 Accept 头怎么影响响应格式?
Spring Boot 的内容协商(Content Negotiation)靠这两个头驱动:Accept 告诉服务端“我要什么”,Content-Type 是请求体类型(对 GET 无效)。服务端按 Accept 列表顺序匹配可用的 HttpMessageConverter。
典型场景:Postman 测试时忘了设 Accept: application/xml,结果一直拿到 JSON;或者前端 Axios 没配 headers: { Accept: 'application/xml' },后端根本收不到切换信号。
- 浏览器地址栏直接访问接口,默认
Accept: text/html,*/*,Spring 会 fallback 到 JSON(不是 XML) - 用
curl -H "Accept: application/xml"测试最可靠 - 如果想强制返回 XML,可在方法上加
@RequestMapping(produces = "application/xml"),但会丢掉协商灵活性
为什么加了 @EnableWebMvc 后 XML 不生效?
加了 @EnableWebMvc 就等于放弃 Spring Boot 自动配置的 WebMvcConfigurationSupport,包括默认注册的 Jackson2ObjectMapperBuilder 和 MappingJackson2XmlHttpMessageConverter。此时 XML 转换器不会自动加载,哪怕你引了依赖。
错误表现:所有接口都只返回 JSON,Accept: application/xml 完全被忽略,日志里也看不到 XML converter 初始化记录。
- 删掉
@EnableWebMvc是最简单解法(除非你真需要完全自定义 MVC 配置) - 如果必须保留,就得手动注册
MappingJackson2XmlHttpMessageConverter,并在configureMessageConverters里 add 进去 - 注意:手动注册时,要确保
MappingJackson2XmlHttpMessageConverter在MappingJackson2HttpMessageConverter(JSON)之前,否则协商时 JSON 总是优先匹配
返回 XML 时中文乱码或根节点名不对?
Jackson XML 序列化默认用 UTF-8,但若响应头没带 charset=utf-8,某些老客户端(如 IE、部分 Java HttpClient)可能当 ISO-8859-1 解析;另外,根元素名默认取类名,不加注解就是 <user></user>,而不是你想要的 <user></user> 或 <response></response>。
- 在
application.properties加spring.http.converters.preferred-json-mapper=jackson(不影响 XML),再配server.servlet.context-path=等无关项没用,重点是 converter 配置 - 用
@JacksonXmlRootElement(localName = "user")控制根节点名 - 确保 response header 包含
Content-Type: application/xml;charset=UTF-8—— Spring Boot 2.3+ 默认已带,老版本可加@Configuration注册StringHttpMessageConverter并设setDefaultCharset(StandardCharsets.UTF_8)
复杂点在于:同一个实体既要被 JSON 用,又要被 XML 用,注解得兼顾两边;比如 @JsonProperty("user_id") 和 @JacksonXmlProperty(localName = "user-id") 写法不同,稍不注意就漏一个,导致某一种格式字段消失。










