Accept 头到底怎么决定返回 JSON 还是 XML?为什么返回 String 时 Content-Type 说是 json 内容却不是?.json 后缀还能用吗?406 和 415 有什么区别?这篇在 Spring Boot 4.0.8 的 Spring MVC 7.0.9 上逐个请求验证。
GET /n/user (无 Accept) → 200 [application/json] {"name":"Tom","age":20}
GET /n/user Accept: */* → 200 [application/json] {"name":"Tom","age":20}
GET /n/user Accept: application/json → 200 [application/json] {"name":"Tom","age":20}
GET /n/user Accept: application/xml → 200 [application/xml;charset=UTF-8] <User><name>Tom</name><age>20</age></User>
GET /n/user Accept: application/json;q=0.5, application/xml;q=0.9 → 200 [application/xml;charset=UTF-8] <User><name>Tom</name><age>20</age></User>
GET /n/user Accept: text/html → 406 [text/html;charset=UTF-8] <html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are s
GET /n/user Accept: text/plain → 406 [-]
GET /n/user Accept: application/xml, application/json → 200 [application/xml;charset=UTF-8] <User><name>Tom</name><age>20</age></User>q 值大的赢,没有 Accept 或 */* 取第一个能写出该对象的转换器。
GET /n/str (无 Accept) → 200 [text/plain;charset=UTF-8] plain-string GET /n/str Accept: application/json → 200 [application/json] plain-string GET /n/str Accept: text/plain → 200 [text/plain;charset=UTF-8] plain-string GET /n/str Accept: application/xml → 200 [application/xml;charset=UTF-8] plain-string GET /n/str Accept: text/html → 200 [text/html;charset=UTF-8] plain-string
String 返回值原样写出,只是按 Accept 贴 Content-Type。
GET /n/json-only Accept: application/xml → 406 [application/xml;charset=UTF-8] <Map><timestamp>2026-10-19T03:38:12.497Z</timestamp><status>406</status><error>Not Acceptable</error><path>/n/
GET /n/json-only Accept: application/json → 200 [application/json] {"name":"Tom","age":20}
GET /n/json-only (无 Accept) → 200 [application/json] {"name":"Tom","age":20}
GET /n/two Accept: application/json → 200 [application/json] {"from":"json-method"}
GET /n/two Accept: application/xml → 200 [application/xml;charset=UTF-8] <from>xml-method</from>
GET /n/two Accept: text/plain → 406 [-]
GET /n/two (无 Accept) → 200 [application/json] {"from":"json-method"}
GET /n/entity Accept: application/json → 200 [application/xml] <User><name>Tom</name><age>20</age></User>
GET /n/entity Accept: application/xml → 200 [application/xml] <User><name>Tom</name><age>20</age></User>produces 参与映射;ResponseEntity 显式指定则不再协商。
GET /n/user.json (无 Accept) → 404 [application/json] {"status":404,"error":"Not Found","path":"/n/user.json"}
GET /n/user.xml (无 Accept) → 404 [application/json] {"status":404,"error":"Not Found","path":"/n/user.xml"}
GET /n/user?format=xml (无 Accept) → 200 [application/json] {"name":"Tom","age":20}
GET /n/user?format=json Accept: application/xml → 200 [application/xml;charset=UTF-8] <User><name>Tom</name><age>20</age></User>路径后缀不再识别;?format= 默认也不识别。
GET /n/user?format=xml (无 Accept) → 200 [application/xml;charset=UTF-8] <User><name>Tom</name><age>20</age></User>
GET /n/user?format=json Accept: application/xml → 200 [application/json] {"name":"Tom","age":20}
GET /n/user?format=csv (无 Accept) → 406 [-] favor-parameter 打开后参数优先于 Accept。
POST /n/in (无 Accept) Content-Type: application/json → 200 [text/plain;charset=UTF-8] json-in User[name=Tom, age=20]
POST /n/in (无 Accept) Content-Type: application/xml → 415 [application/json] {"status":415,"error":"Unsupported Media Type","path":"/n/in"}
POST /n/in (无 Accept) Content-Type: text/plain → 415 [application/json] {"status":415,"error":"Unsupported Media Type","path":"/n/in"}
POST /n/in (无 Accept) → 415 [application/json] {"status":415,"error":"Unsupported Media Type","path":"/n/in"}
POST /n/any (无 Accept) Content-Type: application/xml → 200 [text/plain;charset=UTF-8] any-in User[name=Tom, age=20]
POST /n/any (无 Accept) Content-Type: text/plain → 415 [application/json] {"status":415,"error":"Unsupported Media Type","path":"/n/any"}Content-Type 不满足是 415。