如何强制@RestController将响应体编码为指定字符集?
我有一个@RestController,类上配置了如下@RequestMapping注解:
@RestController @RequestMapping(consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
同时在方法上配置了:
@RequestMapping(value = "/api/", method = RequestMethod.POST, produces = "application/xml;charset=windows-1251")
使用Postman请求后得到的响应为<tag field="Абонент найден"/>,这本质是UTF-8编码的字节被客户端以windows-1251解码导致的乱码。
需求是:将Java中的Unicode字符串转换为windows-1251编码的字节输出,而非仅修改HTTP响应头的charset声明。
1. 全局配置XML消息转换器编码
Spring默认的XML消息转换器(如Jaxb2RootElementHttpMessageConverter或MappingJackson2XmlHttpMessageConverter)会用UTF-8编码响应内容,需要修改其默认编码为windows-1251。创建Web配置类:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 针对JAXB处理XML的场景 Jaxb2RootElementHttpMessageConverter xmlConverter = new Jaxb2RootElementHttpMessageConverter(); MediaType windows1251Xml = new MediaType("application", "xml", Charset.forName("windows-1251")); xmlConverter.setSupportedMediaTypes(Collections.singletonList(windows1251Xml)); converters.add(xmlConverter); // 若使用Jackson处理XML,替换为以下代码 // MappingJackson2XmlHttpMessageConverter jacksonXmlConverter = new MappingJackson2XmlHttpMessageConverter(); // jacksonXmlConverter.setDefaultCharset(Charset.forName("windows-1251")); // converters.add(jacksonXmlConverter); } }
该配置会让所有XML响应直接以windows-1251编码生成字节,配合@RequestMapping的produces声明,客户端能正确解析。
2. 方法级手动处理响应输出
如果仅需单个接口生效,可以直接操作HttpServletResponse,手动控制编码输出:
@RequestMapping(value = "/api/", method = RequestMethod.POST) public void handleRequest(HttpServletResponse response) throws IOException { // 业务逻辑生成的结果字符串(Java中为Unicode编码) String result = "<tag field=\"Абонент найден\"/>"; // 设置响应头 response.setContentType("application/xml;charset=windows-1251"); // 将Unicode字符串转换为windows-1251字节序列并写入响应流 response.getOutputStream().write(result.getBytes(Charset.forName("windows-1251"))); }
注意:Java字符串本身是Unicode编码,调用getBytes("windows-1251")会直接将字符映射为windows-1251对应的字节,避免了中间的UTF-8转换环节。
3. Spring Boot配置文件全局指定编码
在application.properties中添加配置,直接指定XML消息转换器的编码:
spring.http.converters.xml.charset=windows-1251 spring.http.converters.xml.enabled=true
此方式适合Spring Boot项目,无需编写配置类,简单直接。
你遇到的乱码是编码不匹配导致的:Spring默认用UTF-8生成响应字节,而响应头声明windows-1251,客户端用windows-1251解码UTF-8字节,出现“乱码”。正确逻辑是直接生成windows-1251编码的字节,同时响应头声明对应charset,确保客户端解码时用相同编码。
内容的提问来源于stack exchange,提问作者Eljah

