jsp页面中通过请求另一个页面并通过url传递了带有中文的参数,结果在接收端获取参数时乱码了

经检查乱码现象指出新在IE浏览器中,其他浏览器火狐、chrome等不会有问题

最后的解决方式是:

手动将此中文进行编码:encodeURI(url)即可

先来看看三个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中配置。

  1. <span style="font-size:12px;"><jboss-web>
  2. <context-root>/</context-root>
  3. </jboss-web></span>

2、ServletPath是在应用的web.xml中配置。

  1. <span style="font-size:12px;"><servlet-mapping>
  2. <servlet-name>Example</servlet-name>
  3. <url-pattern>/example/*</url-pattern>
  4. </servlet-mapping></span>

2、Servlet API
我们使用以下servlet API获得URL的值及参数。

  1. <span style="font-size:12px;">request.getParameter("name");           // 获得queryString的参数值(来自于get和post),其值经过Servlet服务器URL Decode过的
  2. request.getPathInfo();                  // 注意:pathinfo返回的字符串是经过Servlet服务器URL Decode过的。
  3. requestURI = request.getRequestURI(); // 内容为:contextPath/servletPath/pathinfo 浏览器提交过来的原始数据,未被Servlet服务器URL Decode过。</span>

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

(2) 对于中文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

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

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

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

  1. <span style="font-size:12px;"><Connector port="8080" protocol="HTTP/1.1"
  2. maxThreads="150" connectionTimeout="20000"
  3. redirectPort="8443" URIEncoding="GBK"/></span>

URIEncoding告诉服务器servlet解码URL时采用的编码。

<Connector port="8080" ... useBodyEncodingForURI="true" />
useBodyEncodingForURI告诉服务器解码URL时候需要采用request body指定的编码。

(2) weblogic服务器
对于weblogic服务器,该文件是weblogic.xml

  1. <span style="font-size:12px;"><input-charset>
  2. <java-charset-name>GBK</java-charset-name>
  3. </input-charset></span>

(三)浏览器显示
浏览器根据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。

浏览器URL编码的更多相关文章

  1. 浏览器 url 编码

    1.问题的由来 : http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 2.网络标准RFC 1738做了硬性规定: 只有字母和数字[0-9 ...

  2. URL编码:不同的操作系统、不同的浏览器、不同的网页字符集,将导致完全不同的编码结果。

    URL编码:不同的操作系统.不同的浏览器.不同的网页字符集,将导致完全不同的编码结果. 因此如果Url中有中文或特殊字符,一定要自己调用函数编码解码,不要让浏览器帮你编码,否则出现了问题会浪费你很多时 ...

  3. 浏览器url地址殊字符转义编码

    网址URL中特殊字符转义编码字符    -    URL编码值 空格    -    %20"          -    %22#         -    %23%        -   ...

  4. 浏览器自动转换URL编码产生乱码问题

    如果网址中含有汉字,浏览器会自动将其转换成URL编码,而在接收端,它又自动转换回来. 大部分时候都没什么问题,但有时候就很讨厌.因为生成这种URL编码,编码时的字符集和解码字符集不一定相同,比如编码时 ...

  5. url 编码(percentcode 百分号编码)(转载)

    原文地址:http://www.cnblogs.com/leaven/archive/2012/07/12/2588746.html   http://www.imkevinyang.com/2009 ...

  6. 【原】聊一聊 url 编码问题

    最近项目中遇到需要编码的一个问题,在encode和encodeURIComponent上绕了个小圈,所以打算总结一下js的编码问题,网上也有很多类似的文章,不过呢,总结出来的东西才是自己滴 为什么需要 ...

  7. 【基础进阶】URL详解与URL编码

    作为前端,每日与 URL 打交道是必不可少的.但是也许每天只是单纯的用,对其只是一知半解,随着工作的展开,我发现在日常抓包调试,接口调用,浏览器兼容等许多方面,不深入去理解URL与URL编码则会踩到很 ...

  8. 【阮一峰】深入研究URL编码问题及JavaScript相应的解决方案

    作者: 阮一峰 日期: 2010年2月11日 一.问题的由来 URL就是网址,只要上网,就一定会用到. 一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号.比如,世界上 ...

  9. url编码

    url编码 情况1:网址路径中包含汉字 打开IE,输入网址”http://zh.wikipedia.org/wiki/春节”.注意,”春节”这两个字此时是网址路径的一部分. 查看HTTP请求的头信息, ...

随机推荐

  1. c++之vector

    vector是STL中最常见的容器,它是一种顺序容器,支持随机访问.vector是一块连续分配的内存,从数据安排的角度来讲,和数组极其相似, 不同的地方就是:数组是静态分配空间,一旦分配了空间的大小, ...

  2. 在 NetBeans IDE 6.0 中分析 Java 应用程序性能

    NetBeans IDE 6.0 包含一个强大的性能分析工具,可提供与应用程序运行时行为有关的重要信息.通过 NetBeans 性能分析工具,我们可以方便地在 IDE 中监控应用程序的线程状态.CPU ...

  3. json对象与json字符串对象格式

    var cStr = "{\"c\":\"{\\\"b\\\":\\\"000\\\",\\\"b2\\\&q ...

  4. Apache Spark技术实战之4 -- 利用Spark将json文件导入Cassandra

    欢迎转载,转载请注明出处. 概要 本文简要介绍如何使用spark-cassandra-connector将json文件导入到cassandra数据库,这是一个使用spark的综合性示例. 前提条件 假 ...

  5. 使用 JavaScript 实现链表

    代码: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...

  6. 安卓仿微信Tab页用Fragment实现

    最终效果图如: 实现步骤: 新建项目tabdemo,我选的是4.0.3版本,然后依次新建三个Fragment,名字分别为:ChatFragment.FriendFragment.FindFragmen ...

  7. [LeetCode]题解(python):116 Populating Next Right Pointers in Each Node

    题目来源 https://leetcode.com/problems/populating-next-right-pointers-in-each-node/ Given a binary tree ...

  8. k8s入门系列之集群安装篇

    关于kubernetes组件的详解介绍,请阅读上一篇文章<k8s入门系列之介绍篇> Kubernetes集群安装部署 •Kubernetes集群组件: - etcd 一个高可用的K/V键值 ...

  9. ng-bind-html 的原素没有高度

    angularjs里绑定html元素,在页面的div里使用ng-bind-html <!-- html--> <div class="info" ng-bind- ...

  10. Chrome浏览器M53更新后超链接的dispatchEvent(evt)方法无法触发文件下载

    一个经典的js前台文件下载方法: var aLink = document.createElement('a'); var datatype="data:text/plain;charset ...