Spring MVC - @RequestParam causing MissingServletR

2019-06-07 07:15发布

问题:

The follwing Spring MVC code throws MissingServletRequestParameterException,

@Controller
@RequestMapping("/users")
public class XXXXResource extends AbstractResource {

.....

 @RequestMapping(method = RequestMethod.PUT
            , produces = {"application/json", "application/xml"}
            , consumes = {"application/x-www-form-urlencoded"}
    )
    public
    @ResponseBody
    Representation createXXXX(@NotNull @RequestParam("paramA") String paramA,
        @NotNull @RequestParam("paramB") String paramB,
        @NotNull @RequestParam("paramC") String paramC,
        @NotNull @RequestParam("paramD") String paramD ) throws Exception {
   ...
   }
}

There are no stack traces in the logs, only the Request from Postman returns with HTTP 400 Error.

回答1:

if you want to Content-type:application/x-www-form-urlencoded means that the body of the HTTP request sent to the server should be one giant string -- name/value pairs are separated by the ampersand (&) and will be urlencoded as his name implies.

name=name1&value=value2

this means that you should not user @RequestParam because the arguments are passed in the body of the http request.

So if you want to use this content-type from their doc:

You convert the request body to the method argument by using an HttpMessageConverter. HttpMessageConverter is responsible for converting from the HTTP request message to an object and converting from an object to the HTTP response body. The RequestMappingHandlerAdapter supports the @RequestBody annotation with the following default HttpMessageConverters:

ByteArrayHttpMessageConverter converts byte arrays.

StringHttpMessageConverter converts strings.

FormHttpMessageConverter converts form data to/from a MultiValueMap.

SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.

You should use @RequestBody with FormHttpMessageConverter, which will get this giant string and will convert it to MultiValueMap<String,String>. Here is a sample.

@RequestMapping(method = RequestMethod.PUT
        , consumes = {"application/x-www-form-urlencoded"}
        ,value = "/choice"
)
public
@ResponseBody
String createXXXX(@RequestBody MultiValueMap params) throws Exception {
    System.out.println("params are " + params);
    return "hello";
}