javaweb项目中遇到的一些乱码问题
在做javaweb項目時,我們經常會遇到一些亂碼問題:
首先,確定一點思想:要想不亂碼,你要保證編碼一致就行了,即統一編碼~
其一,jsp等頁面中的中文顯示亂碼(這里不只是說jsp文件,其它文件也有這種情況)
這時你要注意2點,一是你這個jsp文件是不是用utf-8編寫的,在所有的編寫工具中你都能進行設置的,比如在EditPlus中,
或者在myeclipse中,都能設置的,MyEclipse編碼設置
另外,你還要在jsp頭部添加這個(有的形式可能不一樣,但意思一樣就行了),
其二,服務器響應亂碼
服務器發送給客戶端數據!響應是由response對象來完成,response是響應對象,向客戶端輸出響應正文(響應體)可以使用response的響應流,repsonse一共提供了兩個響應流對象,
PrintWriter out = response.getWriter():獲取字符流;
ServletOutputStream out = response.getOutputStream():獲取字節流;
當然,如果響應正文內容為字符,那么使用response.getWriter(),如果響應內容是字節,例如下載時,那么可以使用response.getOutputStream()。注意,在一個請求中,不能同時使用這兩個流!也就是說,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同時使用這兩個流。不然會拋出IllegalStateException異常。
如果響應的數據不是字符數據,那么就無需去考慮編碼問題。當然,如果響應的數據是字符數據,那么就一定要考慮編碼的問題了。
response.getWriter().print(“博客”);
上面代碼因為沒有設置repsonse.getWriter()字符流的編碼,所以服務器使用默認的編碼(ISO-8859-1)來處理,因為ISO-8859-1不支持中文,所以一定會出現亂碼的。
所以在使用response.getWriter()發送數據之前,一定要設置response.getWriter()的編碼,這需要使用response.setCharacterEncoding()方法:
response.setCharacterEncoding(“utf-8”);
response.getWriter().print(“博客”);
上面代碼因為在使用response.getWriter()輸出之前已經設置了編碼,所以輸出的數據為utf-8編碼。但是,因為沒有告訴瀏覽器使用什么編碼來讀取響應數據,所以很可能瀏覽器會出現錯誤的解讀,那么還是會出現亂碼的。
當然,通常瀏覽器都支持來設置當前頁面的編碼,如果用戶在看到編碼時,去設置瀏覽器的編碼,如果設置的正確那么亂碼就會消失。
在靜態頁面中,使用<meta>來設置content-type響應頭,例如:
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
但是我們不能讓用戶總去自己設置編碼,而且應該直接通知瀏覽器,服務器發送過來的數據是什么編碼,這樣瀏覽器就直接使用服務器告訴他的編碼來解讀!這需要使用content-type響應頭。
response.setContentType(“text/html;charset=utf-8”);
response.getWriter().print(“博客”);
上面代碼使用setContentType()方法設置了響應頭content-type編碼為utf-8,這不只是在響應中添加了響應頭,還等于調用了一次response.setCharacterEncoding(“utf-8”),也就是說,通過我們只需要調用一次response.setContentType(“text/html;charset=utf-8”)即可,而無需再去調用response.setCharacterEncoding(“utf-8”)了。
其三,請求編碼亂碼
頁面的編碼就是頁面中輸入數據的編碼。
當客戶端通過POST請求發送數據給服務器時,可以在使用request.getParameter()獲取請求參數之前先通過request.setCharacterEncoding()來指定編碼,然后再使用reuqest.getParameter()方法來獲取請求參數,那么就是用指定的編碼來讀取了。
也就是說,如果是POST請求,服務器可以指定編碼!但如果沒有指定編碼,那么默認還是使用ISO-8859-1來解讀。
request.setCharacterEncoding(“utf-8”);
String name = request.getParameter(“name”);
當客戶端通過GET請求發送數據給服務器時,使用request.getParameter()獲取的數據是被服務器誤認為ISO-8859-1編碼的,也就是說客戶端發送過來的數據無論是UTF-8還是GBK,服務器都認為是ISO-8859-1,問題本質是get方式傳遞的參數內容默認編碼方式問ISO8859-1,而且使用request.setCharacterEncoding("utf-8")也無法解決問題,要解決這個問題我用過3種辦法;
(1)我們需要在使用request.getParameter()獲取數據后,再轉發成正確的編碼。例如客戶端以UTF-8發送的數據,使用如下轉碼方式:
String name = request.getParameter(“name”);
name = new String(name.getBytes(“iso-8859-1”), “utf-8”);
這種是什么時候遇到亂碼再解決(解碼),但不推薦,每次都要弄,麻煩;
(2)在web.xml總配置filter,filter自己寫,
web.xml中:
<filter> <filter-name>EncodingFilter</filter-name> <filter-class>xx.xx.xx.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>filter相關類:
//EncodingFilter類: import java.io.IOException;import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest;public class EncodingFilter implements Filter {private String charset = "UTF-8";@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;if(req.getMethod().equalsIgnoreCase("GET")) {if(!(req instanceof GetRequest)) {req = new GetRequest(req, charset);//處理get請求編碼}} else {req.setCharacterEncoding(charset);//處理post請求編碼}chain.doFilter(req, response);}@Overridepublic void init(FilterConfig fConfig) throws ServletException {String charset = fConfig.getInitParameter("charset");if(charset != null && !charset.isEmpty()) {this.charset = charset;}} }//GetRequest類:import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper;/*** 對GET請求參數加以處理!* @author qdmmy6**/ public class GetRequest extends HttpServletRequestWrapper {private HttpServletRequest request;private String charset;public GetRequest(HttpServletRequest request, String charset) {super(request);this.request = request;this.charset = charset;}@Overridepublic String getParameter(String name) {// 獲取參數String value = request.getParameter(name);if(value == null) return null;//如果為null,直接返回nulltry {// 對參數進行編碼處理后返回return new String(value.getBytes("ISO-8859-1"), charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}@SuppressWarnings({ "unchecked", "rawtypes" })@Overridepublic Map getParameterMap() {Map<String,String[]> map = request.getParameterMap();if(map == null) return map;// 遍歷map,對每個值進行編碼處理for(String key : map.keySet()) {String[] values = map.get(key);for(int i = 0; i < values.length; i++) {try {values[i] = new String(values[i].getBytes("ISO-8859-1"), charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}}// 處理后返回return map;}@Overridepublic String[] getParameterValues(String name) {String[] values = super.getParameterValues(name);for(int i = 0; i < values.length; i++) {try {values[i] = new String(values[i].getBytes("ISO-8859-1"), charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}return values;} } (3)改變tomcat的編碼在conf/server.xml中,將
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />改為
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="UTF-8"/>其四,url編碼
這里需要注意的問題是,
通過頁面傳輸數據給服務器時,如果包含了一些特殊字符是無法發送的。這時就需要先把要發送的數據轉換成URL編碼格式,再發送給服務器。
其實需要我們自己動手給數據轉換成URL編碼的只有GET超鏈接,因為表單發送數據會默認使用URL編碼,也就是說,不用我們自己來編碼。
因為URL默認只支持ISO-8859-1,這說明在URL中出現中文和一些特殊字符可能無法發送到服務器。所以我們需要對包含中文或特殊字符的URL進行URL編碼。
服務器會自動識別數據是否使用了URL編碼,如果使用了服務器會自動把數據解碼,無需我們自己動手解碼。
還是那句話吧,編碼這個問題是挺復雜的,很多地方都容易出錯,做個項目不能保證一開始就都對,但出錯之后要能及時改正,一條線中,看看2端的編碼是否一致,或者起點和終點的編碼是否對應,一一排查,很容易就能找到問題所在~
也要多在網上看看解決辦法,有可能一下就懂了~
轉載于:https://www.cnblogs.com/Arry10/p/7731801.html
總結
以上是生活随笔為你收集整理的javaweb项目中遇到的一些乱码问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 把CentOS启动进度条替换为详细信息
- 下一篇: electron 使用中的注意事项