@RequestBody MultiValueMap不支持内容类型'application/x-www-form-urlencoded; charset = UTF-8'

Som*_*kar 73 model-view-controller spring spring-mvc

基于x-www-form-urlencoded与Spring @Controller的问题的答案

我写了下面的@Controller方法

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST
            , produces = {"application/json", "application/xml"}
            ,  consumes = {"application/x-www-form-urlencoded"}
    )
     public
        @ResponseBody
        Representation authenticate(@PathVariable("email") String anEmailAddress,
                                    @RequestBody MultiValueMap paramMap)
                throws Exception {


            if(paramMap == null || paramMap.get("password") == null) {
                throw new IllegalArgumentException("Password not provided");
            }
    }
Run Code Online (Sandbox Code Playgroud)

请求失败并出现以下错误

{
  "timestamp": 1447911866786,
  "status": 415,
  "error": "Unsupported Media Type",
  "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
  "message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
  "path": "/users/usermail%40gmail.com/authenticate"
}
Run Code Online (Sandbox Code Playgroud)

[PS:泽西岛更加友好,但现在考虑到实际限制,现在无法使用它]

Dou*_*iro 84

问题是,当我们使用application/x-www-form-urlencoded时,Spring并不将其理解为RequestBody.因此,如果我们想要使用它,我们必须删除@RequestBody注释.

然后尝试以下方法:

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, 
        produces = {MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public @ResponseBody  Representation authenticate(@PathVariable("email") String anEmailAddress, MultiValueMap paramMap) throws Exception {
   if(paramMap == null && paramMap.get("password") == null) {
        throw new IllegalArgumentException("Password not provided");
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

请注意,删除了注释@RequestBody

回答:Http Post请求内容类型为application/x-www-form-urlencoded在Spring中不起作用

  • 如果有人想知道为什么这在没有任何注释的情况下工作,似乎 Spring 处理任何未注释的参数,就好像它们有 @ModelAttribute 一样,即使这种行为(遗憾的是)没有记录。并且 `@ModelAttribute 确实理解 x-www-form-urlencoded (5认同)
  • public ResponseEntity<?> getToken(MultiValueMap paramMap) IllegalArgumentException:参数类型不匹配 (2认同)

Sca*_*dge 57

现在看来你可以只用标记方法参数,@RequestParam它将为你完成工作.

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) {
  //work with Map
}
Run Code Online (Sandbox Code Playgroud)

  • 这在 Spring Boot 2.4.2 上有效 (2认同)

小智 13

在请求中添加标头以将内容类型设置为application/json

curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY
Run Code Online (Sandbox Code Playgroud)

这样Spring就知道如何解析内容.


Edg*_*ini 12

在春天 5

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam MultiValueMap body ) {

    // import org.springframework.util.MultiValueMap;

    String datax = (String) body .getFirst("datax");
}
Run Code Online (Sandbox Code Playgroud)


Yas*_*iri 7

@RequestBody MultiValueMap paramMap

在这里删除@RequestBody Annotaion

@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount(@RequestBody LogingData user){
    logingService.save(user);
    return "login";
}




@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount( LogingData user){
    logingService.save(user);
    return "login";
} 
Run Code Online (Sandbox Code Playgroud)

像那样

  • 虽然此代码可以解决问题,但[包括解释](//meta.stackexchange.com/q/114762) 如何以及为何解决问题确实有助于提高帖子的质量,并可能会带来更多结果赞成票。请记住,您是在为将来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 (7认同)

Ham*_*eji 6

只需删除@RequestBody注释即可解决问题(在 Spring Boot 2 上测试):

@RestController
public class MyController {

    @PostMapping
    public void method(@Valid RequestDto dto) {
       // method body ...
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

当我想在 Spring MVC 中处理简单的 HTML 表单提交使用thymeleafSpring 的表单标签)时,我遇到了同样的问题。

\n

道格拉斯·里贝罗的答案将会非常有效。但以防万一,对于像我这样真正想在 Spring MVC 中使用“@RequestBody”的人来说。

\n

这是问题的原因:

\n
    \n
  • Spring 需要 \xe2\x91\xa0识别 "Content-Type",并且 \xe2\x91\xa1将内容转换\n为我们在方法签名中声明的参数类型。
  • \n
  • 不支持application/x-www-form-urlencoded ” ,因为默认情况下,Spring 找不到合适的 HttpMessageConverter来执行转换作业,即步骤 \xe2\x91\xa1。
  • \n
\n

解决方案:

\n
    \n
  • 我们手动将适当的 HttpMessageConverter添加到应用程序Spring 配置中。
  • \n
\n

脚步:

\n
    \n
  1. 选择我们要使用的 HttpMessageConverter 类。对于‘ application/x-www-form-urlencoded ’,我们可以选择“org.springframework.http.converter.FormHttpMessageConverter
  2. \n
  3. 将FormHttpMessageConverter 对象添加到 Spring 的配置中,\n通过在我们的应用程序中调用“WebMvcConfigurer”实现类的“public void\n configureMessageConverters (List<HttpMessageConverter<?>>\nconverters)”方法。在方法内部,我们可以根据需要使用“ converters.add() ”添加任何HttpMessageConverter对象。
  4. \n
\n

顺便说一句,我们可以使用“ @RequestParam ”访问该值的原因是:

\n

根据Servlet 规范(第 3.1.1 节):

\n
\n

以下是在将 post 表单\n数据填充到参数集中之前必须满足的条件: 请求是HTTP\nor HTTPS 请求。2. HTTP 方法是POST。3. 内容类型为\n application/x-www-form-urlencoded4. servlet 已对requestobject上的任何getParameter 系列方法进行了初始调用。

\n
\n

因此,请求正文中的值将被填充到参数中。但在 Spring 中,您仍然可以访问 RequestBody,甚至可以在同一方法的签名中使用@RequstBody@RequestParam。\n例如:

\n
@RequestMapping(method = RequestMethod.POST, consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})\npublic String processForm(@RequestParam Map<String, String> inputValue,  @RequestBody MultiValueMap<String, List<String>> formInfo) {\n    ......\n    ......\n}\n
Run Code Online (Sandbox Code Playgroud)\n

inputValue 和 formInfo 包含相同的数据,除了“ @RequestParam ”的类型是Map,而“ @RequestBody ”的类型是MultiValueMap

\n