【问题标题】:Spring @MVC and the @RequestBody annotation with x-www-form-urlencoded data?Spring @MVC 和带有 x-www-form-urlencoded 数据的 @RequestBody 注释?
【发布时间】:2013-05-03 04:23:47
【问题描述】:

我试图弄清楚为什么当 Spring @Controller 处理程序方法包含 @RequestBody 注释时,我无法接收来自 jQuery.ajax 调用的请求。考虑以下几点:

HTML/JavaScript

<form id="foo" action="/baz">
  <input name="bar">
</form>

<script>
  $(function() {
    var $fooForm = $('#foo');

    $fooForm.on('submit', function(evt) {
      evt.preventDefault();

      $.ajax({
        url: $fooForm.action,
        data: $fooForm.serialize(),
        dataType: 'json',
        type: 'POST',
        success: function(data) { console.log(data); }
      });
    });
  });
</script>

Java

@RequestMapping(
  value = "/baz",
  method = RequestMethod.POST,
  consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
  produces = MediatType.APPLICATION_JSON_VALUE
)
public @ResponseBody SearchResults[] jqueryPostHandler(
  @RequestBody FormDataObject formData)
{
  return this.searchService.find(formData);
}

上面的操作会因为@RequestBody注解而失败并返回一个415错误(不会产生异常)。但是如果@RequestBody注解被移除(即参数签名只是FormDataObject formData),那么该方法将被调用并且JSON将被返回给JavaScript。

为什么会这样? POST 请求包括请求正文中的数据。注释不应该处理这样的请求吗?

我意识到我可以将 JavaScript 发送的内容类型更改为 application/json 并将 consumes 属性更改为 MediaType.APPLICATION_JSON_VALUE 以使注释正常工作。但是为什么它不适用于普通的表单请求?

注意:我使用的是 Spring 3.1.4。

【问题讨论】:

标签: spring jquery spring-mvc


【解决方案1】:

您是否尝试过登录“org.springframework.web”以找出返回状态码的原因?在转换为 415 之前应该引发并记录一个异常。

另外,如果发送表单数据,为什么不直接忽略@RequestBody。然后,您将使用数据绑定(即@ModelAttribute)将 Servlet 请求参数应用于对象字段。这比使用 FormHttpMessageConverter 更可取。

【讨论】:

  • 打开日志记录表明,使用 @RequestBody 注释它确实映射到正确的方法,但它抛出“org.springframework.web.HttpMediaTypeNotSupportedException:内容类型'application/x-www-form-urlencoded;charset=UTF-8' 不支持”。
  • 根据我有限的理解,注解@RequestBody暗示要处理的数据会在请求体中。这会通知编译器阅读代码的人。所以,留下它会产生模棱两可的代码。这就是为什么我想知道为什么会失败。
【解决方案2】:

正如Spring Docs of @RequestBody 所说,请求正文将由HttpMessageConverter 转换为您的对象。

有 4 个默认的 HttpMessageConverters:

要转换 url 编码的形式,也就是 ajax.serialize() 创建,这是FormHttpMessageConverter 的工作。由于您有HttpMediaTypeNotSupportedException 异常,我猜您没有配置FormHttpMessageConverter。检查你的 spring 配置文件,这里是一个例子:

< bean class ="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
   < property name= "messageConverters" >
         < list>
             < ref bean= "mappingJacksonHttpMessageConverter" />
             < ref bean= "stringHttpMessageConverter" /> 
             <!-- Do you have this converter ? -->
             < ref bean= "formHttpMessageConverter" />
         </ list>
    </ property>
</ bean>

【讨论】:

  • 以上对我不起作用,即使我添加了所有转换器。我必须在stackoverflow.com/a/31083802/471213 使用自定义转换器才能使其工作
  • @usr-local-ΕΨΗΕΛΩΝ 你的问题和这个问题一样吗?我的答案是针对这个问题,如果你的答案不同,或者你应该提出一个新问题来解释更多细节。
  • 不完全相同的问题:提交表单时出现错误 406,提交 JSON 时出现错误。但是,在我使用 Spring 的代码进行调试之前,我不明白请求实体必须以某种方式实现MultiValueMap 才能与FormHttpMessageConverter 一起使用。所以现在我开始认为,要么是 OP 的 FormDataObject 实现了该接口,要么我遇到了与 OP 相同的问题,但添加该转换器不起作用。顺便说一句,我使用的是 Spring 4.2
  • @usr-local-ΕΨΗΕΛΩΝ 我建议您针对您的问题提出一个新问题,在此评论中,没有提供足够的信息。
  • @SidneydeMoraes,应该是这样。但是您可以自己将 MultiValueMap 转换为 Object。
【解决方案3】:

问题是当我们使用 application/x-www-form-urlencoded 时,Spring 并不将其理解为 RequestBody。所以,如果我们想使用这个 我们必须删除 @RequestBody 注释。

然后尝试以下操作:

@RequestMapping(
        value = "/baz",
        method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
        produces = MediatType.APPLICATION_JSON_VALUE
)
public @ResponseBody SearchResults[] jqueryPostHandler(
        FormDataObject formData)
{
    return this.searchService.find(formData);
}

注意去掉了注释@RequestBody

回答Http Post request with content type application/x-www-form-urlencoded not working in Spring

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-02-07
    • 2019-01-03
    • 1970-01-01
    相关资源
    最近更新 更多