不支持@RequestBody MultiValueMap 的内容类型‘ application/x-www-form-urlencode; charset = UTF-8’

根据答案 用 Spring@Controller 解决 x-www-form-urlencode 的问题

我已经编写了下面的@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"
}

[附注: 泽西人更友好,但是由于这里的实际限制现在不能使用它]

353984 次浏览

问题在于,当我们使用 Application/x-www-form-urlencode时,Spring 并不将其理解为 RequestBody。如果我们想用这个 我们必须删除 @ RequestBody注释。

然后试试下面的方法:

@RequestMapping(
path = "/{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

回答 : < a href = “ https://stackoverflow. com/questions/34782025/Http-Post-request-with-content-type-application-x-www-form-urlencode-not-workin/38252762 # 38252762”> Http Post request with content type application/x-www-form-urlencode not working in Spring

在请求中添加一个头,将内容类型设置为 application/json

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

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

现在似乎可以用 @RequestParam标记方法参数,它将为您完成这项工作。

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

我在 这个 StackOverflow 的答案中写了一篇关于另一种选择的文章。

在那里,我一步一步地写,用代码解释。简单来说:

首先 : 写一个对象

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

Third : tell to spring use 这个转换器实现了一个 WebMvcConfigurer.class,覆盖 configureMessageConverters 方法

第四个 和最后一个: 在控制器内的映射中使用这个实现设置,在对象的前面使用 = MediaType.APPATION _ FORM _ URLENCODED _ VALUE 和@RequestBody。

我用的是弹簧靴2。

在春天5

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


// import org.springframework.util.MultiValueMap;


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

只需删除 @RequestBody注释就可以解决这个问题(在 Spring Boot 2上进行了测试) :

@RestController
public class MyController {


@PostMapping
public void method(@Valid RequestDto dto) {
// method body ...
}
}
@PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
...
}

那条路对我有用

你可以尝试打开弹簧转换器的支撑

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


}


@ RequestBody MultiValueMap paramMap

在这里 删除@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";
}

像这样

如果您正在使用 JMeter 进行测试,那么只需添加一个 HTTP Header Manager: enter image description here

当我想在 Spring MVC 中处理我的 简单的 HTML 表单提交(使用 百里香叶Spring 的表单标签没有)时,我遇到了同样的问题。

道格拉斯•里贝罗(Douglas Ribeiro)的回答将非常有效。但以防万一,对于任何人,像我,谁 真的想用“@RequestBody”在春季 MVC。

下面是问题的 原因:

  • Spring 需要1 认可「内容类别」,并且2 < strong > 转换 Content 到我们在方法签名中声明的参数类型
  • Application/x-www-form-urlencode’是 不支持,因为,< strong > by Default ,Spring 无法找到要执行的 正确的 HttpMessageConverter 换工作,也就是步骤2。

解决方案:

  • 我们将 手动操作添加到 < strong > Spring’s 中 配置 我们的申请.

步骤:

  1. 选择要使用的 HttpMessageConverter 类 “ Application/x-www-form-urlencode”,我们可以选择 “ org.springframework.http.Converter.FormHttpMessageConverter”。
  2. FormHttpMessageConverter 对象添加到 Spring 的配置中, 称之为“公共空间” ConfigureMessageConverters (List < HttpMessageConverter < ? > > 转换器)”的方法 在我们的应用程序中。在方法中,我们可以添加任何 HttpMessageConverter 对象,使用“ Add ()”。

顺便说一下,原因为什么我们可以使用“ @ RequestParam”来进行 访问值:

根据 Servlet 规范(第3.1.1节) :

以下是投递表格前必须满足的条件 Data 将被填充到参数集: 请求是 < strong > HTTP 或 HTTPS 请求 .2。 HTTP 方法是 职位.3 Application/x-www-form-urlencode .4 根据 < strong > 请求调用任何 方法的参数族 对象 .

所以 请求体中的值就是 填充到参数中。但在春天,你可以 仍然访问 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”的类型是 地图,而“ @ RequestBody”的类型是 MultiValueMap