spring boot 控制器可以接收明文/文本吗? [英] Can spring boot controller receive plain/text?

查看:125
本文介绍了spring boot 控制器可以接收明文/文本吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用纯文本正文 (utf-8) 处理 POST 请求,但似乎 spring 不喜欢调用的纯文本性质.可能是它不受支持 - 否则,我是否编码错误?

I am trying to process a POST request with body of plain text (utf-8) but it seems that spring does not like the plain text nature of the call. Could it be that it is not supported - or otherwise, am I coding it wrong?

@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']

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded' not supported]

我用 curl 命令测试过:

I tested with curl command:

curl -s -X POST -H 'Content-Type: text/plain; charset: utf-8' --data-binary @text.txt localhost:8080/abc/def

text.txt 包含纯文本(希伯来语为 UTF-8).

The text.txt contains plain text (UTF-8 in Hebrew).

推荐答案

我想对 spring 是否支持 text/plain 的问题的另一部分有所了解?

I would like to throw some light on the other part of the question of whether spring supports text/plain?

根据 spring 文档:@RequestMapping 注释中的消费"或可消费媒体类型是什么

According to spring docs: what is "consumes" or Consumable Media Types in the @RequestMapping annotation

定义:

消耗性媒体类型

您可以通过指定可使用的媒体类型列表来缩小主要映射的范围.只有当 Content-Type 请求标头与指定的媒体类型匹配时,才会匹配请求.例如:"

"You can narrow the primary mapping by specifying a list of consumable media types. The request will be matched only if the Content-Type request header matches the specified media type. For example:"

@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 的请求之外的所有请求.

Consumable media type expressions can also be negated as in !text/plain to match to all requests other than those with Content-Type of text/plain.

媒体类型在内部如何匹配?

How spring does the media type matching internally?

Spring 请求驱动设计以称为调度程序 Servlet 的 servlet 为中心,它使用特殊的 bean 来处理请求,其中一个 bean 是 RequestMappingHandlerMapping,它使用检查媒体类型ConsumesRequestCondition 类的 getMatchingCondition 方法如下所示.

Spring Request Driven Design is centred around a servlet called the dispatcher Servlet which uses special beans to process requests one of the bean is RequestMappingHandlerMapping which checks for the media type using getMatchingCondition method of ConsumesRequestCondition class as shown below.

    @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,它实际上进行检查

the get matching condition class uses static inner class ConsumesMediaType Expression which actually makes the check

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

一旦媒体类型不匹配并且 getMatchingCondition 返回 null,则此方法返回 false 导致调用 RequestMappingInfoHandlerMapping 的 handleNoMatch 方法,并使用 PartialMatchHelper 类检查它具有的不匹配类型,如下所示,并且 spring 一次抛出 HttpMediaTypeNotSupportedException 错误它的see消耗不匹配

This method returns false once the media type does not match and getMatchingCondition returns null which results in handleNoMatch method of RequestMappingInfoHandlerMapping being called and using PartialMatchHelper class we check for the what type of mismatch it has as shown below and spring throws HttpMediaTypeNotSupportedException error once its see consumes mismatch

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 命令.

Spring supports all media types as per the IANA https://www.iana.org/assignments/media-types/media-types.xhtml the problem lies only with the curl command as quoted by others.

这篇关于spring boot 控制器可以接收明文/文本吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆