`
wangyanlong0107
  • 浏览: 480519 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

【转】form表单提交数据编码方式及tomcat的接受编码方式

 
阅读更多

form有2中方法把数据提交给服务器,get和post,分别说下吧。 
(一)get提交 
1.首先说下客户端(浏览器)的form表单用get方法是如何将数据编码后提交给服务器端的吧。 
   
对于get方法来说,都是把数据串联在请求的url后面作为参数,如:http://localhost:8080/servlet?msg=abc 
(很常见的一个乱码问题就要出现了,如果url中出现中文或其它特殊字符的话,如:http://localhost:8080/servlet?msg=杭州,服务器端容易得到乱码),url拼接完成后,浏览器会对url进行URL encode,然后发送给服务器,URL encode的过程就是把部分url做为字符,按照某种编码方式(如:utf-8,gbk等)编码成二进制的字节码,然后每个字节用一个包含3个字符的字符串 "%xy" 表示,其中xy为该字节的两位十六进制表示形式。我这里说的可能不清楚,具体介绍可以看下java.net.URLEncoder类的介绍在这里。了解了URL encode的过程,我们能看到2个很重要的问题,第一:需要URL encode的字符一般都是非ASCII的字符(笼统的讲),再通俗的讲就是除了英文字母以外的文字(如:中文,日文等)都要进行URL encode,所以对于我们来说,都是英文字母的url不会出现服务器得到乱码问题,出现乱码都是url里面带了中文或特殊字符造成的;第二:URL encode到底按照那种编码方式对字符编码?这里就是浏览器的事情了,而且不同的浏览器有不同的做法,post方法先看有没
<meta http-equiv="charset" content="iso-8859-1">,没有,则用内码。中文版的浏览器一般会默认的使用GBK,通过设置浏览器也可以使用UTF-8,可能不同的用户就有不同的浏览器设置,也就造成不同的编码方式,所以很多网站的做法都是先把url里面的中文或特殊字符用javascript做URL encode,然后再拼接url提交数据,也就是替浏览器做了URL encode,好处就是网站可以统一get方法提交数据的编码方式。 完成了URL encode,那么现在的url就成了ASCII范围内的字符了,然后以iso-8859-1的编码方式转换成二进制随着请求头一起发送出去(http请求头在网络上是以iso-8859-1编码传送的 固定的,get/post方法的请求报头均是如此。这里想多说几句的是,对于get方法来说,没有请求实体,含有数据的url都在请求头里面,之所以用URL encode,我个人觉的原因是:对于请求头来说最终都是要用iso-8859-1编码方式编码成二进制的101010.....(类似于内码转换,利用中间表,内存的程序转换成iso-8859-1编码)的纯数据在互联网上传送,如果直接将含有中文等特殊字符做iso-8859-1编码会丢失信息,所以先做URL encode是有必要的。 

--------------------------------------------
上面说"URL encode到底按照那种编码方式对字符编码?这里就是浏览器的事情了" ,那么浏览器的编码方式是什么呢?首先是依赖
优先级是:<%@ page contentType="text/html;charset=UTF-8" %> 大于 <%@  pageEncoding="UTF-8"%> 大于 页面编码方式(
通过 右键->属性 查看) ,如果<%@ page contentType="text/html;charset=UTF-8" %> 在一起指定 <%@  pageEncoding="UTF-8"%>
如:<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> 那么charset 和pageEncoding编码要一致,否则
对有中文的页面会报错。
另外对于是form 的get 请求会encoding的,如图一,而不是form 的get 请求,而是自行构造的带有中文的URL 类似于:
window.location.href = "/cnca/conversionEx/download.action?startOscym="+startOscym+
"&endOscym="+endOscym+"&modelid="+modelid+"&realname="+realname;
是不会encoding的,如图二。

对Ajax 提交的post 或get 请求,也不会encoding。如果是Tomcat,在Action 中, request.getParameter()确定的值不乱码,
而部署到ws 上确乱码了, 所以应该人为去encoding,在js 用:
var url = "/cnca/conversionEx/download.action?startOscym="+startOscym+
"&endOscym="+endOscym+"&modelid="+modelid+"&realname="+realname;
url = encodeURI(url);
--------------------------------------------

2。服务器端(tomcat)是如何将数据获取到进行解码的。

 

   第一步是先把数据用iso-8859-1进行解码,对于get方法来说,tomcat获取数据的是ASCII范围内的请求头字符,其中的请求url里面带有参数数据,如果参数中有中文等特殊字符,那么目前还是URL encode后的%XY状态,先停下,我们先说下开发人员一般获取数据的过程。通常大家都是request.getParameter("name")获取参数数据,我们在request对象或得的数据都是经过解码过的,而解码过程中程序里是无法指定,这里要说下,有很多新手说用request.setCharacterEncoding("字符集")可以指定解码方式,其实是不可以的,看servlet的官方API说明有对此方法的解释:Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using getReader().可以看出对于get方法他是无能为力的。那么到底用什么编码方式解码数据的呢,这是tomcat的事情了,默认缺省用的是iso-8859-1,这样我们就能找到为什么get请求带中文参数为什么在服务器端得到乱码了,原因是在客户端一般都是用UTF-8或GBK对数据URL encode,这里用iso-8859-1方式URL decoder显然不行,在程序里我们可以直接

 

  1. new String(request.getParameter("name").getBytes("iso-8859-1"),"客户端指定的URL encode编码方式")       


还原回字节码,然后用正确的方式解码数据,网上的文章通常是在tomcat里面做个配置 
Xml代码

 

 

  1. <Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort="8443" URIEncoding="GBK"/>   


这样是让tomcat在获取数据后用指定的方式URL decoder(遇到“%”就做decode动作),URL decoder的介绍在这里 

http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URLDecoder.html#decode(java.lang.String,%20java.lang.String)
--------------------------------------------
我认为:URL 在经过 encoding (在网络上以字节码方式传输), 如以encoding的编码是GBK 为例,java.net.URLEncoder.encode("组织名称","GBK"),
在经过 encoding 提交到服务器(这里以Tomcat为例),用request.getParameter() 时首先经过了如下解码过程
java.net.URLDecoder.decode(经过encoding后以%xy表现形式的字节码,"ISO-8859-1"),因为encoding 的编码是GBK,
而decoding(解码)时的编码是ISO-8859-1。所以request.getParameter()得到是乱码。
用这种new java.lang.String((request.getParameter()).getBytes("ISO-8859-1"),"GBK") 以逆向方式:先用ISO-8859-1 Encoding,
然在用GBK decoding 成字符串。如下:
System.out.println(new java.lang.String((java.net.URLDecoder.decode(java.net.URLEncoder.encode("组织名称","GBK"),"ISO-8859-1")).getBytes("ISO-8859-1"),"GBK"));

(二)post提交 
1.客户端(浏览器)的form表单用post方法是如何将数据编码后提交给服务器端的。 
在post方法里所要传送的数据也要URL encode,那么他是用什么编码方式的呢? 
在form所在的html文件里如果有段<meta http-equiv="Content-Type" content="text/html; charset=字符集(GBK,utf-8等)"/>,那么post就会用此处指定的编码方式编码。一般大家都认为这段代码是为了让浏览器知道用什么字符集来对网页解释,所以网站都会把它放在html代码的最前端,尽量不出现乱码,其实它还有个作用就是指定form表单的post方法提交数据在http request body的URL encode编码方式。从这里可以看出对于get方法来说,浏览器对数据的URL encode的编码方式是有浏览器设置来决定,(可以用js做统一指定),而post方法,开发人员可以指定。

2。服务器端(tomcat)是如何将数据获取到进行解码的。 
如果用tomcat默认缺省设置,也没做过滤器等编码设置,那么他也是用iso-8859-1解码的,但是request.setCharacterEncoding("字符集")可以派上用场。

 

http://www.cnblogs.com/yencain/articles/1321386.html; 
http://wanghuan8086.javaeye.com/blog/173869

 

自从Tomcat5.x开始,GET和POST方法提交的信息,tomcat采用了不同的方式来处理编码对于POST请求,Tomcat会仍然使用request.setCharacterEncoding方法所设置的编码来处理,如果未设置,则使用默认的iso-8859-1编码。而GET请求则不同,Tomcat对于GET请求并不会考虑使用request.setCharacterEncoding方法设置的编码,而会永远使用iso-8859-1编码,而这位朋友使用的正好是GET请求,因此,tomcat将会使用iso-8859-1将提交的字节转换成字符串。 
解决的方法有三个: 
1.  将GET请求改成POST请求,然后就可以使用request.setCharacterEncoding方法设置编码,并使用request.getParameter方法直接获得中文请求参数了。 
2.  不用改GET请求,在Servlet中使用如下的代码来得到中文请求参数。 
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK"); 
3.为了保证get数据采用UTF8编码,在server.xml中进行了如下设置 
<connector port="8080" maxthreads="150" minsparethreads="25" <br="">maxSpareThreads="75" enableLookups="false" redirectPort="8443" 
acceptCount="100" debug="99" connectionTimeout="20000" 
disableUploadTimeout="true" URIEncoding="UTF-8"/> 

 

分享到:
评论

相关推荐

    关于\"form表单提交数据编码方式和tomcat接受数据解码方式的思考\"一文的纠错

    NULL 博文链接:https://strength-java.iteye.com/blog/1455439

    Tomcat容器管理安全的验证方式汇总

    当访问服务器中受保护的资源时,容器管理的验证方法可以控制确认用户身份的方式。Tomcat支持四种容器管理的安全防护,它们是: 1、BASIC(基本验证):通过HTTP验证,需要提供base64编码文本的用户口令 2、DIGEST(摘要...

    Servlet与JSP核心编程第2版

    第4章 客户请求的处理:表单数据 4.1 表单数据的作用 4.2 在servlet中读取表单数据 4.3 示例:读取3个参数 4.4 示例:读取所有参数 4.5 参数缺失或异常时默认值的应用 4.6 过滤字符串中的html特殊字符 ...

    JavaScript完全自学宝典 源代码

    Web服务器:Tomcat 5.5.20及以上版本 Java运行时环境:Java5.0 JRE及以上版本 2.本书所附光盘范例 第1章(\c01) 示例描述:演示JavaScript的简单应用及JavaScript特效。 1.1.html 用JavaScript开发的弹出式...

    外文翻译 stus MVC

    • Before passing it to the Action class, Struts will also conduct form state validation by calling the validation() method on UserActionForm. Note: This is not always wise to do. There might be ways ...

    Java学习笔记-个人整理的

    {1.2}数字表达方式}{17}{section.1.2} {1.3}补码}{19}{section.1.3} {1.3.1}总结}{23}{subsection.1.3.1} {1.4}数据类型}{23}{section.1.4} {1.4.1}整数与浮点数}{23}{subsection.1.4.1} {1.4.1.1}浮点数原理}...

    超级有影响力霸气的Java面试题大全文档

     ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,...

    java 面试题 总结

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector...

    Spring Security 中文教程.pdf

    16. acegi到spring security的转换方式 16.1. Spring Security是什么 16.2. 目标 16.3. 步骤 16.4. 总结 V. 高级话题 17. 领域对象安全(ACLs) 17.1. 概述 17.2. 关键概念 17.3. 开始 18. 预认证...

    Spring Security-3.0.1中文官方文档(翻译版)

    16. acegi 到spring security 的转换方式 16.1. Spring Security 是什么 16.2. 目标 16.3. 步骤 16.4. 总结 V. 高级话题 17. 领域对象安全(ACLs) 17.1. 概述 17.2. 关键概念 17.3. 开始 18. 预...

Global site tag (gtag.js) - Google Analytics