java - Spring Boot - 不支持内容类型 'application/x-www-form-urlencoded;charset=UTF-8'

标签 java spring spring-boot

我正在使用最新的 Spring Boot 版本,当前为 2.2.2-RELEASE。

我有这个端点:

@RequestMapping(method = RequestMethod.POST, value = "/test", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<?> post(@RequestParam(required = false) MultiValueMap<?, ?> paramMap) throws Exception {
    // CODE
    return new ResponseEntity<>(HttpStatus.OK);
}

如果我(从 postman )调用它,将正文设置为 x-www-form.urlencoded 一切都很好,我会收到 200 OK 状态代码。

但是如果我修改上述端点(添加另一个参数)如下:

@RequestMapping(method = RequestMethod.POST, value = "/test", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<?> post(@RequestParam(required = false) MultiValueMap<?, ?> paramMap, RequestEntity<?> req) throws Exception {
    // CODE
    return new ResponseEntity<>(HttpStatus.OK);
}

我收到此错误:

{
    "timestamp": 1576961587242,
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
    "path": "/test"
}

有什么东西丢失了吗?

提前谢谢您。

最佳答案

正如 @Sunil Dabburi 建议调试 AbstractMessageConverterMethodArgumentResolver 中的 readWithMessageConverters 方法揭示了这个问题,一旦理解就会变得非常简单。 Spring 有大约 15 个默认消息转换器,它们负责将传入请求的内容转换为 RequestEntityHttpEntity。如果请求有主体,转换器会读取它并将其转换为它负责的对象类型。根据传入请求的媒体类型,每个转换器决定是否可以读取该请求。对于 application/x-www-form-urlencoded 媒体类型,默认的 Spring 转换器都无法处理此类请求。因此,就会出现上述错误。

application/x-www-form-urlencoded 媒体类型的自定义转换器添加到 Spring 的 http 消息转换器列表中可以解决该问题。在下面的示例中,自定义转换器仅负责读取请求,并且仅负责具有所需媒体类型的请求。

** 这些读取有助于理解媒体类型本身以及 spring 如何使用它,因此自定义转换器应该如何转换传入的请求:

以下是此类自定义 http 消息转换器的示例:

@Component
public class FormUrlencodedHttpMessageConverter extends 
AbstractGenericHttpMessageConverter<MultiValueMap<String, String>> {

private static final MediaType CONVERTER_MEDIA_TYPE = MediaType.APPLICATION_FORM_URLENCODED;

public FormUrlencodedHttpMessageConverter() {
    super(CONVERTER_MEDIA_TYPE);
}

@Override
public MultiValueMap<String, String> read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
        throws IOException, HttpMessageNotReadableException {

    String urlEncodedData = new BufferedReader(
            new InputStreamReader(inputMessage.getBody(), StandardCharsets.UTF_8)).readLine();

    String[] keyValuePairs = urlEncodedData.split("&");
    MultiValueMap<String, String> keyValuePairsMap = new LinkedMultiValueMap<>();

    for (String keyValuePair : keyValuePairs) {
        String[] pairElements = keyValuePair.split("=");
        String key = pairElements[0];
        String value = pairElements[1];
        keyValuePairsMap.add(key, value);
    }

    return keyValuePairsMap;
}

@Override
protected boolean canRead(@Nullable MediaType mediaType) {

    return CONVERTER_MEDIA_TYPE.includes(mediaType);
}

@Override
protected boolean canWrite(@Nullable MediaType mediaType) {

    return CONVERTER_MEDIA_TYPE.includes(mediaType);
}

@Override
protected void writeInternal(MultiValueMap<String, String> t, Type type, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {
    throw new RuntimeException("Method 'writeInternal' in " + this.getClass().getSimpleName() + " is not implemented");
}

@Override
protected MultiValueMap<String, String> readInternal(Class<? extends MultiValueMap<String, String>> clazz, HttpInputMessage inputMessage)
        throws IOException, HttpMessageNotReadableException {
    throw new RuntimeException("Method 'readInternal' in " + this.getClass().getSimpleName() + " is not implemented");
}

关于java - Spring Boot - 不支持内容类型 'application/x-www-form-urlencoded;charset=UTF-8',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59439782/

相关文章:

java - 无法通过java split()方法从字符串中获取数字

java - Spring 中的 FileNotFoundException

java - Spring Bootstrap 和 Aspect 是如何实现的?

java - Spring Json 解码期间出现 JsonMappingException

java - 如何链接可完成的 future

java - 从控制台获取枚举类型的输入

java - 具有多个条件的 Spring JPA 自定义存储库

java - 如何使用Intent录制视频?

java - 根据 Spring Boot 中的角色获取用户列表

spring-boot - 在 Spring Boot 应用程序中使用 JavaCompiler API - 无法正确设置编译类路径