【问题标题】:Spring4 @RequestBody required doesn't work所需的 Spring4 @RequestBody 不起作用
【发布时间】:2016-04-07 06:35:43
【问题描述】:

我已经将 Spring 版本从 4.0.x 升级到 4.2.3(刚刚是 4.2.4),突然,@RequestBody 注释中的“required = false”属性无法按预期工作(就像在版本更改之前一样)。

带有 HttpStatus 415 的服务器响应 - 不支持的媒体类型。

控制器方法(每个 Spring 版本都相同)。

@RequestMapping(value = "/entity/{entityId}/{from}/{size}", method = RequestMethod.POST)
@ResponseBody
@JsonView(ToShowIn.App.class)
public ResponseEntity<?> getActiveEntityPaged(
    @PathVariable int entityId, @PathVariable int from, @PathVariable int size, 
    @RequestBody(required = false) EntityFilterParam entityFilterParam) {

    ...
}

真的,这不是问题,因为从客户端,避免发送空,例如,设置空EntityFilterParam 实例足以解决它。但我想了解这个令人烦恼的问题是因为我的概念错误,还是因为新 Spring 版本的错误。

更新#1

版本

<spring-version>4.2.4.RELEASE</spring-version>
<jackson-2-version>2.3.2</jackson-2-version>

请求来自 Android 设备,使用 spring-android 库 (AKA RestTemplate)。

通用方法,适用于 4.0.x 版本,EntityFilterParam 可以为空。

super.doRestList(
    new HttpEntity<EntityFilterParam>(EntityFilterParam, this.getHttpHeaders()),
    HttpMethod.POST,
    urlBuilder);

在 4.2.3 和 4.2.4 上,为解决此问题,EntityFilterParam 不能为空。 -> HttpStatus 415 - 不支持的媒体类型。修复它。

super.doRestList(
    new HttpEntity<EntityFilterParam>((EntityFilterParam != null) ? EntityFilterParam : new EntityFilterParam(), this.getHttpHeaders()),
    HttpMethod.POST,
    urlBuilder);

在doRestList内部,执行RestTemplate请求。

final ResponseEntity<E[]> responseEntity =
    (ResponseEntity) super.getRestTemplate()
        .exchange(urlBuilder.getURL(), httpMhetod,
            requestEntity, this.entityArray.getClass());

在哪里,urlBuilder.getURL()(URL 字符串,这里@PathVariables 工作正常)和this.getHttpHeaders() 返回下一个 HttpHeaders 配置。

RestFactory.httpHeaders = new HttpHeaders();

RestFactory.httpHeaders.setAuthorization(this.getAuthorization(user));
RestFactory.httpHeaders.set(HttpHeaders.CONNECTION, "Close"); // Switch off keep-alive.
RestFactory.httpHeaders.set(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.8");
RestFactory.httpHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

super.getRestTemplate() 是单例方法,它返回使用我自己的 CloseableHttpClient 配置设置的 RestTemplate 实例。

我知道HttpHeaders.CONTENT_TYPE对于application/json是缺失的,但是有意识的,其实在http body的payload不为空的时候有效,为空的时候就失败了。

发生错误时,在请求流进入控制器方法之前执行415,因此不执行任何操作。

更新#2

另一个有趣的点,Jackson2 将 null 值序列化为“null”字符串,那么 body 的 payload 就不是 null,而是用“null”填充。

【问题讨论】:

  • “已经停止工作”是什么意思?当你省略身体时,你会得到一个例外吗?你得到什么错误?
  • 服务器返回 415 Http 状态(不支持的媒体类型)。
  • 令人惊讶,因为我报告了这个错误,并且它已在 4.2.2 中修复。见jira.spring.io/browse/SPR-13417
  • 因此,在 4.2.3 和 4.2.4 中,该错误又回来了。 :(
  • 对 SPR-13417 的修复还附带了一个单元测试,它仍然是绿色的。我已经尝试过以前的 repro 项目 (github.com/spring-projects/spring-framework-issues/tree/master/…),它仍然适用于 4.2.2、4.2.3 和 4.2.4。您能否提供有关此问题的更多详细信息:HTTP 请求标头,Jackson 视图的代码示例 + Controller 方法返回的对象?

标签: spring rest spring-mvc


【解决方案1】:

我已经尝试重现这个确切的问题,但没有多大成功。

您确认使用 curl 命令时问题仍然存在吗? curl -vvv -X POST https://example.com/entity/12/50/10 之类的东西(如果是,请在此处粘贴输出)

对于spring-android 中的RestTemplate,我不是100% 的,但如果没有提供内容类型,则模板默认添加"Content-Type: application/x-www-form-urlencoded"。如果是这种情况,为"org.springframework.web" 配置"DEBUG" 日志级别应该显示类似

[INFO] [talledLocalContainer] org.springframework.web.HttpMediaTypeNotSupportedException: 
Content type 'application/x-www-form-urlencoded' not supported

我认为无论如何你都应该设置 Content-Type。您提到这样做失败了-您能详细说明一下吗?

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 2018-09-07
  • 1970-01-01
  • 2017-10-14
  • 2018-05-25
  • 2019-02-13
相关资源
最近更新 更多