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

Java Web 編碼解碼全攻略:徹底解決中文 URL 亂碼

     編輯:Java 相關知識

核心流程:請求與響應的編解碼鏈路

用戶發送 HTTP 請求 → 瀏覽器對 URL、Cookie、Parameter 編碼 → 服務器接收並解析 → 對 URL、Cookie、Parameter 解碼 → 業務邏輯處理(涉及數據庫、文件等編解碼) → 服務器編碼響應 → 瀏覽器解碼顯示。最易發生亂碼的環節在於客戶端與服務器的交互過程。

四種請求方式與編碼行為

  1. 直接輸入 URL
  2. 頁面超鏈接
  3. 表單 GET 提交
  4. 表單 POST 提交

URL 編碼詳解

URL 結構

scheme://host:port/path?queryString。瀏覽器會對 path 和 queryString 進行編碼。

主流瀏覽器編碼差異(以「我是」為例)

瀏覽器Path 編碼QueryString 編碼
FirefoxUTF-8 (E6 88 91 E6 98 AF)UTF-8 (E6 88 91 E6 98 AF)
ChromeUTF-8 (E6 88 91 E6 98 AF)UTF-8 (E6 88 91 E6 98 AF)
IEUTF-8 (E6 88 91 E6 98 AF)GBK (CE D2 CA C7)

編碼規範:非 ASCII 字符按編碼轉為 16 進制字節,每字節前加「%」。

Tomcat 解碼機制

URI 解碼

在 org.apache.catalina.connector.CoyoteAdapter.convertURI 中,讀取 Connector 配置的 URIEncoding:

<Connector URIEncoding="utf-8" />

未配置則默認 ISO-8859-1。

QueryString 解碼

首次調用 request.getParameter 時觸發 parseParameters,解碼邏輯:

  • 若設置了 request.setCharacterEncoding(enc),則用該編碼;
  • 否則用 Content-Type 中的 charset;
  • 再無則默認 ISO-8859-1。

若需讓 QueryString 也用 Body 編碼,需配置:

<Connector URIEncoding="UTF-8" useBodyEncodingForURI="true"/>

表單提交編碼差異

GET 提交

數據拼接在 URL 後,屬於 QueryString 部分,受 URIEncoding 控制。若頁面 UTF-8 而 Tomcat 未配或配錯,會亂碼。常用修正:

new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8")

POST 提交

瀏覽器按 Content-Type charset 編碼,服務器同樣用該 charset 解碼,通常不會亂碼。可通過 request.setCharacterEncoding(charset) 手動指定。

解決中文 URL 亂碼的多種方案

1. JavaScript 編碼(繞過瀏覽器差異)

  • escape():ISO Latin 編碼,輸出 %uXXXX 格式,不編碼「+」,不適合直接用於 URL。
  • encodeURI():UTF-8 編碼整個 URL,不編碼特殊符號 ! @ # $ & * ( ) = : / ; ? + '。
  • encodeURIComponent():UTF-8 編碼 URL 組成部分,比 encodeURI 更強,會編碼 ; / ? : @ & = + $ , # 等。

推薦使用 encodeURIComponent 對參數單獨編碼。

單次編碼 + 後台手動解碼

// 前端
var url = '/ShowMoblieQRCode.servlet?name=我是cm';
window.location.href = encodeURI(url);
// 後台
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");

雙重編碼 + URLDecoder 解碼

// 前端
window.location.href = encodeURI(encodeURI(url));
// 後台
String name = request.getParameter("name");
name = URLDecoder.decode(name, "UTF-8");

2. Filter 方案(推薦)

方案一:統一設置請求編碼

public class CharacterEncoding implements Filter {
    private String encoding;
    public void init(FilterConfig config) {
        encoding = config.getInitParameter("encoding");
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        req.setCharacterEncoding(encoding);
        chain.doFilter(req, resp);
    }
}
// web.xml 配置 encoding=utf-8,url-pattern=/*

方案二:在 Filter 中手動解碼 GET 參數並存入 Attribute

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    String method = request.getMethod();
    if ("post".equalsIgnoreCase(method)) {
        request.setCharacterEncoding("UTF-8");
    } else { // GET
        Enumeration<String> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String name = paramNames.nextElement();
            String[] values = request.getParameterValues(name);
            if (values != null) {
                for (int i = 0; i < values.length; i++)
                    values[i] = new String(values[i].getBytes("ISO-8859-1"), "UTF-8");
                request.setAttribute(name, values);
            }
        }
    }
    chain.doFilter(request, response);
}

3. 通用配置

  • JSP 頁面:<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
  • Tomcat server.xml:<Connector URIEncoding="utf-8" />

總結

中文 URL 亂碼源於瀏覽器、操作系統、頁面編碼、服務器配置的多重不一致。最佳實踐:統一全鏈路 UTF-8,配置 Tomcat URIEncoding,配合 Filter 統一處理 GET/POST,前端採用 encodeURIComponent。徹底消除亂碼隱患。

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