在 Servlet 開發中,中文亂碼是高頻痛點。常見錯誤是:Filter 初始化參數配置 UTF-8,但 JSP 頁面卻用 GBK,導致請求/響應編碼不一致,最終出現亂碼。本文提供基於全鏈路統一編碼的標准解決方案。
請求解碼、響應編碼、頁面編碼、數據庫連接、JVM 文件編碼 —— 必須全部統一為 UTF-8(推薦)或 GBK,絕不混用。
package cn.com.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import java.io.IOException;
/**
* 字符編碼過濾器
* 統一設置請求解碼與響應編碼
*/
@WebFilter(
urlPatterns = "/*",
initParams = @WebInitParam(name = "encoding", value = "UTF-8")
)
public class CharacterEncodingFilter implements Filter {
private String encoding = "UTF-8"; // 默認值
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String configEncoding = filterConfig.getInitParameter("encoding");
if (configEncoding != null && !configEncoding.isEmpty()) {
this.encoding = configEncoding;
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 1. 設置請求字符編碼(解決 POST 請求體亂碼)
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
// 2. 設置響應內容類型與字符編碼(解決輸出亂碼)
response.setContentType("text/html;charset=" + encoding);
response.setCharacterEncoding(encoding);
// 3. 繼續鏈路
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 清理資源(如有)
}
}
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>cn.com.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
| 環節 | 配置位置 | 推薦值 | 驗證方式 |
|---|---|---|---|
| 請求解碼 | Filter.doFilter -> request.setCharacterEncoding() | UTF-8 | POST 表單中文參數正確 |
| 響應編碼 | Filter.doFilter -> response.setCharacterEncoding()/setContentType() | UTF-8 | 瀏覽器 Network 面板 Content-Type: text/html;charset=UTF-8 |
| JSP 頁面編碼 | 頁面頂部 <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> | UTF-8 | 瀏覽器查看源碼中文正常 |
| HTML Meta 聲明 | <meta charset="UTF-8"> | UTF-8 | 瀏覽器自動識別編碼 |
| Java 源文件編碼 | IDE 設置 / Maven <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | UTF-8 | 編譯無警告,字符串字面量正確 |
| 數據庫連接 | JDBC URL ?characterEncoding=UTF-8 / useUnicode=true | UTF-8 | 中文存取正常 |
| Tomcat URI 編碼 | server.xml Connector URIEncoding="UTF-8" | UTF-8 | GET 參數中文正確 |
Spring Boot 2.1+ 默認提供 CharacterEncodingFilter,只需配置:
# application.yml
server:
servlet:
encoding:
charset: UTF-8
enabled: true
force: true # 強制覆蓋請求/響應編碼
force-request: true
force-response: true
server.xml 的 Connector 添加 URIEncoding="UTF-8",或 Spring Boot 配置 server.tomcat.uri-encoding=UTF-8。解決中文亂碼的核心是建立全鏈路 UTF-8 編碼閉環。通過 Filter 統一請求/響應編碼,配合頁面、數據庫、容器、構建工具的協同配置,可徹底消除亂碼問題。現代項目優先使用 Spring Boot 自動配置,傳統項目按本文 Filter 模板標準化部署。