【问题标题】: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

标签: spring spring-mvc model-view-controller


【解决方案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 StackOverflow 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 我们的应用程序的配置

      步骤:

      1. 选择我们要使用的 HttpMessageConverter 类。为了 'application/x-www-form-urlencoded',我们可以选择 “org.springframework.http.converter.FormHttpMessageConverter”。
      2. 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 标头管理器:

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-19
            • 2020-04-13
            • 2019-11-13
            • 2018-07-24
            • 2015-11-01
            • 2015-03-26
            • 1970-01-01
            • 2020-04-21
            相关资源
            最近更新 更多