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

Posted

技术标签:

【中文标题】@RequestBody MultiValueMap 不支持内容类型 \'application/x-www-form-urlencoded;charset=UTF-8\'【英文标题】:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported for @RequestBody MultiValueMap@RequestBody MultiValueMap 不支持内容类型 'application/x-www-form-urlencoded;charset=UTF-8' 【发布时间】:2016-02-21 03:25:20 【问题描述】:

基于for problem with x-www-form-urlencoded with 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");
            
    

请求失败并出现以下错误


  "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"

[PS:Jersey 更加友好,但由于这里的实际限制,现在无法使用它]

【问题讨论】:

你在@RequestBody 中添加了consumes = "application/x-www-form-urlencoded" 吗? 你是如何执行请求的?添加 (js,jquery, curl 或任何你使用的) 的代码。 我也有同样的问题。就我而言,我使用 jquery ajax 发布数据,数据为 JSON.stringify("ordersToDownload":"00417002" 这是我使用的代码:$.ajax(url:"/myurl", type:"POST", data: JSON.stringify("someAttribute":"someData") ) 查看我的答案enter link description here 【参考方案1】:

问题是当我们使用 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;

注意去掉了注释@RequestBody

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

【讨论】:

谢谢!解决问题。现在我想知道我们如何明确删除 application/x-www-form-urlencoded 没有必要@kholofeloMaloma 如果有人想知道为什么这在没有任何注释的情况下工作,似乎 Spring 处理任何未注释的参数就好像它们有 @ModelAttribute, even though this behaviour is (sadly) not documented. And @ModelAttribute 确实理解 x-www-form-urlencoded public ResponseEntity> getToken(MultiValueMap paramMap) IllegalArgumentException: 参数类型不匹配 感谢您的信息!作为一个新手,我想知道 Spring 解析有效负载并将其绑定到对象的这种奇怪行为背后的原因是什么?【参考方案2】:

看来现在你可以用@RequestParam标记方法参数,它会为你完成这项工作。

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) 
  //work with Map

【讨论】:

这在 Spring Boot 2.4.2 上有效【参考方案3】:

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

curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY

这样spring就知道如何解析内容了。

【讨论】:

您可能还需要在命令中添加 Accept 标头:'curl -vk -H "Accept: application/json" -H "Content-Type: application/json" ' etc.跨度> 您能解释一下如何将此设置添加到我的 html 表单吗?【参考方案4】:

在春天 5

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

    // import org.springframework.util.MultiValueMap;

    String datax = (String) body .getFirst("datax");

【讨论】:

是的,在映射中包含 consumer=MediaType.APPLICATION_FORM_URLENCODED_VALUE,您应该得到更多积分,先生!谢谢!从请求中获取 MultiValueMap 现在需要 @RequestParam 接缝【参考方案5】:

@RequestBody MultiValueMap 参数映射

在这里删除@RequestBody注释

@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";
 

这样

【讨论】:

虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。【参考方案6】:

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

@RestController
public class MyController 

    @PostMapping
    public void method(@Valid RequestDto dto) 
       // method body ...
    

【讨论】:

【参考方案7】:

我在this *** answer 中写了一个替代方案。

那里我一步一步写,用代码解释。捷径:

首先:写一个对象

第二个:创建一个转换器来映射扩展AbstractHttpMessageConverter的模型

第三:告诉spring使用这个转换器实现一个覆盖configureMessageConverters方法的WebMvcConfigurer.class

第四个也是最后一个:在控制器内部的映射中使用此实现设置,在对象前面使用 = MediaType.APPLICATION_FORM_URLENCODED_VALUE 和 @RequestBody。

我正在使用 Spring Boot 2。

【讨论】:

【参考方案8】:

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

Douglas Ribeiro 的回答会很好用。但以防万一,对于像我这样真正想在 Spring MVC 中使用“@RequestBody”的任何人。

这是问题的原因

Spring需要①识别“Content-Type”,②转换 内容添加到我们在方法签名中声明的参数类型。 “application/x-www-form-urlencoded不支持,因为,由 默认,Spring找不到合适的HttpMessageConverter来做 转换工作,即步骤②。

解决方案:

我们手动Spring 中添加一个适当的 HttpMessageConverter 我们的应用程序的配置

步骤:

    选择我们要使用的 HttpMessageConverter 类。为了 'application/x-www-form-urlencoded',我们可以选择 “org.springframework.http.converter.FormHttpMessageConverter”。 将 FormHttpMessageConverter 对象添加到 Spring 的配置中, 通过调用“公共空白 configureMessageConverters(List> converters)" "WebMvcConfigurer" 实现类的方法 在我们的应用程序中。在方法内部,我们可以添加任何 HttpMessageConverter 对象,根据需要使用“converters.add()”。

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

根据 Servlet 规范(第 3.1.1 节):

以下是post form之前必须满足的条件 数据将填充到参数集:请求是 HTTP 或 HTTPS 请求。 2. HTTP 方法是POST。 3.内容类型为 应用程序/x-www-form-urlencoded。 4. servlet 进行了初始化 对 request 调用任何 getParameter 系列方法 对象

因此,请求正文中的值将被填充到参数中。但是在 Spring 中,您仍然可以访问 RequestBody,即使您可以在 同一方法的签名处使用 @RequstBody@RequestParam强>。 喜欢:

@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String processForm(@RequestParam Map<String, String> inputValue,  @RequestBody MultiValueMap<String, List<String>> formInfo) 
    ......
    ......

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

【讨论】:

【参考方案9】:
@PostMapping(path = "/my/endpoint", consumes =  MediaType.APPLICATION_FORM_URLENCODED_VALUE )
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception 
    ...

这种方式适合我

【讨论】:

这是最简单的答案;在 @RestController 上的 Spring Boot 2.6.0 上为我工作。【参考方案10】:

你可以尝试在spring的转换器中开启支持

@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer 

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) 
        // add converter suport Content-Type: 'application/x-www-form-urlencoded'
        converters.stream()
                .filter(AllEncompassingFormHttpMessageConverter.class::isInstance)
                .map(AllEncompassingFormHttpMessageConverter.class::cast)
                .findFirst()
                .ifPresent(converter -> converter.addSupportedMediaTypes(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
    



【讨论】:

【参考方案11】:

如果您使用 JMeter 进行测试,只需添加一个 HTTP 标头管理器:

【讨论】:

以上是关于@RequestBody MultiValueMap 不支持内容类型 'application/x-www-form-urlencoded;charset=UTF-8'的主要内容,如果未能解决你的问题,请参考以下文章

@RequestBody使用

@RequestParam @RequestBody @PathVariable 之@requestBody注解的使用

@RequestBody 和 @RequestParam 有啥区别?

@RequestBody 处理类型

自定义spring参数注解 - 打破@RequestBody单体限制

@RequestBody