You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat 8.5.53特殊字符乱码问题:重启后自动恢复

Tomcat偶发UTF-8编码异常(重启自愈)问题排查与解决

遇到过好多次这类Tomcat偶发编码乱码、重启后自动恢复的情况,给你拆解分析下这两个问题的根因和靠谱的解决方案:

问题1:Web应用返回UTF-8编码特殊字符显示为????

现象回顾

Web应用返回的UTF-8编码特殊字符(比如'、é)显示为????,重启Tomcat后恢复正常。

可能根因

  • Tomcat的响应编码未全局强制锁定,当Connector的编码缓存出现异常时,默认切换到了不支持UTF-8的编码(比如ISO-8859-1)
  • 应用内的JSP/Servlet未正确设置响应的contentType为text/html;charset=UTF-8,且Tomcat全局响应编码配置未生效,重启后编码缓存重置,临时恢复正常

解决方案

  1. 全局配置Tomcat Connector编码
    修改conf/server.xml中的Connector节点,添加URIEncoding="UTF-8"和useBodyEncodingForURI="true",确保请求和响应的编码统一:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="UTF-8"
               useBodyEncodingForURI="true"/>
    
  2. 添加应用级编码过滤器
    在应用的web.xml中添加全局编码过滤器,强制所有请求和响应使用UTF-8:

    <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>
    

    如果不是Spring应用,可以自定义一个简单的编码过滤器,核心逻辑是设置request.setCharacterEncoding("UTF-8")和response.setCharacterEncoding("UTF-8")。

  3. 确保JSP页面编码正确
    所有JSP页面开头必须设置:

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

问题2:POST提交特殊字符用户名后Cookie解密乱码

现象回顾

部署在Tomcat 8.5.53的应用,POST提交含特殊字符的用户名(比如Amélie.Lacoste),对应的Cookie经Base64编码+AES加密后,解密解码结果显示为Am?lie.Lacoste,重启Tomcat后恢复正常。

可能根因

  • 核心问题是POST请求参数的编码未被强制设置,当Tomcat的参数解析缓存异常时,用了默认的ISO-8859-1编码解析POST参数,导致特殊字符被损坏后存入Cookie;重启后缓存重置,临时恢复了正确的UTF-8解析
  • Cookie的编码处理未显式指定UTF-8,Tomcat默认的Cookie编码在缓存异常时出现乱码

解决方案

  1. 强化Tomcat默认Servlet编码配置
    修改conf/web.xml中的default Servlet,添加编码参数:

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
  2. 显式处理Cookie的编码解码
    在设置Cookie值时,手动用UTF-8编码:

    String cookieValue = URLEncoder.encode(encryptedUsername, "UTF-8");
    Cookie userCookie = new Cookie("user", cookieValue);
    response.addCookie(userCookie);
    

    获取Cookie值时,用UTF-8解码:

    String cookieValue = URLDecoder.decode(cookie.getValue(), "UTF-8");
    String decryptedUsername = decryptAndDecode(cookieValue); // 你的解密解码逻辑
    
  3. 锁定JVM层面的默认编码
    在Tomcat的启动脚本(比如bin/catalina.sh或bin/catalina.bat)中添加JVM参数,确保JVM默认编码为UTF-8:

    # Linux/Mac 在catalina.sh中添加
    JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
    
    # Windows 在catalina.bat中添加
    set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
    

总结

这类偶发的重启自愈编码问题,本质是Tomcat的编码相关缓存(Connector编码缓存、参数解析缓存)出现异常,导致编码切换到了不支持UTF-8的格式。通过从Tomcat全局配置、应用代码配置、JVM参数三个层面强制锁定UTF-8编码,就能彻底避免这类问题再次发生,不用再依赖重启临时解决。

内容的提问来源于stack exchange,提问作者Akshay Gaba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 08:57:41