Struts + Hibernate 應用中,HTTP 請求參數編碼、JSP 頁面編碼、數據庫連接編碼、JVM 文件編碼不一致,導致中文存儲讀取亂碼。核心缺口:Servlet 規範未強制要求容器按指定編碼解碼請求參數。
基於 Servlet Filter 攔截所有請求,在參數讀取前強制設置編碼。
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>com.company.demo.util.SetEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value> <!-- 或 UTF-8 -->
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
package com.company.demo.util;
import java.io.IOException;
import javax.servlet.*;
public class SetEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true; // 默認忽略客戶端指定編碼
public void destroy() {
encoding = null; filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 若忽略模式 或 請求未設置編碼,則強制設置
if (ignore || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(selectEncoding(request));
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null) this.ignore = true;
else this.ignore = "true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value);
}
protected String selectEncoding(ServletRequest request) {
return this.encoding; // 可擴展:根據請求動態決定編碼
}
// getter/setter 省略
}
| 環節 | 配置要點 |
|---|---|
| JSP 頁面 | <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> |
| web.xml | 過濾器 encoding=UTF-8;<jsp-config><jsp-property-group><page-encoding>UTF-8</page-encoding></jsp-property-group></jsp-config> |
| Struts | struts-config.xml controller contentType="text/html;charset=UTF-8" |
| Hibernate | 數據庫連接 URL 追加 ?useUnicode=true&characterEncoding=UTF-8;MySQL 表/列 CHARSET=utf8 |
| 數據庫 | CREATE DATABASE ... DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci |
| JVM | 啟動參數 -Dfile.encoding=UTF-8 (慎用,影響日志等) |