GET和POST

本文详细解析了GET和POST两种HTTP请求方式的工作原理,包括客户端如何编码数据并发送给服务器,以及服务器端如何解码这些数据。重点介绍了不同情况下可能出现的乱码问题及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(一)get提交 
  1.首先说下客户端(浏览器)的form表单用get方法是如何将数据编码后提交给服务器端的吧。 
       对于get方法来说,都是把数据串联在请求的url后面作为参数,如:http://localhost:8080/servlet?msg=abc ,

如果url中出现中文或其它特殊字符的话,服务器端容易得到乱码,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到底按照那种编码方式对字符编码?这里就是浏览器的事情了,而且不同的浏览器有不同的做法,中文版的浏览器一般会默认的使用GBK,通过设置浏览器也可以使用UTF-8,可能不同的用户就有不同的浏览器设置,也就造成不同的编码方式,所以很多网站的做法都是先把url里面的中文或特殊字符用 javascript做URL encode,然后再拼接url提交数据,也就是替浏览器做了URL encode,好处就是网站可以统一get方法提交数据的编码方式。

(Roxanne:浏览器把中文请求encode成GBK二进制形式,下面说的合理性有待验证,request的getQuerySTring()方法可以直接得到前面的GBK二进制,然后重新按GBK解码的时候没有问题发生,至于用getParameter()方法得到的数据,可能已经由服务器按iso-8859-1解码的时候丢失了数据导致乱码)

 完成了URL encode,那么现在的url就成了ASCII范围内的字符了,然后以iso-8859-1的编码方式转换成二进制随着请求头一起发送出去。这里想多说几句的是,对于get方法来说,没有请求实体,含有数据的url都在请求头里面,之所以用URL encode,我个人觉的原因是:对于请求头来说最终都是要用iso-8859-1编码方式编码成二进制的101010.....的纯数据在互联网上传送,如果直接将含有中文等特殊字符做iso-8859-1编码会丢失信息,所以先做URL encode是有必要的。 

   2。服务器端(tomcat)是如何将数据获取到进行解码的。 
   第一步是先把数据用iso-8859-1进行解码,对于get方法来说,tomcat获取数据的是ASCII范围内的请求头字符,其中的请求url里面带有参数数据,如果参数中有中文等特殊字符,那么目前还是URL encode后的%XY状态。(Roxanne:验证了我上面的说法)先停下,我们先说下开发人员一般获取数据(当request的数据得到正确处理后)的过程。通常大家都是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方法他是无能为力的。(Roxanne:不知道什么意思,反正就是get里面不能用这个方法, 有文章说post的数据是request的一部分)那么到底用什么编码方式解码数据的呢,这是tomcat的事情了,默认缺省用的是 iso-8859-1,这样我们就能找到为什么get请求带中文参数为什么在服务器端得到乱码了,原因是在客户端一般都是用UTF-8或GBK对数据 URL encode,这里用iso-8859-1方式URL decoder显然不行,在程序里我们可以直接 
Java代码 
1. new String(request.getParameter("name").getBytes("iso-8859-1"),"客户端指定的URL encode编码方式")  

还原回字节码,然后用正确的方式解码数据(Roxanne:难道这里还要解码数据吗?不是已经解码了吗。getByte()得到的是字节数组,解码是对二进制进行解码,估计是中间涉及了一个编码的步骤,所以要重新解码,待解决)

网上的文章通常是在tomcat里面做个配置 

Xml代码 
1. <Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort="8443" URIEncoding="GBK"/>  
这样是让tomcat在获取数据后用指定的方式URL decoder,在request得到参数前得到正确解码,URL decoder的介绍在这里 
(一)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方法提交数据的 URL encode编码方式从这里可以看出对于get方法来数,浏览器对数据的URL encode的编码方式是有浏览器设置来决定,(可以用js做统一指定),而post方法,开发人员可以指定。 
2。服务器端(tomcat)是如何将数据获取到进行解码的。 
如果用tomcat默认缺省设置,也没做过滤器等编码设置,那么他也是用iso-8859-1解码的,但是request.setCharacterEncoding("字符集")可以派上用场。 
我发现上面说的tomcat所做的事情前提都是在请求头里没有指定编码方式,如果请求头里指定了编码方式将按照这种方式编码。  
   有2篇文章推荐下,地址分别是 
深入浅出URL编码:
http://www.cnblogs.com/yencain/articles/1321386.html ; 
表单用post方法提交数据时乱码问题:
http://wanghuan8086.javaeye.com/blog/173869  
### GET POST 请求的区别及用法 #### 基本概念 GET POST 是最常用的两种 HTTP 方法,主要用于在客户端服务器之间传输数据。通过这些方法实现请求-响应机制,从而完成数据的获取或提交。 #### 数据传递方式 - **GET 方法**:当使用 GET 方法时,参数会附加到 URL 中作为查询字符串的一部分[^1]。这意味着所有的数据都暴露在外,适合于无敏感信息的数据传递。 - **POST 方法**:相比之下,POST 将数据放在请求体中发送给服务器[^2]。这种方式更加安全,因为数据不会显示在浏览器地址栏里。 #### 安全性可见性 - 使用 **GET** 的时候,由于所有参数都在URL上展示出来,因此不适合处理涉及隐私或者机密的信息[^3]。 - 对于需要保护的内容,则推荐采用 **POST** 来隐藏实际传送的数据。 #### 缓存行为 - 浏览器通常会对相同的 GET 请求进行缓存以便加快访问速度;而每次新的 POST 请求都会被当作独立事件对待并重新执行操作而不利用之前的存储结果。 #### 处理能力 - **GET**: 主要用来读取资源,理论上不应该改变服务器状态。 - **POST**: 可以创建新资源或将更新现有资源的状态。 以下是两个简单的 Python 示例来演示如何分别发起 GET POST 请求: ```python import requests # Example of making a GET request response_get = requests.get('https://example.com/api/data', params={'key': 'value'}) print(response_get.url) # Example of making a POST request payload_post = {'username': 'testuser', 'password': 'securepass'} response_post = requests.post('https://example.com/login', data=payload_post) ``` ### 结论 综上所述,在选择使用哪种类型的 HTTP 请求时应考虑具体应用场景的需求以及安全性等因素的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值