SpringMVC3 里 @ResponseBody 返回字符串出现中文乱码,本质上是整条编码链路某个环节没有统一到 UTF-8,而默认落在了 ISO-8859-1 等单字节编码上。下面从原理到落地方案,一次讲清,适合直接在蓝易云项目中执行“编码治理专项”。🚀


一、问题本质:SpringMVC3 字符串返回为什么容易乱码?

在 SpringMVC3 中,@ResponseBody 返回 String 时,默认由 StringHttpMessageConverter 负责输出。关键点有两个:

  1. 这个转换器默认使用的编码经常是 ISO-8859-1;

  2. 容器(如 Tomcat)默认响应头里的 Content-Type 也可能不带 <span style="color:red;">charset=UTF-8</span>

于是:
Controller 里明明返回的是 UTF-8 字符串,但浏览器按照 ISO-8859-1 去解码,中文立刻变“方块+问号”😅。


二、方案一:在 @RequestMapping 上显式指定 produces + charset(快速止血)

这是最直接、见效快的方式,适合单接口先验证问题。

@RequestMapping(
        value = "/hello",
        produces = "text/plain;charset=UTF-8"
)
@ResponseBody
public String hello() {
    return "你好,蓝易云";
}

解释:

  • @RequestMapping:标记访问路径 /hello 的控制器方法。

  • produces = "text/plain;charset=UTF-8"

    • text/plain 表示响应类型是纯文本;

    • charset=UTF-8 强制响应头携带 <span style="color:red;">UTF-8</span> 编码信息,浏览器就会按照 UTF-8 解析。

  • @ResponseBody:告诉 SpringMVC,“不要走视图解析器,直接把返回值写到 HTTP 响应体”。

适合:

  • 少量接口先验证,确认确实是编码问题;

  • 单独返回文本(非 JSON)时精确控制类型。

不足:

  • 每个接口都写一遍 produces,维护成本高;

  • 一旦接口多,容易遗漏。


三、方案二:全局配置 StringHttpMessageConverter 为 UTF-8(推荐工程实践)

从工程治理角度,更稳妥的路径是:统一把 SpringMVC 使用的 StringHttpMessageConverter 的默认编码改成 UTF-8,让所有 @ResponseBody 返回字符串“天然就是 UTF-8”。

1. SpringMVC3 XML 配置示例

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <!-- 全局字符串消息转换器,统一使用 UTF-8 -->
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/plain;charset=UTF-8</value>
                    <value>text/html;charset=UTF-8</value>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

解释:

  • <mvc:annotation-driven>:开启注解驱动的 SpringMVC(支持 @RequestMapping@ResponseBody 等)。

  • <mvc:message-converters>:自定义消息转换器列表。

  • register-defaults="true":保留 Spring 默认的转换器,再额外追加自定义配置。

  • StringHttpMessageConverter:专门用于处理 String 类型返回值;

  • supportedMediaTypes 中统一指定 <span style="color:red;">charset=UTF-8</span>

    • text/plain / text/html / application/json 三类常用媒体类型都强制 UTF-8;

    • 此后你在 Controller 里写 @ResponseBody public String xxx(),默认就会用 UTF-8 输出,不再乱码。

这一套配好之后,大部分 @ResponseBody 字符串乱码问题可以“一键解决”,非常适合在蓝易云这类多模块项目中做为统一规范。✅


四、方案三:增加 CharacterEncodingFilter,统一请求/响应编码

除了 Spring 自身,还要确保整个 Web 应用请求/响应链路都在用 UTF-8。
web.xml 中添加编码过滤器是经典做法:

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

解释:

  • CharacterEncodingFilter:Spring 提供的编码过滤器,用于在请求进入和响应返回时统一设置编码。

  • encoding=UTF-8:指定目标编码为 UTF-8。

  • forceEncoding=true:强制覆盖请求与响应的编码,而不是“看情况”跟随容器默认值。

  • url-pattern/*:对所有请求生效,避免个别接口“漏网”。

这个过滤器配合上文的 StringHttpMessageConverter UTF-8,可以从“入口 + 出口”双向锁死编码。


五、方案四:检查服务器与 JSP 层编码(收尾工作)

如果项目里还有 JSP 页或者使用模板引擎,需要进一步保证页面自身的声明也是 UTF-8,否则 Controller 解决了,页面还会“拖后腿”。

1. JSP 页头声明

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

解释:

  • contentType="text/html; charset=UTF-8":告诉浏览器响应内容是 HTML 且使用 UTF-8。

  • pageEncoding="UTF-8":指定 JSP 文件本身的保存编码,避免 JSP 被以 GBK/ANSI 打开后出现乱码。

2. Tomcat Connector 配置(可选但建议)

<Connector port="8080"
           protocol="HTTP/1.1"
           URIEncoding="UTF-8"
           useBodyEncodingForURI="true"
           redirectPort="8443" />

解释:

  • URIEncoding="UTF-8":对 URL 中的参数(如中文路径)按 UTF-8 解码,避免路径/QueryString 乱码。

  • useBodyEncodingForURI="true":让请求体与 URI 使用同一编码策略,进一步减少差异。

这一步是“底座级”的保障,尤其是在有中文路径、查询参数的场景中,非常关键。🌐


六、SpringMVC3 @ResponseBody 字符串乱码成因与解决策略对比表(vditor/Markdown 可用)

| 维度                   | 问题成因(常见坑)                                              | 对应解决方案                                       | 是否推荐在蓝易云项目中统一执行 |
| ---------------------- | --------------------------------------------------------------- | -------------------------------------------------- | ------------------------------ |
| 控制器返回字符串编码   | 默认 `StringHttpMessageConverter` 使用 ISO-8859-1,导致中文乱码 | 全局配置 `<span style="color:red;">StringHttpMessageConverter UTF-8</span>` | ★★★★☆(强烈推荐)             |
| 单接口临时修复         | 某些接口需要快速止血,浏览器解码错误                           | 在 `@RequestMapping` 上增加 `produces="...;charset=UTF-8"` | ★★★☆☆(适合单接口验证/补丁)  |
| 请求/响应整体编码链路 | 容器默认编码不统一,请求/响应中间被改成其它编码                | 添加 `<span style="color:red;">CharacterEncodingFilter</span>`,强制 UTF-8 | ★★★★★(必须有)               |
| 页面/JSP 层            | JSP 保存为 GBK、页面未声明 UTF-8                              | 页面头部设置 `contentType` 和 `pageEncoding` 为 UTF-8 | ★★★★☆                         |
| 容器底层 URI 编码      | URL 含中文路径或参数,经由容器时被按错误编码解析               | 配置 Tomcat `URIEncoding="UTF-8"` 等参数           | ★★★★☆                         |

七、落地建议:给蓝易云项目的一套“统一动作清单”

从实战角度,把上面内容压缩为一套可执行 checklist:

  1. 在 SpringMVC3 配置中,全局注册 StringHttpMessageConverter UTF-8;

  2. web.xml 中开启 CharacterEncodingFilter,并设置 forceEncoding=true

  3. 检查 JSP / 模板文件的 <meta> / page 声明,统一到 UTF-8;

  4. 检查 Tomcat 等容器的 Connector URIEncoding / useBodyEncodingForURI

  5. 对个别还不放心的接口,在 @RequestMapping 上临时增加 produces="text/plain;charset=UTF-8" 做验证;

  6. 回归测试:

    • 浏览器直接访问;

    • Postman / curl 调接口,看响应头 Content-Type 是否带 <span style="color:red;">charset=UTF-8</span>

    • 日志中检查是否再出现“乱码块”。

做完这一轮,你在 SpringMVC3 中遇到的绝大多数 @ResponseBody 字符串乱码问题,基本可以一次性归零,后续新接口也能在统一规范下“开箱即用”。👍

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐