瀏覽器發送請求參數預設以 ISO-8859-1 編碼;伺服器若以 GBK/UTF-8 解碼即產生亂碼。解決核心:統一雙端編碼為 UTF-8。
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
所有 .jsp/.java 檔案以 UTF-8 儲存(IDE 設定 File Encoding = UTF-8)。
<filter>
<filter-name>SetCharacterEncodingFilter</filter-name>
<filter-class>com.example.filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
package com.example.filter;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class SetCharacterEncodingFilter implements Filter {
private String encoding = "UTF-8";
private boolean ignore = true;
public void init(FilterConfig config) {
String e = config.getInitParameter("encoding");
if (e != null) encoding = e;
String ig = config.getInitParameter("ignore");
if (ig != null) ignore = Boolean.parseBoolean(ig);
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
if (ignore || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding); // POST 直接生效
}
// GET 參數需包裝 Request 覆寫 getParameter
if ("GET".equalsIgnoreCase(request.getMethod())) {
request = new Utf8RequestWrapper(request);
}
chain.doFilter(request, res);
}
public void destroy() {}
}
// 包裝類:自動將 ISO-8859-1 -> UTF-8
class Utf8RequestWrapper extends HttpServletRequestWrapper {
public Utf8RequestWrapper(HttpServletRequest request) { super(request); }
private String decode(String s) {
try { return new String(s.getBytes("ISO-8859-1"), "UTF-8"); }
catch (Exception e) { return s; }
}
@Override public String getParameter(String name) { return decode(super.getParameter(name)); }
@Override public String[] getParameterValues(String name) {
String[] vals = super.getParameterValues(name);
if (vals != null) for (int i=0;i
server.xml 的 <Connector> 加入:
<Connector port="8080" protocol="HTTP/1.1"
URIEncoding="UTF-8" useBodyEncodingForURI="true" />
配合 Filter,GET/POST 參數全自動正確解碼,無需手動轉碼。
jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Taipei
// 取得原始 Connection
Connection raw = dataSource.getConnection();
// 包裝為自動轉碼 Connection
Connection conn = new EncodingConnection(raw, true, "ISO-8859-1", "UTF-8");
// 後續 setString/getString 直接用中文,內部自動雙向轉碼
EncodingConnection 透過 Proxy 模式攔截 PreparedStatement.setString / ResultSet.getString 實現透明轉碼,避免業務代碼散落轉碼邏輯。
EncodingFilter 映射 /*,ignore=true。URIEncoding="UTF-8" useBodyEncodingForURI="true"。encodeURIComponent(value)。characterEncoding=UTF-8。EncodingConnection 透明包裝。