encodeURI来解决URL传递时为什么需要进行两次encodeURI编码
文章来源于https://blog.csdn.net/u012027337/article/details/52126475,转载请注明出处
说明: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解码,编码和解码的过程是对称的,所以不会出现乱码。