在 Java Web 開發中,通过 URL 參數傳遞中文(如 `` 或 `response.sendRedirect("page?msg=中文")`)是極常見的場景。但由於瀏覽器、Web 容器、Java 內部編碼不一致,極易出現亂碼。本文梳理「編碼→傳輸→解碼」全鏈路,給出生產可用的標準化方案。
亂碼本質:編碼與解碼使用的字符集不匹配。
String raw = "中文參數";
String encoded = java.net.URLEncoder.encode(raw, StandardCharsets.UTF_8.name());
// 结果:%E4%B8%AD%E6%96%87%E5%8F%83%E6%95%B0
String url = "/target?msg=" + encoded;
UTF-8,避免平台默認編碼差異。String encoded = request.getParameter("msg"); // 容器已按 ISO-8859-1 或 UTF-8 解碼一次
if (encoded != null) {
// 關鍵:將容器解碼後的字符串「還原」為原始位元組,再按 UTF-8 重組
String decoded = new String(encoded.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
// decoded 即為 "中文參數"
}
為什麼用 ISO-8859-1? 它是單字節編碼,0x00~0xFF 一一映射,能無損「還原」容器解碼時產生的位元組序列,再按真實編碼(UTF-8)重組字符串。
修改 server.xml 的 `URIEncoding="UTF-8":
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
useBodyEncodingForURI="true" />
URIEncoding:指定 URL 解碼字符集(含 Query String)。useBodyEncodingForURI:若為 true,優先用請求體編碼(request.setCharacterEncoding)解碼 URL。效果:配置後,request.getParameter("msg") 直接返回正確中文,**無需手動轉碼**。但需確保前端頁面編碼也是 UTF-8(``)。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean<CharacterEncodingFilter> encodingFilter() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true); // 強制 request/response 編碼
filter.setForceRequestEncoding(true);
filter.setForceResponseEncoding(true);
FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(filter);
bean.addUrlPatterns("/*");
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
配合 Tomcat URIEncoding="UTF-8",實現全鏈路 UTF-8 無感知。
| 場景 | 錯誤做法 | 正確做法 |
|---|---|---|
| JS 構建 URL | `url + "?name=" + name` | `url + "?name=" + encodeURIComponent(name)` |
| Java 後端重定向 | `redirect:/page?name=" + name` | `redirect:/page?name=" + URLEncoder.encode(name, "UTF-8")` |
| 表單 GET 提交 | 依賴瀏覽器默認編碼 | 頁面強制 `` + 後端配置 URIEncoding |
| 雙重編碼 | 前端 encode + 後端再 encode | 全鏈路只編碼一次,解碼一次 |
new String(param.getBytes(ISO_8859_1), UTF_8) 手動轉碼,或封裝工具類/攔截器。