在使用tomcat的時候, 一直很好奇他是怎麼對請求的參數進行編解碼的,帶着下面三個問題,一起看下。
1. get/post請求如何編解碼,根據什麼參數配置
2. URI編碼
3. 中文參數爲什麼會出現亂碼
1. 下圖是tomcat各版本默認的編解碼方式
我們發現tomca6和tomcat7對URI的默認解碼方式爲ISO-8859-1, 但是涉及中文入參的請求,一般參數採用utf-8或gbk編碼,這樣就會出現編解碼方式不一致,導致亂碼。
2. URI編碼
上圖解釋了爲什麼我們會看到的瀏覽器地址欄的帶有百分號的url地址,因爲我們明明可能輸入的是帶中文的參數,但是看到的卻是包含%的參數
3. 編解碼過程的實現(以tomcat8爲例)
Tomcat對於參數的處理方法爲org.apache.catalina.connector.Request#parseParameters
Charset charset = getCharset(); boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); parameters.setCharset(charset); // POST請求處理 if (useBodyEncodingForURI) { parameters.setQueryStringCharset(charset); }// GET請求,處理URI parameters.handleQueryParameters();
org.apache.tomcat.util.http.Parameters
private Charset queryStringCharset = StandardCharsets.UTF_8;// GET請求處理,默認採用UTF-8編碼 processParameters(decodedQuery, queryStringCharset);
POST請求從Content-type中取編碼方式
Charset charset = getCharset();
public Charset getCharset() throws UnsupportedEncodingException { if (charset == null) { getCharacterEncoding(); if (characterEncoding != null) { charset = B2CConverter.getCharset(characterEncoding); } } return charset; }
public String getCharacterEncoding() { if (characterEncoding == null) { characterEncoding = getCharsetFromContentType(getContentType()); } return characterEncoding; }
從http頭部獲取響應值編碼方式
public MessageBytes contentType() { if (contentTypeMB == null) { contentTypeMB = headers.getValue("content-type"); } return contentTypeMB; }