在URL中传递中文的解决方式
1.第一种方式,主要是通过配置搞定
1.1)在服务器端设置
(1)在tomcat的配置文件中指定编码
server.xml文件中指定:URIEncoding=”UTF-8”
<Connector connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"
useBodyEncodingForURI="true" URIEncoding="UTF-8"/>
URIEncoding告诉服务器servlet解码URL时采用的编码;
useBodyEncodingForURI 告诉服务器解码URL时候需要采用request body指定的编码
(2)在weblogic服务器的配置文件中指定编码
weblogic.xml 文件中指定UTF-8
<input-charset>
<java-charset-name>UTF-8</java-charset-name>
</input-charset>
1.2)在浏览器端设置
在页面设置文件的编码和保存格式UTF-8
在页面头设置:pageEncoding=”UTF-8” contentType=”text/html; charset=UTF-8”
在HtmL中的meta设置:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
这样设置后,满足在主流浏览器:chrome、firefox等浏览器URL中带有中文的请求自动转码问题,
不需要额外在后台代码里进行手动转码。
但是,对独树一帜的IE大浏览器仍旧不起效果,会出现令人头疼的乱码问题。解决方案看第3步了
1.3)在前端用js对URL进行编码后再发送请求(仅仅只是为了兼容IE)
var srcUrl = _contextEbtPath + “/dic/index?condition=我是中文查询条件撒”;
var encodeUrl = encodeURI(srcUrl);
这样编码一次后,也不会影响其他主流浏览器的编码转换问题,得到彻底解决。
2.第二种也是最直接的方式,用硬编码解决
直接在后台请求处理前,手动进行一次转码。
缺点是凡是有中文请求URL的都需要硬编码一次,优点是直接明了。
condition = new String(condition.getBytes("iso8859-1"),"utf-8");
3.相关知识延伸阅读
3.1)在URL中中文字符通常出现在以下两个地方:
http://localhost:8080/example/中 国 name=中国
(1)Query String中的参数值,比如 keywords=中国
(2)servlet path,比如: /中 国
3.2)出现乱码问题的原因主要是以下几方面:
(1)浏览器:我们的客户端(浏览器)本身并没有遵循URI编码的规范。
(2)Servlet服务器:Servlet服务器的没有正确配置。
3.3)相关知识:http请求的几个环节
浏览器(ie firefox)—————–>Servlet服务器 ——————–>浏览器显示
<编码> < 解码成unicode,然后将显示的内容编码> <解码>
(1)浏览器把URL(以及post提交的内容)经过编码后发送给服务器。
(2)这里的Servlet服务器实际上指的是由Servlet服务器提供的servlet实现ServletRequestWrapper,
不同应用服务器的 servlet实现不同,这些servlet的实现把这些内容解码转换为unicode,
处理完毕后,然后再把结果(即网页)编码返回给浏览器。
(3)浏览器按照指定的编码显示该网页。
注意:
当对字符串进行编码和解码的时候都涉及到字符集,通常使用的字符集为ISO8859-1、GBK、UTF-8、UNICODE。
3.4)相关知识:URL的组成及说明
域名:端口/contextPath/servletPath/pathInfo queryString
(1)contextPath是在Servlet服务器的配置文件中指定的
(a)对于weblogic:contextPath是在应用 的weblogic.xml中配置。
<context-root>/</context-root>
(b)对于tomcat:contextPath是在server.xml中配置。
<Context path="/" docBase="D:/server/blog.war" debug="5" reloadable="true" crossContext="true"/>
(c)对于jboos: contextPath是在应用的jboss-web.xml中配置
<jboss-web>
<context-root>/</context-root>
</jboss-web>
(2)servletPath是在应用的web.xml中配置
<servlet-mapping>
<servlet-name>Example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>
3.5)相关知识:Servlet获取URL的值及参数 API
(1)获得 queryString的参数值(来自于GET和POST),其值经过Servlet服务器URL Decode 过的
request.getParameter(“name”);
(2)获取 pathinfo 信息,返回的字符串是经过Servlet服务器URL Decode过的
request.getPathInfo();
(3)获取 requestURI 浏览器提交过来的原始数据,未被Servlet服务器URL Decode过。
requestURI = request.getRequestURI();
3.6)相关知识:servlet规范(开发人员必须清楚的servlet规范:)
(1) HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的request body的编码而不是设置get方法提交的queryString的编码。
该方法告诉应用服务器应该采用什么编码解析post传过来的内容。很多文章并没有说明这一点。
(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。
(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。
(4) POST提交的数据是作为request body的一部分。
(5) 网页的Http头中ContentType(“text/html; charset=GBK”)的作用:
(a) 告诉浏览器网页中数据是什么编码;
(b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。
这里需要注意的是:这里所说的ContentType是指http头的ContentType,而不是在网页中meta中的ContentType。
3.7)浏览器和服务器对编码的解析
URL:http://localhost:8080/example/中 国 name=中国
汉字 编码 二进制表示
中国 UTF-8 0xe4 0xb8 0xad 0xe5 0x9b 0xbd[-28, -72, -83, -27, -101, -67]
中国 GBK 0xd6 0xd0 0xb9 0xfa[-42, -48, -71, -6]
中国 ISO8859-1 0x3f,0x3f[63, 63]信息失去
3.7.1)浏览器发送请求时的编码
<1>GET方式提交,浏览器会对URL进行URL encode,然后发送给服务器。
(a)对于中文IE,如果在高级选项中选中总以UTF-8发送(默认方式),则PathInfo是URL Encode是按照UTF-8编码,QueryString是按照GBK编码。
http://localhost:8080/example/中 国 name=中国
实际上提交是:GET /example/%E4%B8%AD%E5%9B%BD name=%D6%D0%B9%FA
(b)对于中文IE,如果在高级选项中取消总以UTF-8发送,则PathInfo和QueryString是URL encode按照GBK编码。
实际上提交是:GET /example/%D6%D0%B9%FA name=%D6%D0%B9%FA
(c)对于中文firefox,则pathInfo和queryString都是URL encode按照GBK编码。
实际上提交是:GET /example/%D6%D0%B9%FA name=%D6%D0%B9%FA
很显然,不同的浏览器以及同一浏览器的不同设置,会影响最终URL中PathInfo的编码。
对于中文的IE和FIREFOX都是采用GBK编码 QueryString。
小结,解决方案:
(a)**URL中如果含有中文等非ASCII字符,则浏览器会对它们进行URLEncode。为了避免浏览器采用了我们不希望的编码,
所以最好不要在URL中直接使用非ASCII字符,而采用URL Encode编码过的字符串%.**
比如:URL:http://localhost:8080 /example/中国 name=中国
建议:URL:http://localhost:8080/example/%D6%D0 %B9%FA name=%D6%D0%B9%FA
(b)我们建议URL中PathInfo和QueryString采用相同的编码,这样对服务器端处理的时候会更加简单。
<2>POST方式提交
对于POST方式,表单中的参数值对是通过request body发送给服务器,**此时浏览器会根据网页的ContentType(“text/html; charset=GBK”)
中指定的编码进行对表单中的数据进行编码**,然后发给服务器。
在服务器端的程序中我们可以通过 Request.setCharacterEncoding() 设置编码,然后通过request.getParameter获得正确的数据。
解决方案:
从最简单,所需代价最小来看,我们对URL以及网页中的编码使用统一的编码对我们来说是比较合适的。
如果不使用统一编码的话,我们就需要在程序中做一些编码转换的事情。这也是我们为什么看到有网络上大量的资料介绍如何对乱码进行处理,
其中很多解决方案都只是一时的权宜之计,没有从根本上解决问题。
3.7.2)Servlet服务器
Servlet服务器实现的Servlet遇到URL和POST提交的数据中含有%的字符串,它会按照指定的字符集解码。
下面两个Servlet方法返回 的结果都是经过解码的:
request.getParameter(“name”);
request.getPathInfo();
这里所说的”指定的字符集”是在应用服务器的配置文件中配置。
(1) tomcat服务器
对于tomcat服务器,该文件是server.xml
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="150" connectionTimeout="20000"
redirectPort="8443" URIEncoding="GBK"/>
URIEncoding告诉服务器servlet解码URL时采用的编码。
<Connector port="8080" ... useBodyEncodingForURI="true" />
useBodyEncodingForURI 告诉服务器解码URL时候需要采用request body指定的编码。
(2) weblogic服务器
对于weblogic服务器,该文件是weblogic.xml
<input-charset>
<java-charset-name>GBK</java-charset-name>
</input-charset>
3.7.3)浏览器显示
浏览器根据http头中的ContentType(“text/html; charset=GBK”),指定的字符集来解码服务器发送过来的字节流。
我们可以调用 HttpServletResponse.setContentType()设置http头的ContentType。
总结:
(1)URL中的PathInfo和QueryString字符串的编码和解码是由浏览器和应用服务器的配置决定的,
我们的程序不能设置,不要期望用request.setCharacterEncoding()方法能设置URL中参数值解码时的字符集。
所以我们建议URL中不要使用中文等非ASCII字符,如果含有非ASCII字符的话要使用URLEncode编码一下,比如:
http://localhost:8080 /example1/example/中国
正确的写法:
http://localhost:8080/example1/example/%E4%B8%AD%E5%9B%BD
并且我们建议URL中不要在PathInfo和QueryString同时使用非ASCII字符,比如
http://localhost:8080 /example1/example/中国 name=中国
原因很简单:不同浏览器对URL中PathInfo和QueryString编码时采 用的字符集不同,但应用服务器对URL通常会
采用相同的字符集来解码。
(2)我们建议URL中的URL Encode编码的字符集和网页的contentType的字符集采用相同的字符集,这样程序的实现就很简单,
不用做复杂的编码转换。 JS中对中文(UTF-8格式保存的)进行编码(unicode编码)的函数常用有:encodeURI(str); encodeURIComponent(str);