Struts 1 直接將表單數據填充至 ActionForm,過程中未對 HttpServletRequest 執行 setCharacterEncoding(),導致預設使用 ISO-8859-1 解碼,中文產生亂碼。本文提供兩種經典解決方案:全域 Filter 方案(推薦)與 自訂 ActionServlet 方案,並解析原理與配置細節。
Tomcat org.apache.catalina.connector.HttpRequestBase.parseParameters() 預設以 ISO-8859-1 解碼請求參數。Struts 1 在 ActionServlet.process() 內部才建立 ActionForm 並填充屬性,此時若未預先設定請求編碼,中文已在解碼階段損壞,無法恢復。
package com.example.filter;
import java.io.IOException;
import javax.servlet.*;
public class CharacterEncodingFilter implements Filter {
private String encoding = "UTF-8";
@Override
public void init(FilterConfig config) throws ServletException {
String cfg = config.getInitParameter("encoding");
if (cfg != null && !cfg.trim().isEmpty()) encoding = cfg;
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding(encoding);
resp.setCharacterEncoding(encoding); // 統一回應編碼
chain.doFilter(req, resp);
}
@Override
public void destroy() {}
}
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.example.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>
package com.example.struts;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.ActionServlet;
public class EncodingActionServlet extends ActionServlet {
@Override
protected void process(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
String encoding = getInitParameter("encoding");
if (encoding != null) req.setCharacterEncoding(encoding);
super.process(req, resp);
}
}
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>com.example.struts.EncodingActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</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>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
| 維度 | Filter 方案 | ActionServlet 方案 |
|---|---|---|
| 適用範圍 | 全 Web 應用(含 JSP、Servlet、Struts) | 僅 Struts 處理的請求 (*.do) |
| 耦合度 | 零侵入,不依賴 Struts | 緊耦合 Struts 核心類別 |
| 執行順序 | 最早攔截,確保後續所有組件受益 | 在 Struts 內部,較晚 |
| 維護性 | 高,標準 Servlet API | 低,升級 Struts 版本可能失效 |
| 推薦等級 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
確保 JSP 編譯與輸出編碼一致,避免頁面顯示亂碼。
Struts 1 中文亂碼本質是請求參數解碼時機過晚。**全域 Filter 方案**符合 Servlet 規範、覆蓋面最廣、維護成本最低,是首選最佳實踐。配合 JSP 頁面編碼宣告,可徹底消除中文亂碼問題。