我正在尝试使用纯文本主体(utf-8)处理POST请求,但似乎spring不喜欢该调用的纯文本性质。可能是它不受支持吗?否则,我编码是否错误?
@RestController
@RequestMapping(path = "/abc", method = RequestMethod.POST)
public class NlpController {
@PostMapping(path= "/def", consumes = "text/plain; charset: utf-8", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> doSomething(@RequestBody String bodyText)
{
...
return ResponseEntity.ok().body(responseObject);
}
}
回复为:
已解决的[org.springframework.web.HttpMediaTypeNotSupportedException:不支持内容类型'application / x-www-form-urlencoded'
我使用curl命令进行了测试:
curl -s -X POST -H 'Content-Type: text/plain; charset: utf-8' --data-binary @text.txt localhost:8080/abc/def
text.txt包含纯文本(希伯来语为UTF-8)。
答案 0 :(得分:1)
在弹簧是否支持文本/纯文本的问题的另一部分,我想作一些阐述。
根据spring文档: @RequestMapping 批注
中的“消费”或“消耗性媒体类型”是什么定义:
耗材类型
“您可以通过指定消耗性媒体类型的列表来缩小主映射的范围。仅当Content-Type请求标头与指定的媒体类型匹配时,请求才会被匹配。例如:”
@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
也可以像在!text / plain中一样否定消耗性媒体类型表达式,以匹配除Content / Type为text / plain的请求以外的所有请求。
介质类型在内部如何匹配?
Spring请求驱动设计围绕一个称为调度程序Servlet的Servlet进行,该Servlet使用特殊的Bean来处理请求,其中一个Bean是RequestMappingHandlerMapping,它使用以下命令检查媒体类型 ConsumesRequestCondition类的getMatchingCondition方法,如下所示。
@Override
public ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return PRE_FLIGHT_MATCH;
}
if (isEmpty()) {
return this;
}
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(expressions);
result.removeIf(expression -> !expression.match(exchange));
return (!result.isEmpty() ? new ConsumesRequestCondition(result) : null);
}
获取匹配条件类使用静态内部类ConsumesMediaType Expression,它实际上进行了检查
@Override
protected boolean matchMediaType(ServerWebExchange exchange) throws UnsupportedMediaTypeStatusException {
try {
MediaType contentType = exchange.getRequest().getHeaders().getContentType();
contentType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
return getMediaType().includes(contentType);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Can't parse Content-Type [" +
exchange.getRequest().getHeaders().getFirst("Content-Type") +
"]: " + ex.getMessage());
}}
一旦媒体类型不匹配,此方法将返回false,并且getMatchingCondition返回null,这将导致调用RequestMappingInfoHandlerMapping的handleNoMatch方法,并使用PartialMatchHelper类检查如下所示的不匹配类型,并一旦抛出HttpMediaTypeNotSupportedException错误就抛出弹簧看到消耗不匹配
if (helper.hasConsumesMismatch()) {
Set<MediaType> mediaTypes = helper.getConsumableMediaTypes();
MediaType contentType = null;
if (StringUtils.hasLength(request.getContentType())) {
try {
contentType = MediaType.parseMediaType(request.getContentType());
}
catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotSupportedException(ex.getMessage());
}
}
throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList<>(mediaTypes));
}
Spring根据IANA https://www.iana.org/assignments/media-types/media-types.xhtml支持所有媒体类型,问题仅出在别人引用的curl命令上。
答案 1 :(得分:0)
@rumbz 请参考以下链接,它可能会解决您的问题
@RequestMapping(value = "/some-path", produces =
org.springframework.http.MediaType.TEXT_PLAIN)
public String plainTextAnnotation() {
return "<response body>";
}
其中,将/ some-path替换为您要使用的任何内容。
public String plainTextResponseEntity() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(org.springframework.http.MediaType.TEXT_PLAIN);
return new ResponseEntity("<response body>", httpHeaders, HttpStatus.OK);
}
答案 2 :(得分:0)
每个@ m-deinum的评论:问题不在spring框架中-而是curl在请求中添加了“ application / x-www-form-urlencoded”的事实...
为了使这个问题更完整:
curl -s -X POST -H "Content-Type:" -H "Content-Type: text/plain; charset: utf-8" --data-binary @file.txt localhost:8080/abc/def