首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java URL 中文亂碼徹底解決方案:JS 編碼、Filter 過濾、Tomcat 配置三大體系

     編輯:Java 相關知識

前言

URL 中文亂碼是 Java Web 開發經典痛點。GET 請求參數在瀏覽器、代理、伺服器多層編解碼下極易出錯。本文系統梳理三大解決體系:前端 JS 編碼、後端 Filter 過濾、Tomcat 容器配置,助你徹底根治。

一、亂碼根因分析

GET 請求 URL 編碼流程:

  1. 瀏覽器將中文按頁面編碼(或 UTF-8)編碼為 %XX%XX
  2. 發送 HTTP 請求,URL 中攜帶編碼後字節
  3. Tomcat 接收請求,按 URIEncoding(預設 ISO-8859-1)解碼為字串
  4. Servlet request.getParameter() 返回解碼後字串

核心衝突:瀏覽器編碼 ≠ Tomcat 解碼編碼 → 亂碼。POST 請求體由 request.setCharacterEncoding() 控制,通常不受影響。

二、方案一:前端 JS 雙重編碼(最徹底,需前後端配合)

核心 API 對比

方法編碼範圍不編碼字符適用場景
escape()非 ASCII@ * + - . / _已棄用,不推薦
encodeURI()整個 URL! @ # $ & * ( ) = : / ; ? + ' ~編碼完整 URL
encodeURIComponent()單個參數值~ ! * ( ) ' (僅保留極少)編碼參數值(推薦)

單次編碼方案

// 前端
var url = '/search?name=' + encodeURIComponent('中文關鍵字');
window.location.href = url;

// 後端:Tomcat URIEncoding=UTF-8 時自動正確解碼
// 若 Tomcat 預設 ISO-8859-1,需手動轉碼:
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");

雙重編碼方案(兼容舊容器配置)

// 前端:雙重 encodeURI
var url = '/search?name=' + encodeURI(encodeURI('中文關鍵字'));
// 生成:/search?name=%25E4%25B8%25AD%25E6%2596%2587...

// 後端:URLDecoder 解碼
String name = request.getParameter("name");
name = URLDecoder.decode(name, "UTF-8"); // 自動處理 %25 -> % -> 字節

原理:第一次編碼產生 %E4%B8%AD,第二次將 % 編碼為 %25,Tomcat 按 ISO-8859-1 解碼還原為 %E4%B8%AD,後端 URLDecoder 再次解碼得到中文。

三、方案二:Filter 統一解碼(推薦,透明無感)

1. 簡易版:僅設置請求編碼(僅對 POST 生效)

@WebFilter("/*")
public class EncodingFilter implements Filter {
    private String encoding = "UTF-8";

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        req.setCharacterEncoding(encoding);
        resp.setCharacterEncoding(encoding);
        chain.doFilter(req, resp);
    }
}

局限:setCharacterEncoding 對 GET 請求無效(參數已在 URL 解析階段完成解碼)。

2. 完整版:手動解碼 GET 參數(核心方案)

@WebFilter("/*")
public class UrlDecodingFilter implements Filter {
    private String encoding = "UTF-8";

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // POST:直接設置編碼
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            try { request.setCharacterEncoding(encoding); } catch (Exception ignored) {}
        }
        // GET:手動重新解碼所有參數
        else {
            Map<String, String[]> paramMap = request.getParameterMap();
            if (paramMap != null) {
                for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
                    String[] values = entry.getValue();
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 關鍵:ISO-8859-1 -> 字節 -> UTF-8 字串
                                values[i] = new String(values[i].getBytes("ISO-8859-1"), encoding);
                            } catch (UnsupportedEncodingException ignored) {}
                        }
                    }
                }
            }
        }

        response.setContentType("text/html;charset=" + encoding);
        chain.doFilter(request, response);
    }
}

原理:Tomcat 預設用 ISO-8859-1 解碼 URL,得到的字串實際是「字節值對應的 ISO-8859-1 字符」。將其按 ISO-8859-1 轉回字節,再按 UTF-8 解碼,即還原原始中文。

四、方案三:Tomcat 容器級配置(最簡單,推薦生產環境)

修改 $CATALINA_HOME/conf/server.xml,在 <Connector> 添加 URIEncoding:

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"
           useBodyEncodingForURI="true" />
  • URIEncoding="UTF-8":強制 Tomcat 用 UTF-8 解碼 URL(GET 參數)
  • useBodyEncodingForURI="true":若請求體編碼(POST)與 URI 編碼一致,可簡化配置

重啟 Tomcat 即時生效,無需代碼修改。Spring Boot 內嵌 Tomcat 配置:

server.tomcat.uri-encoding=UTF-8

五、JSP 頁面編碼雙重保障

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

六、方案對比與選型建議

方案優點缺點推薦指數
Tomcat URIEncoding零代碼侵入、全局生效、效能最佳需控制容器配置權限⭐⭐⭐⭐⭐
Filter 手動解碼應用層可控、無需容器權限、兼容性好需確保 Filter 順序在最前、略增 CPU⭐⭐⭐⭐
JS 雙重編碼無後端依賴、兼容舊環境前後端強耦合、URL 難閱讀、易漏編碼⭐⭐

七、終極建議

  1. 生產環境首選 Tomcat URIEncoding=UTF-8,一勞永逸。
  2. 無容器控制權時,部署 UrlDecodingFilter 並確保 <filter-mapping> 排在最前。
  3. 避免手動 new String(bytes, "ISO-8859-1") 分散在業務代碼中,集中到 Filter。
  4. POST 請求同樣受益:useBodyEncodingForURI="true" 讓請求體編碼與 URI 保持一致。
  5. 資料庫連接字串:JDBC URL 添加 characterEncoding=utf8&useUnicode=true。

八、總結

URL 中文亂碼本質是編碼與解碼不一致。掌握「瀏覽器編碼 → Tomcat 解碼 → Servlet 獲取」鏈路,在正確層面統一 UTF-8,即可徹底解決。生產環境強烈建議容器級配置 Tomcat URIEncoding=UTF-8,輔以 JSP 頁面編碼聲明,零代碼侵入、效能最優、維護成本最低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved