Spring @MVC and the @RequestBody annotation with x

2020-05-21 04:09发布

I am trying to figure out why I can't receive a request from a jQuery.ajax call when then Spring @Controller handler method includes a @RequestBody annotation. Consider the following:

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);
}

The above will fail with the @RequestBody annotation present and return a 415 error (no exception will be generated). But if the @RequestBody annotation is removed (i.e. the parameter signature is just FormDataObject formData) then the method will be called and JSON will be returned to the JavaScript.

Why is this the case? A POST request includes the data in the body of the request. Shouldn't the annotation process such a request?

I realize that I could change the content type sent by the JavaScript to application/json and the consumes property to MediaType.APPLICATION_JSON_VALUE to make the annotation work correctly. But why doesn't it work with a normal form request?

Note: I am using Spring 3.1.4.

3条回答
女痞
2楼-- · 2020-05-21 04:45

Have you tried turning up logging on 'org.springframework.web' to find out the reason for the returned status code? There should be an exception raised and logged before it's translated to a 415.

Also if sending form data, why not just leave out the @RequestBody. You'll then be use data binding (i.e. @ModelAttribute) that will apply Servlet request parameters to object fields. This is preferable to using the FormHttpMessageConverter.

查看更多
Juvenile、少年°
3楼-- · 2020-05-21 04:52

The problem is that when we use application/x-www-form-urlencoded, Spring doesn't understand it as a RequestBody. So, if we want to use this we must remove the @RequestBody annotation.

Then try the following:

@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);
}

Note that removed the annotation @RequestBody

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

查看更多
爷的心禁止访问
4楼-- · 2020-05-21 04:55

As the Spring Docs of @RequestBody says, the request body would be converted to your object by HttpMessageConverter.

There are 4 default HttpMessageConverters:

To convert the url encoded form, which is ajax.serialize() create, it's the job of FormHttpMessageConverter. Since you have a HttpMediaTypeNotSupportedException exception, I guess that you didn't configure FormHttpMessageConverter. Check your spring configuration file, here is an example :

< 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>
查看更多
登录 后发表回答