http请求编码问题

总结html

1.经过浏览器向服务器发送请求,浏览器会根据自带的默认编码格式自动对URL进行编码。(注意是URL不包含 request boby部分);java

2.服务器接收请求,会按照tomcat中设置的编码格式自动对URL进行解码。因此当浏览器与服务器的编码格式设置不相同,则URL中有中文的部分就会出现乱码。程序员

post请求中,request body中的内容的编码格由 request.setCharacterEncoding()决定web

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////api

浏览器URL编码浏览器

转:http://www.cnblogs.com/haitao-fan/p/3399018.htmltomcat

转:http://blog.csdn.net/yzhz/article/details/1676796服务器

深刻浅出URL编码网络

1、问题:
        编码问题是Java初学者在web开发过程当中常常会遇到问题,网上也有大量相关的文章介绍,但其中不少文章并无对URL中使用了中文等非ASCII的字符形成服务器后台程序解析出现乱码的问题做出准确的解释和说明。本文将详细介绍因为在URL中使用了中文等非ASCII的字符形成乱码的问题。app

一、在URL中中文字符一般出如今如下两个地方:
(1)、Query String中的参数值,好比http://search.china.alibaba.com/search/offer_search.htm?keywords=中国
(2)、servlet path,好比:http://search.china.alibaba.com/selloffer/中国.html


二、出现乱码问题的缘由主要是如下几方面:
(1)、浏览器:咱们的客户端(浏览器)自己并无遵循URI编码的规范(http://www.w3.org/International/O-URL-code.html)。
(2)、Servlet服务器:Servlet服务器的没有正确配置。
(3)、开发人员并不了解Servlet的规范和API的含义。

2、基础知识:
一、一个http请求通过的几个环节:
浏览器(ie firefox)【get/post】------------>Servlet服务器------------------------------->浏览器显示
                               编码                 解码成unicode,而后将显示的内容编码        解码
(1) 浏览器把URL(以及post提交的内容)通过编码后发送给服务器。
(2) 这里的Servlet服务器实际上指的是由Servlet服务器提供的servlet实现ServletRequestWrapper,不一样应用服务器的servlet实现不一样,这些servlet的实现把这些内容解码转换为unicode,处理完毕后,而后再把结果(即网页)编码返回给浏览器。
(3) 浏览器按照指定的编码显示该网页。

        当对字符串进行编码和解码的时候都涉及到字符集,一般使用的字符集为ISO8859-一、GBK、UTF-八、UNICODE。


二、URL的组成:
域名:端口/contextPath/servletPath/pathInfo?queryString
说明:

一、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>

二、ServletPath是在应用的web.xml中配置。
<servlet-mapping>
    <servlet-name>Example</servlet-name>
    <url-pattern>/example/*</url-pattern>
</servlet-mapping>

二、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过。


三、开发人员必须清楚的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、下面咱们分别从浏览器和应用服务器来举例说明:
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]信息失去


(一)、浏览器
一、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。

小结:解决方案:
一、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

二、咱们建议URL中PathInfo和QueryString采用相同的编码,这样对服务器端处理的时候会更加简单。

二、还有一个问题,我发现不少程序员并不明白URL Encode是须要指定字符集的。不明白的人能够看看这篇文档:http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URLEncoder.html

二、 POST提交
        对于POST方式,表单中的参数值对是经过request body发送给服务器,此时浏览器会根据网页的ContentType("text/html; charset=GBK")中指定的编码进行对表单中的数据进行编码,而后发给服务器。
在服务器端的程序中咱们能够经过Request.setCharacterEncoding() 设置编码,而后经过request.getParameter得到正确的数据。

解决方案:
一、从最简单,所需代价最小来看,咱们对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。

总结:
一、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一般会采用相同的字符集来解码。

二、咱们建议URL中的URL Encode编码的字符集和网页的contentType的字符集采用相同的字符集,这样程序的实现就很简单,不用作复杂的编码转换。

相关文章
相关标签/搜索