為什么會(huì)有亂碼
??產(chǎn)生亂碼的原因一句話就能說明白:
編碼和解碼使用的字符集不同沧卢。
??比如說在后端把字符串 "你好,世界" 按照 UTF-8 進(jìn)行編碼顽铸,但是前端卻按照 GB2312 進(jìn)行解碼臭挽,那自然會(huì)產(chǎn)生亂碼。
解決 response 中的亂碼
??因?yàn)槟壳按蟛糠譃g覽器都是采用 UTF-8 編碼的,所以向?yàn)g覽器輸出中文字符,只需在 doGet 方法中指定 Content-Type:text/html;charset=utf-8掷漱。
response.setContentType("text/html;charset=utf-8");
解決 request 中的亂碼
GET
??獲取 HTTP 請(qǐng)求中的中文參數(shù)時(shí)可能會(huì)有亂碼,所以先將字符串變回字節(jié)數(shù)組榄檬,然后再按照 UTF-8 進(jìn)行編碼卜范。假設(shè) HTTP 請(qǐng)求中帶了一個(gè) username 的參數(shù),那么就需要在 doGet 方法中進(jìn)行如下處理
String username = request.getParameter("username");
// Tomcat 默認(rèn)的編碼方式是 ISO8859-1
username = new String(username.getBytes("iso8859-1"),"utf-8");
??問題是鹿榜,在實(shí)際的應(yīng)用場(chǎng)景中 HTTP 請(qǐng)求攜帶的參數(shù)可能有多個(gè)海雪,所以就不能只針對(duì)某個(gè)參數(shù)進(jìn)行修改。解決的方案是使用裝飾器模式舱殿,寫一個(gè) HttpServletRequest 的裝飾器類喳魏,經(jīng)過裝飾的 request 對(duì)請(qǐng)求中的任何參數(shù)都能進(jìn)行編碼的處理。
// 裝飾器類怀薛,用來設(shè)置 GET 請(qǐng)求的編碼
public class EncodingRequest extends HttpServletRequestWrapper{
private HttpServletRequest request; // 真正的 request 對(duì)象
public EncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) { // 覆寫 getParameter 方法,將所有參數(shù)的編碼設(shè)置為 UTF-8
String value = request.getParameter(name);
try {
value = new String(value.getBytes("iso-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return value;
}
}
??然后用一個(gè) Filter 對(duì)所有的請(qǐng)求進(jìn)行編碼的處理迷郑,然后再把處理過后的 request 對(duì)象傳遞給 Servlet:
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if (req.getMethod().equals("GET")) { // 處理 GET 請(qǐng)求的編碼
EncodingRequest encodingReq = new EncodingRequest(req);
// 注意這里傳遞的是 EncodingRequest 對(duì)象
chain.doFilter(encodingReq, response);
}
if (req.getMethod().equals("POST")) { // 處理 POST 請(qǐng)求的編碼
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
}
public void init(FilterConfig fConfig) throws ServletException {}
}
POST
??因?yàn)榇蠖鄶?shù)情況下我們?cè)?doPost 方法內(nèi)都會(huì)調(diào)用 doGet 方法枝恋,因此按照上面的做法就能解決 POST 請(qǐng)求中的中文亂碼問題。如果使用 Spring 進(jìn)行開發(fā)嗡害,那么有 POST 請(qǐng)求亂碼的專門解決方案焚碌。在 web.xml 中添加如下配置:
<!-- POST 亂碼過濾器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
??這樣就可以解決 POST 的亂碼問題了。