1. 程式人生 > >encodeURI來解決URL傳遞時為什麼需要進行兩次encodeURI編碼

encodeURI來解決URL傳遞時為什麼需要進行兩次encodeURI編碼

說明:1 .encodeURL函式主要是來對URI來做轉碼,它預設是採用的UTF-8的編碼.
        2. UTF-8編碼的格式:一個漢字來三個位元組構成,每一個位元組會轉換成16進位制的編碼,同時新增上%號.

 下面先看一段前端程式碼:

 /**
  *初始化datagrid
  */
  function initDatagrid(id,typevalue,organame){
	 
  	var url="${base}/organization/queryOrganizationList.action?id="+id+"&typevalue="+typevalue+"&organame="+organame+""	; 
  	url=encodeURI(encodeURI(url));
  	$("#dataGridObject").datagrid({
  		title:'', //標題
  		method:'post',
  		border:false,
  		singleSelect:false, //多選
  		fitColumns: true, //自動調整各列,用了這個屬性,下面各列的寬度值就只是一個比例。
  		striped: true, //奇偶行顏色不同
  		collapsible:true,//可摺疊 
  		url:url, //資料來源
  		queryParams:params, //查詢條件
  		pageSize:20,})
看見這段程式碼的同學可能會有疑問為什麼url要進行兩次編碼enCodeURL(enCodeURI(url)),先不做解答,我們再來看看後臺程式碼
@SuppressWarnings("rawtypes")
	@RequestMapping(value = "organization/queryOrganizationList")
	@ResponseBody
	public Map<String, Object> queryOrganizationList(HttpServletRequest request, PageRequest pageRequest,QueryOrganizationParamsVO paramsVO, 
			int page, int rows,String id,String typevalue,String organame) throws UnsupportedEncodingException {
		Map<String, Object> map = new HashMap<String, Object>();
		pageRequest.setPageSize(rows);
		pageRequest.setPageNo(page);
		AuthInfo  logininfo=SessionUtil.getLoginUsers(request).get(0);
		String orgid=logininfo.getOrganId();
		//注意:使用java.net.URLDecoder.decode()函式解碼,獲取機構名稱的中文
		organame=java.net.URLDecoder.decode(organame , "UTF-8");
		try {
			Page pages = this.organizationService.queryOrganizationList(pageRequest, paramsVO,id,typevalue,orgid,organame);
			map.put("total", pages.getTotalCount());
			map.put("rows", pages.getRows());
		} catch (Exception e) {
			System.out.println(e.getMessage());
			map.put("total", 0);
			map.put("rows", 0);
		}
		return map;
	}
	

後臺使用了java.net.URLDecoder.decode(organame , "UTF-8")函式來對從url傳過來的機構名稱進行解碼,獲取機構名稱的中文字串,為什麼在後臺要進對url進行兩次編碼,我們在後臺訪問機構名稱的時候才不會出現亂碼,下面給大家看一下我查資料獲取的關於這裡要做兩次encodeURI的原因以及說明,個人感覺還是講的還是比較清晰的,希望能幫助大家理解。
這裡要做兩次encodeURI的原因以及說明::

具體說明其中具體的原理分析如下,假設頁面端傳入的機構名稱(organame)中文是:"中”,按照下面步驟進行解碼
1.第一次encodeURI,按照utf-8方式獲取位元組陣列變成[-28,-72-83],對位元組碼陣列進行遍歷,把每個位元組轉化成對應的16進位制數,這樣就變成了[E4,B8,AD],最後變成[%E4,%B8,%AD]

2.第二次encodeURI,把陣列最後變成[%25E4,%25B8,%25AD]然後就把處理後的資料[%25E4,%25B8,%25AD]發往伺服器端,

當應用伺服器呼叫getParameter方法,getParameter方法會去向應用伺服器請求引數,應用伺服器最初獲得的就是傳送來的[%25E4,%25B8,%25AD],

應用伺服器會對這個資料進行URLdecode操作,URldecode操作和encodeURL操作是相反的操作,處理結果就是[%E4,%B8,%AD],並把這個值返回給getParameter方法,然後再在伺服器端中呼叫相應的URL轉碼方法或者是函式  就可以把資料還原成最初頁面傳送過來的中文“中”了。

URL編碼與兩次encodeURI

當使用位址列提交查詢引數時,如果不編碼,非英文字元會按照作業系統的字符集進行編碼提交到伺服器,伺服器會按照配置的字符集進行解碼,所以如果兩者不一致就會導致亂碼。

encodeURI函式採用UTF-8對URL進行編碼,所以如果伺服器在進行解碼時使用的是其他的編碼方式就會出現亂碼,預設的伺服器配置的解碼字符集都不是UTF-8,所以大部分情況下位址列提交中文查詢引數時會產生亂碼;針對這種情況,可以連續使用兩次encodeURI在客戶端(主要指瀏覽器)對非英文字元進行編碼,然後在服務端使用java.net.URLDecoder(String."UTF-8")解碼,即可得到正確的中文。

如果只進行一次encodeURI,得到的是UTF-8形式的URL,伺服器端通過request.getParameter()解碼查詢引數(通常是iso-8859-1)就會得到亂碼。

如果進行兩次encodeURI,第一次編碼得到的是UTF-8形式的URL,第二次編碼得到的依然是UTF-8形式的URL,但是在效果上相當於首先進行了一次UTF-8編碼(此時已經全部轉換為ASCII字元),再進行了一次iso-8859-1編碼,因為對英文字元來說UTF-8編碼和ISO-8859-1編碼的效果相同。在伺服器端,首先通過request.getParameter()自動進行第一次解碼(可能是gb2312,gbk,utf-8,iso-8859-1等字符集,對結果無影響)得到ascii字元,然後再使用UTF-8進行第二次解碼,通常使用java.net.URLDecoder("","UTF-8")方法。

兩次編碼兩次解碼的過程為:

UTF-8編碼->UTF-8(iso-8859-1)編碼->iso-8859-1解碼->UTF-8解碼,編碼和解碼的過程是對稱的,所以不會出現亂碼。

encodeURL函式主要是來對URI來做轉碼,它預設是採用的UTF-8的編碼.
. UTF-8編碼的格式:一個漢字來三個位元組構成,每一個位元組會轉換成16進位制的編碼,同時新增上%號.



總結:

    1、前端進行兩次編碼(使用utf-8的編碼格式)

    2、後臺伺服器自動會解碼一次,但是不是按照utf-8的格式解碼

   3、兩次編碼兩次解碼的過程為:
        UTF-8編碼->UTF-8(iso-8859-1)編碼->iso-8859-1解碼->UTF-8解碼,編碼和解碼的過程是對稱的,所以不會出現亂碼。