request.setCharacterEncoding 關於編碼 概述

來源:互聯網
上載者:User

request.setCharacterEncoding 關於編碼

 

概述
從Servlet2.3開始,支援用戶端內容協商。服務端內容協商,很早就有,服務端在返回的資料中通過Content-Type來指定返回的資料內容。在REST叫囂的背景下,用戶端也需要協商:例如通過PUT方法提交一段XML或JSON資料來更新服務端的一個對象。用戶端可通過URL尾碼名.xml或.json的方式來告訴服務端提交的資料類型;也可通過HTTP頭的Content-Type來告之服務端提交的資料類型。

 

關於該問題的Blog

【1】給出了兩個辦法

http://forum.springsource.org/showthread.php?t=14063

Hi,
I am woking on a site that receives input in CJK .
This may be a naive  question:
I am using org.springframework.web.servlet.DispatcherServlet as my servlet and I need to set CharacterEnconding on the HttpServletRequest.
I looked into the source code and I relaized there is no code that calls setCharacterEncoding

I dig into the forum and found 2 solutions:

1. Use the CharacterEncodingFilter

2. Override DispatcherServlet.doService  as:
public class MyServlet extends DispatcherServlet {
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

request.setCharacterEncoding( "UTF-8" );
super.doService( request , response ) ;
}
}

I tried to do #1 for it seems to be more desirable (cleaner) solution.
in web.xml I added:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFi lter</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>

But it doesn't seem to work.
Could someone tell me how to do that? Use CharacterEncodingFilter?
Thanks in advance.

 

【2】注意事項

http://www.junlu.com/msg/125726.html

With the 2.3 servet API, there is a new method:
 request.setCharacterEncoding(String encoding)
通過Content-Type告訴服務端當前請求編碼:
This lets you tell the server a request's character encoding.
(例如HTTP頭: Content-Type:    text/html; charset=UTF-8
Content-Type:application/x-www-form-urlencoded; charset=UTF-8)

It is critical that  setCharacterEncoding is called BEFORE any
request.getParameter is called (or getReader). Otherwise, you are at the
mercy of the appserver for what you get back on the getParameter call.

For example, if setCharacterEncoding is not called, you could get a null
value back on getParameter("foo").

 

 

解決該問題:用戶端協商編碼方式

用戶端協商http請求編碼方式代碼  
  1. private String negotiateCharacterEncoding(HttpServletRequest request,Map<String,String> outParam) {  
  2.         String clientEncoding = request.getCharacterEncoding();//HTTP標準:用戶端聲稱的編碼(但是目前大多數瀏覽器並未實施該標準)  
  3.         outParam.put("point","HTTP標準");  
  4.         //協商過程:  
  5.         //1. 通過HTTP標準指定用戶端編碼;(在HTTP頭中設定:Content-Type    =[text/html; charset=UTF-8])  
  6.         //2. 通過自訂HTTP頭(Client-Charset)指定用戶端編碼;  
  7.         //3. 通過自訂HTTP查詢參數(Client-Charset)指定用戶端編碼(只針對HTTP-GET方法)。(以免動態script標籤發起請求時設定不了HTTP頭;編碼數值都是英文字元,提取編碼數值跟編碼無關。)  
  8.         //4. 如果所有的協商都沒有,那麼服務端強制使用配置:defaultEncoding  
  9.         //5. 如果服務端沒有配置defaultEncoding,那麼使用容器預設的ISO-8...(如果上述指定的編碼不被支援,那麼依然使用容器預設的)  
  10.         if(clientEncoding==null || clientEncoding.trim().equals("")) {  
  11.             clientEncoding = request.getHeader("Client-Charset");  
  12.             outParam.put("point","自訂HTTP頭");  
  13.             if(clientEncoding==null || clientEncoding.trim().equals("")) {  
  14. //              clientEncoding = request.getParameter("Client-Charset");//不能通過該方式提取Client-Charset參數  
  15. //request.setCharacterEncoding(encoding);發揮作用的前提是:調用setCharacterEncoding之前不能執行任何request.getParameter  
  16.                 if("GET".equalsIgnoreCase(request.getMethod())) {  
  17.                     String queryString = request.getQueryString();  
  18.                     if(queryString!=null && !queryString.equals("")) {  
  19.                         //定位參數[Client-Charset]的起始和終止位置  
  20.                         int startIndex = queryString.indexOf("Client-Charset=");  
  21.                         int endIndex = -1;  
  22.                         if(startIndex!=-1) {  
  23.                             startIndex = startIndex+"Client-Charset=".length();  
  24.                             endIndex = queryString.indexOf("&", startIndex);  
  25.                             if(endIndex==-1) {//Client-Charset是最後一個參數  
  26.                                 int sessionidIndex = queryString.indexOf(";", startIndex);//去掉基於URL的SessionID  
  27.                                 if(sessionidIndex!=-1) {  
  28.                                     endIndex = sessionidIndex;  
  29.                                 } else {  
  30.                                     endIndex = queryString.length();  
  31.                                 }  
  32.                             }  
  33.                         }  
  34.                         if(startIndex<endIndex) {  
  35.                             clientEncoding = queryString.substring(startIndex, endIndex);  
  36.                             outParam.put("point","自訂HTTP查詢參數");  
  37.                         }  
  38.                     }  
  39.                 }  
  40.             }  
  41.             if(clientEncoding==null || clientEncoding.trim().equals("")) {  
  42.                 clientEncoding = defaultEncoding;  
  43.                 outParam.put("point","服務端配置");  
  44.             }  
  45.               
  46.         }  
  47.         return clientEncoding;  
  48.     }  

 

設定編碼方式代碼  
  1. if (encoding != null) {  
  2.             try {  
  3.                 request.setCharacterEncoding(encoding);//註:被強制認為是GBK編碼,好處在於用戶端在提交GET請求時不再需要做URLEncode處理了。不好的是,如果用戶端提交以UTF-8的編碼,則編碼出錯了。  
  4.                 //http://www.junlu.com/msg/125726.html  
  5.             } catch (Exception e) {  
  6.                 log.error("Error setting character encoding to '" + encoding  
  7.                         + "' - ignoring.", e);  
  8.             }  
  9.         }  

 

測試案例

/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678
/modifyListener_test.htm?nick=%B7%B1%F3%77%EA%C7%B7%51%D0%6E%ED%94&mobile=13812345678&Client-Charset=GBK
/modifyListener_test.htm?nick=%E7%B9%81%E9%AB%94%E6%98%B5%E7%A8%B1%E8%A1%9D%E9%A0%82&mobile=13812345678&Client-Charset=UTF-8

/modifyListener_test.htm?nick=濤&mobile=13812345678
/modifyListener_test.htm?nick=%CC%CE&mobile=13812345678&Client-Charset=GBK
/modifyListener_test.htm?nick=%CC%CE&mobile=13812345678
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678  //出錯:輸入是UTF-8,卻被伺服器強製為GBK (###nick=娑?,mobile=13812345678)
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8;12345
/modifyListener_test.htm?Client-Charset=UTF-8&nick=%E6%B6%9B&mobile=13812345678;12345 //nick=濤,mobile=13812345678;12345

/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678
並設定包頭:
Content-Type:    text/html; charset=UTF-8

Content-Type:    charset=UTF-8
//協商或配置的編碼:UTF-8,協商源:HTTP標準

 

問題回覆:

Passport有一個全域的Filter,強制所有的HTTP請求的編碼為GBK,所以支援不了URLEncode(UTF-8)。我想了這麼些辦法,都不行:
1、    把這個全域的Filter去掉,不強製為GBK,現有線上的那些沒有編碼的東西支援不了。
這樣設定,對於那些沒有編碼的資料,比如:http://localhost/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678 提取的nick則會出錯。因此會影響線上其他地方。

2、    手動從GBK再轉UTF-8,部分資料能支援,有些不支援。(GBK和UTF-8字元集畢竟不是包含與被包含的關係,其中有衝突的部分)
New String(nick.getBytes(“GBK”),”UTF-8”)  對於http://localhost/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678能轉換出“繁體昵稱衝頂”;但對於

http://localhost/modifyListener_test.htm?nick=濤&mobile=13812345678  其中“波濤”的“濤”則轉換失敗。

現在一個可行的解決辦法是通過HTTP頭協商,需要麻煩你那邊在請求中加一個參數:
1、    在HTTP頭部增加參數:Content-Type,並設定數值:charset=UTF-8   (備忘:在HTTP頭裡設定Client-Charset參數,數值為UTF-8也行。但前提是Content-Type沒被設定為其他)
這樣設定後,nick就可以支援URLEncode(UTF-8)了。

2、    對於動態script標籤的請求,由於無法設定HTTP頭,後台支援查詢參數:Client-Charset
比如:這樣提交HTTP請求:  nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.