Spring REST API 的 Accept-Charset 响应头

本文介绍如何在Spring REST API中解决Accept-Charset过长的问题,通过调整StringHttpMessageConverter的配置来避免发送过长的字符集列表。
基于 Spring 的 REST API,发现响应头里的 Accept-Charset 非常巨大
[quote]Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-compound_text, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp[/quote]

查了一下源码,发现默认的 StringHttpMessageConverter 会加上 Accept-Charset 响应头,并带上所有的字符集!这个选项需要通过设置 writeAcceptCharset 属性来关闭。

[url=https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java]org.springframework.http.converter.StringHttpMessageConverter[/url]

private boolean writeAcceptCharset = true;

if (this.writeAcceptCharset) {
outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
}


this.availableCharsets = new ArrayList<>(Charset.availableCharsets().values());

protected List<Charset> getAcceptedCharsets() {
return this.availableCharsets;
}


也有人反映,为什么 writeAcceptCharset 属性不初始化为fale,[url=https://jira.spring.io/browse/SPR-7316]https://jira.spring.io/browse/SPR-7316[/url]

源码中也注释了,可以通过子类覆盖 getAcceptedCharsets() 方法来返回该有的charsets。
/**
* Return the list of supported {@link Charset}s.
* <p>By default, returns {@link Charset#availableCharsets()}.
* Can be overridden in subclasses.
* @return the list of accepted charsets
*/
protected List<Charset> getAcceptedCharsets() {
return this.availableCharsets;
}


[b]XML配置:[/b]
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
<property name="writeAcceptCharset" value="false"/>
</bean>


[b]Java配置:[/b]
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
stringHttpMessageConverter.setWriteAcceptCharset(false);


SpringBoot已经通过自动配置关闭了这个选项
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration
@Bean
@ConditionalOnMissingBean
public StringHttpMessageConverter stringHttpMessageConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(this.encodingProperties.getCharset());
converter.setWriteAcceptCharset(false);
return converter;
}
### Spring 中处理 `HttpMediaTypeNotSupportedException` 的解决方案 当遇到 `HttpMediaTypeNotSupportedException` 异常时,通常是因为客户端发送的内容类型(Content-Type)或请求头中的 Accept 字段未被服务器端所支持。在这种情况下,Spring MVC 无法找到合适的处理器来解析或生成响应数据。 #### 原因分析 该异常表明当前配置的控制器方法未能匹配到所需的媒体类型。如果客户端发送的是 `'text/plain;charset=UTF-8'` 类型的数据而服务端并未注册对该类型的解析器,则会抛出此异常[^1]。 #### 解决方案 ##### 方法一:扩展消息转换器的支持范围 可以通过自定义 `WebMvcConfigurer` 来增加对 `text/plain` 类型的支持: ```java import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.nio.charset.StandardCharsets; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void extendMessageConverters(List<org.springframework.http.converter.HttpMessageConverter<?>> converters) { StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8); // 添加 text/plain 支持 converters.add(stringConverter); } } ``` 通过这种方式可以显式地告诉 Spring 如何处理纯文本形式的消息体[^2]。 ##### 方法二:调整 Controller 方法签名 确保您的 REST 控制器能够接受并返回多种 MIME 类型的数据。例如,在方法参数中标明允许接收哪些 Content-Type 或者指定生产何种格式的结果集: ```java @RestController @RequestMapping("/example") public class ExampleController { @PostMapping(consumes = {"application/json", "text/plain"}, produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity<String> handleTextPlain(@RequestBody(required=false) String body){ return ResponseEntity.ok("Received: "+body); } } ``` 这里我们让 endpoint 同时消费 JSON 和 plain 文本两种输入,并只产出简单的字符串作为回应[^3]。 #### 注意事项 即使解决了上述问题,仍需注意实际业务逻辑里可能存在的其他潜在隐患。比如某些旧版浏览器可能会错误地标记上传文件流为 plain/text 而非 multipart/form-data 。因此建议始终验证传入数据的有效性和安全性[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值