我使用的是最新的Sping Boot (1.2.1)和它附带的任何Spring MVC版本。
我有一个控制器方法,它对传入和传出数据都进行隐式JSON转换:
@RestController
public class LoginController {
@RequestMapping(value = "/login", method = POST, produces = "application/json")
ResponseEntity<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
// ...
}
}
这是正常的,但只有当请求Content-Type
被设置为application/json
时,它才能正常工作。在所有其他情况下,无论请求主体是什么,它都会以415响应:
{
"timestamp": 1423844498998,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'text/plain;charset=UTF-8' not supported",
"path": "/login/"
}
问题是,我想让我的API更宽松;我希望Spring*只 * 使用POST请求主体,完全忽略Content-Type
头。(如果请求主体不是有效的JSON或者不能解析为LoginRequest示例,Spring已经用400 Bad Request响应,这很好。)在继续使用隐式JSON转换(通过Jackson)时,这是可能的吗?
我尝试过consumes="*"
和其他类似consumes = {"text/*", "application/*"}
的变体,但没有效果:如果Content-Type
不是JSON,则API会继续给出415。
编辑
看起来此行为是由MappingJackson2HttpMessageConverter引起的,其文档中指出:
默认情况下,此转换器支持application/json
和application/*+json
。可以通过设置supportedMediaTypes
属性重写此设置。
我仍然不知道 * 如何确切 * 我定制,例如在一个custom Jackson2ObjectMapperBuilder...
3条答案
按热度按时间t0ybt7op1#
我假设您使用的是Spring提供的默认
MappingJackson2HttpMessageConverter
。如果你想在所有的请求中都有相同的行为,一个解决方案是编写自定义的转换器,它不会在头中查找
Content-Type
(而是总是解析为JSON),然后配置Spring使用你的自定义转换器。同样,这将影响所有的请求,所以可能不适合所有的需求。}
要自定义媒体类型,
wfveoks02#
对于其他任何对此感到好奇的人来说;
可以通过覆盖
WebMvcConfigurerAdapter.extendMessageConverters
来自定义所使用的MappingJackson2HttpMessageConverter
,以允许多种mime类型。但是,它没有按预期工作,因为
application/x-www-form-urlencoded
在ServletServerHttpRequest.getBody
中进行了硬编码,以便在将其传递到MappingJackson2HttpMessageConverter
之前将正文修改为URL编码(即使post数据是JSON)。如果您真的需要这样做,那么我认为唯一的方法是在处理之前放置一个修改请求内容类型头部的
Filter
(并不是暗示这是一个好主意,只是在必要的情况下)。o3imoua43#
更新:小心你用这个
(This这可能是一个愚蠢的想法。)
这样做的副作用是服务器将**response
Content-Type
**设置为请求的Accept
头中的第一个值!(例如,text/plain
而不是正确的application/json
。)在注意到这一点后,我摆脱了这种定制,并解决了Spring的默认行为(如果请求没有正确的
Content-Type
,则响应415错误)。原文回答:
MappingJackson2HttpMessageConverter javadocs声明:
默认情况下,此转换器支持
application/json
和application/*+json
。可以通过设置supportedMediaTypes
属性重写此设置。......这给我指出了一个非常简单的解决方案,似乎工作。在主应用程序类:
(CustomObjectMapper与我拥有的其他Jackson自定义相关;该构造函数参数是可选的。)
这确实会影响所有请求,但到目前为止,我在我的应用程序中没有看到任何问题。如果这成为一个问题,我可能只是将
@RequestBody
参数切换为String,并手动将其反序列化。