SpringBoot @RequestBody 报错 ('application/x-www-form-urlencoded;charset=UTF-8' not supported)

本文详细解析了在SpringBoot中使用@RequestBody时出现的Contenttype'application/x-www-form-urlencoded;charset=UTF-8'notsupported错误,并提供了解决方案。通过自定义RequestMappingHandlerAdapter并添加JSON处理转换器,成功消除了报错。

在Spring boot 中使用 @RequestBody 会报错,提示错误 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported,代码如下:

    @RequestMapping(value = "/act/service/model/{modelId}/save", method = RequestMethod.POST)
	public void saveModel(@PathVariable String modelId, @RequestBody MultiValueMap<String, String> values) {
        // 具体代码
	}

这个在传统 spring MVC 中是有效的,但是在 Spring boot 中会报错。
传统是 Spring MVC 有效,是因为有 <mvc:annotation-driven> 注解,查资料,<mvc:annotation-driven> 注解配置了如下的内容
spring 3.1 版本:

<!-- 注解请求映射  -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">        
        <property name="interceptors">
            <list>  
                <ref bean="logNDCInteceptor"/>   <!-- 日志拦截器,这是你自定义的拦截器 -->
            </list>        
        </property>        
    </bean>      
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">  
            <list>  
                <ref bean="byteArray_hmc" />  
                <ref bean="string_hmc" />  
                <ref bean="resource_hmc" />  
                <ref bean="source_hmc" />  
                <ref bean="xmlAwareForm_hmc" />  
                <ref bean="jaxb2RootElement_hmc" />  
                <ref bean="jackson_hmc" />  
            </list>  
        </property>  
    </bean>  
    <bean id="byteArray_hmc" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /><!-- 处理.. -->
    <bean id="string_hmc" class="org.springframework.http.converter.StringHttpMessageConverter" /><!-- 处理.. -->
    <bean id="resource_hmc" class="org.springframework.http.converter.ResourceHttpMessageConverter" /><!-- 处理.. -->
    <bean id="source_hmc" class="org.springframework.http.converter.xml.SourceHttpMessageConverter" /><!-- 处理.. -->
    <bean id="xmlAwareForm_hmc" class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" /><!-- 处理.. -->
    <bean id="jaxb2RootElement_hmc" class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" /><!-- 处理.. -->
    <bean id="jackson_hmc" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /><!-- 处理json-->

转载:http://elf8848.iteye.com/blog/875830
这个找到的资料是 3.1 的,但是women可以看到,最后一个配置了 Jackson 的 json 处理程序,在更新的版本中,AnnotationMethodHandlerAdapter 已经废弃,使用的是 RequestMappingHandlerAdapter,看下 RequestMappingHandlerAdapter 的源码。


	public RequestMappingHandlerAdapter() {
		StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
		stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316

		this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(stringHttpMessageConverter);
		this.messageConverters.add(new SourceHttpMessageConverter<Source>());
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
	}

这里面没有了 json 的处理过程,我们把它加上

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    
    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
        
        List<HttpMessageConverter<?>> converters = adapter.getMessageConverters();

        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
        MediaType textMedia = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8"));
        supportedMediaTypes.add(textMedia);
        MediaType jsonMedia = new MediaType(MediaType.APPLICATION_JSON, Charset.forName("UTF-8"));
        supportedMediaTypes.add(jsonMedia);jsonConverter.setSupportedMediaTypes(supportedMediaTypes);
        
        converters.add(jsonConverter);
        
        
        adapter.setMessageConverters(converters);
        
       return adapter;
    }
}

成功,报错消除,正确获取到了参数

### 解决方案 当遇到 `Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported` 的错误时,通常是因为控制器方法未正确配置以处理该类型的请求。以下是可能的原因以及解决方案: #### 原因分析 1. **缺少正确的注解** 如果使用的是表单数据提交方式 (`application/x-www-form-urlencoded`),则需要在控制器的方法参数上添加 `@RequestParam` 或者 `@ModelAttribute` 注解来绑定请求中的键值对[^1]。 2. **不匹配的 Content-Type 配置** 默认情况下,Spring Boot 控制器可能会期望 JSON 数据而不是 URL 编码的数据。如果希望支持 `application/x-www-form-urlencoded` 类型,则需显式声明支持此类型的内容解析。 3. **HttpMessageConverter 问题** Spring 使用 HttpMessageConverters 来转换 HTTP 请求体和响应体。默认情况下,某些 Converters 可能未启用或者未正确定义,从而导致无法识别特定的 Content-Type[^3]。 --- #### 实现步骤说明 ##### 方法一:修改 Controller 参数定义 对于基于 `application/x-www-form-urlencoded` 的 POST 请求,在接收参数的地方应采用如下形式: ```java @PostMapping(consumes = "application/x-www-form-urlencoded") public ResponseEntity<String> handleFormSubmission( @RequestParam String hiveTableName, @RequestParam String tableImportType, @RequestParam String pkColumn, @RequestParam String incrementColumn, @RequestParam String cron, @RequestParam Integer datasetId) { // 处理逻辑... return ResponseEntity.ok("Success"); } ``` 上述代码通过 `@RequestParam` 显式指定了每个字段名称及其对应的变量名,确保能够正确映射来自客户端发送的键值对。 ##### 方法二:利用 DTO 对象封装参数 另一种更简洁的方式是创建一个 Data Transfer Object (DTO),并将所有参数集中到一起: ```java public class ImportRequestDto { private String hiveTableName; private String tableImportType; private String pkColumn; private String incrementColumn; private String cron; private int datasetId; // Getters 和 Setters ... } @PostMapping(value = "/import", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public ResponseEntity<String> importData(@ModelAttribute ImportRequestDto dto) { System.out.println(dto.getHiveTableName()); // 进一步业务操作... return ResponseEntity.status(HttpStatus.CREATED).body("Resource created successfully."); } ``` 这里的关键在于使用了 `@ModelAttribute` 而不是 `@RequestBody`,因为后者主要用于解析 JSON 格式的请求体。 ##### 方法三:调整全局消息转换器设置 如果项目中有多个地方需要用到这种格式的支持,可以考虑自定义 Message Converter 并注册它到 Spring 容器中去: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FormEncodingHttpMessageConverter converter = new FormEncodingHttpMessageConverter(); converter.setReadHiddenHttpMethodField(false); Charset charset = StandardCharsets.UTF_8; List<MediaType> mediaTypes = Arrays.asList(new MediaType("application","x-www-form-urlencoded",charset)); converter.setSupportedMediaTypes(mediaTypes); converters.add(0,converter); // 添加至首位优先级最高 } } ``` 这样做的好处是可以统一管理所有的 form 表单编码需求而无需逐个更改 controller 层实现细节[^4]。 --- ### 注意事项 - 当上传文件时,请注意区分普通的 key-value pairs 和 binary 文件流之间的差异。例如上面提到的例子中,“myFile”代表的就是实际待传输文档的位置信息[^2]。 - 确认服务器端日志级别已设为至少 info ,以便观察随机密码打印情况以及其他潜在异常提示。 ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值