先来看看三个url:
url1. http://hi.baidu.com/爱宝的妍
url2. http://hi.baidu.com/%E7%88%B1%E5%AE%9D%E7%9A%84%E5%A6%8D (UTF-8 编码)
url3. http://hi.baidu.com/%B0%AE%B1%A6%B5%C4%E5%FB (GBK 编码)
这三个url指向同一个网页,而且都能够访问。其实,如果你的浏览器是中文环境下的,IE设置“以UTF8发送URL”,那么在IE里输入 url1,服务器端得到的是url2;在firefox里输入url1,服务器端得到的是url3。这是为什么呢?听下文分解(分析部分内容转自 http://blog.csdn.net/yzhz/archive/2007/07/03/1676796.aspx)。
一、问题:
编码问题是JAVA初学者在web开发过程中经常会遇到问题,网上也有大量相关的文章介绍,但其中很多文章并没有对URL中使用 了中文等非ASCII的字符造成服务器后台程序解析出现乱码的问题作出准确的解释和说明。本文将详细介绍由于在URL中使用了中文等非ASCII的字符造 成乱码的问题。
1、在URL中中文字符通常出现在以下两个地方:
(1)、Query String中的参数值,比如http://search.china.alibaba.com/search /offer_search.htm?keywords=中国
(2)、servlet path,比如:http://search.china.alibaba.com/selloffer/中国.html
2、出现乱码问题的原因主要是以下几方面:
(1)、浏览器:我们的客户端(浏览器)本身并没有遵循URI编码的规范 (http://www.w3.org/International/O-URL-code.html)。
(2)、Servlet服务 器:Servlet服务器的没有正确配置。
(3)、开发人员并不了解Servlet的规范和API的含义。
二、基础知识:
1、一个http请求经过的几个环节:
浏览器(ie firefox)【get/post】------------>Servlet服务器 ------------------------------->浏览器显示
编码 解码成unicode,然后将显示的内容编码 解码
(1) 浏览器把URL(以及post提交的内容)经过编码后发送给服务器。
(2) 这里的Servlet服务器实际上指的是由Servlet服务器提供的servlet实现ServletRequestWrapper,不同应用服务器的 servlet实现不同,这些servlet的实现把这些内容解码转换为unicode,处理完毕后,然后再把结果(即网页)编码返回给浏览器。
(3) 浏览器按照指定的编码显示该网页。
当对字符串进行编码和解码的时候都涉及到字符集,通常使用的字符集为ISO8859-1、GBK、UTF-8、UNICODE。
2、URL的组成:
域名:端口/contextPath/servletPath/pathInfo?queryString
说 明:
1、ContextPath是在Servlet服务器的配置文件中指定的。
对于weblogic:
contextPath是在应用 的weblogic.xml中配置。
<context-root>/</context-root>
对 于tomcat:
contextPath是在server.xml中配置。
<Context path="/" docBase="D:/server/blog.war" debug="5" reloadable="true" crossContext="true"/>
对于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>
2、Servlet API
我们使用以下servlet API获得URL的值及参数。
request.getParameter("name"); // 获得queryString的参数值(来自于get和post),其值经过Servlet服务器URL Decode过的
request.getPathInfo(); // 注意:pathinfo返回的字符串是经过Servlet服务器URL Decode过的。
requestURI = request.getRequestURI(); // 内容为:contextPath/servletPath/pathinfo 浏览器提交过来的原始数据,未被Servlet服务器URL Decode过。
3、开发人员必须清楚的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。
三、下面我们分别从浏览器和应用服务器来举例说明:
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]信息失去
(一)、浏览器
1、GET方式提交,浏览器会对URL进行URL encode,然后发送给服务器。
(1) 对于中文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
(1) 对于中文IE,如果在高级选项中取消总以UTF-8发送,则PathInfo和QueryString是URL encode按照GBK编码。
实际上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA
(3) 对于中文firefox,则pathInfo和queryString都是URL encode按照GBK编码。
实际上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA
很显然,不同的浏览器以及同一浏览器的不同设置,会影响最终URL中PathInfo的编码。对于中文的IE和FIREFOX都是采用GBK编码 QueryString。
小结:解决方案:
1、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
2、我们建议URL中PathInfo和QueryString采用相同的编码,这样对服务器端处理的时候会更加简单。
2、还有一个问题,我发现很多程序员并不明白URL Encode是需要指定字符集的。不明白的人可以看看这篇文档:http://gceclub.sun.com.cn/Java_Docs/html /zh_CN/api/java/net/URLEncoder.html
2、 POST提交
对于POST方式,表单中的参数值对是通过request body发送给服务器,此时浏览器会根据网页的ContentType("text/html; charset=GBK")中指定的编码进行对表单中的数据进行编码,然后发给服务器。
在服务器端的程序中我们可以通过 Request.setCharacterEncoding() 设置编码,然后通过request.getParameter获得正确的数据。
解决方案:
1、从最简单,所需代价最小来看,我们对URL以及网页中的编码使用统一的编码对我们来说是比较合适的。
如果不使用统一 编码的话,我们就需要在程序中做一些编码转换的事情。这也是我们为什么看到有网络上大量的资料介绍如何对乱码进行处理,其中很多解决方案都只是一时的权宜 之计,没有从根本上解决问题。
(二)、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>
(三)浏览器显示
浏览器根据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的字符集采用相同的字符集,这样程序的实现就很简单,不用做复杂的编码转换。
到这里大家该明白url编码的原理了吧。再回过头来看看本文一开始给出的三个url。http://hi.baidu.com/爱宝的妍 属于PathInfo,所以根据IE以及Firefox默认设置,ie用utf8 encode了该url,而firefox用gbk encode的,随之服务器端得到了url2和url3不同的url。
分享到:
相关推荐
2. **跨平台兼容性**:不同的系统和浏览器可能使用不同的编码方式,统一使用URL编码可以提高兼容性。 3. **安全性**:防止注入攻击,确保数据安全传输。 4. **标准化**:遵循国际标准,使得数据可以在全球范围内被...
1. **提高兼容性**:通过URL编码,可以确保不同的系统和设备都能正确解析URL中的特殊字符。 2. **避免误解**:不同的浏览器或服务器可能会默认使用不同的字符集来处理非ASCII字符,这可能导致解析错误。通过编码,...
- **Internet Explorer (IE)**:使用UTF-8编码并通过URL编码方式处理。 - **Safari/Chrome**:使用UTF-8编码,并通过MIME Utility进行Base64编码处理。 - **Opera**:与Safari类似,使用UTF-8编码,并通过特定...
4. **兼容性考虑**:易语言URL编码转换模块可能还考虑了不同浏览器和服务器之间的兼容性问题,确保编码和解码结果符合各种标准,如RFC 3986。 5. **性能优化**:对于处理大量URL编码和解码的场景,模块可能会有性能...
并且这个格式居然不能再这个函数里面设置,导致这个结果不可控制,在不同浏览器环境下面结果不同,不能得到自己想要的格式编码。在搜索引擎里面找了很长时间,都没有找到解决这个问题的办法,没办法,只能自己手动...
URL编码,全称为统一资源定位符(Uniform Resource Locator)编码,是互联网上数据通信的一种标准格式,用于确保数据能在不同的系统之间安全传输。在HTTP协议中,URL编码扮演着至关重要的角色,因为某些字符在URL中...
5. **浏览器兼容性**:不同的浏览器对URL编码和解码的处理可能存在差异,因此在处理中文参数时,需要确保代码兼容主流浏览器,例如Chrome、Firefox、Safari和IE等。 6. **最佳实践**:为了避免编码问题,一种好的...
渝海URL编码转换工具 v1.1版提供了一个用户友好的界面,帮助用户快速、便捷地对URL进行编码或解码。 该工具可能包括以下功能: 1. **编码功能**:用户可以输入包含特殊字符的URL,工具会自动将这些字符转换为对应...
通过对HTML5关键特性的兼容性分析,我们可以看到,虽然HTML5为Web开发带来了许多便利,但在实际应用过程中仍需注意不同浏览器之间的差异。开发人员在选择使用HTML5特性时应充分考虑目标用户的浏览器环境,以确保最佳...
关于URL编码和解码的知识点: 1. **URL编码**:URL编码是使用百分号(%)加上字符的ASCII值来表示非ASCII字符或URL中不安全的字符。例如,空格通常被编码为`%20`。 2. **PHP内置函数**:PHP提供了`urlencode()`和`...
综上所述,"浏览器X的系统分析实例"涵盖了软件工程的多个核心领域,对于学习和理解浏览器开发流程、系统设计原则以及实际编码实践具有很高的价值。通过这份文档,我们可以深入到浏览器的内部工作机制,从而提升我们...
在不同的上下文中,URL编码有不同的规则和实现差异: 1. **网址路径中包含汉字**: 浏览器如IE和Firefox会将非ASCII字符(如汉字)以UTF-8编码的形式插入URL。例如,汉字“春节”的UTF-8编码是`E6 98 A5 E8 8A 82`...
对于这种情况,规范建议用户端采取一定的处理措施,如使用URL编码等方式将非ASCII字符转换为可被正确解析的形式。例如,上述链接可以被正确编码为: ```html <a href="http://foo.org/H%C3%A5kon"></a> ``` 通过...
8. **兼容性考虑**:考虑到不同的系统和浏览器可能对URL编码有不同的处理方式,源码可能考虑了跨平台的兼容性问题。 通过分析这个源码,初学者可以深入理解URL编码的原理,掌握易语言的编程技巧,同时也能了解到...
在PB10.5中,你可以通过OLE自动化对象来调用外部应用程序或服务,例如,你可以调用Internet Explorer (IE) 的浏览器功能来打开一个特定的URL。这个过程通常涉及到以下步骤: 1. **创建OLE对象**:首先,在PB中创建...
不同的浏览器对URL长度的限制是不一样的。例如,Chrome和Firefox的限制通常更为宽松,它们可以处理超过20000个字符的URL。然而,这并不意味着你应该总是尝试接近或达到这些限制,因为有些服务器和代理服务器可能有...
在ASP.NET 2.0与C#环境下,获取客户端浏览器信息、IP地址、访问URL以及操作系统类型是常见的需求,尤其在日志记录、数据分析或安全验证等场景中尤为重要。以下是对给定代码片段中涉及的关键知识点进行的详细解析: ...
浏览器的系统安全分析主要关注的是浏览器在运行过程中可能存在的安全风险和漏洞,这些风险往往源自于浏览器的特权域、API滥用、XSS攻击以及文件下载和执行等方面。以下是对这些内容的详细解释: 1. 特权域:特权域...