`
ymq267
  • 浏览: 130415 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式

 
阅读更多
[size=large]HTTP请求中,如果是get请求,那么表单参数以name=value&name1=value1的形式附到url的后面,如果是post请求,那么表单参数是在请求体中,也是以name=value&name1=value1的形式在请求体中。通过chrome的开发者工具可以看到如下(这里是可读的形式,不是真正的HTTP请求协议的请求格式):

get请求:
RequestURL:http://127.0.0.1:8080/test/test.do?name=mikan&address=street  
Request Method:GET  
Status Code:200 OK  
   
Request Headers  
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
Accept-Encoding:gzip,deflate,sdch  
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6  
AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2  
Connection:keep-alive  
Cookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8D  
Host:127.0.0.1:8080  
Referer:http://127.0.0.1:8080/test/index.jsp  
User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36  
   
Query String Parameters  
name:mikan  
address:street  
   
Response Headers  
Content-Length:2  
Date:Sun, 11 May 2014 10:42:38 GMT  
Server:Apache-Coyote/1.1 


Post请求:

RequestURL:http://127.0.0.1:8080/test/test.do 
Request Method:POST 
Status Code:200 OK 
  
Request Headers 
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Accept-Encoding:gzip,deflate,sdch 
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6 
AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2 
Cache-Control:max-age=0 
Connection:keep-alive 
Content-Length:25 
Content-Type:application/x-www-form-urlencoded 
Cookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8D 
Host:127.0.0.1:8080 
Origin:http://127.0.0.1:8080 
Referer:http://127.0.0.1:8080/test/index.jsp 
User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36 
  
Form Data 
name:mikan 
address:street 
  
Response Headers 
Content-Length:2 
Date:Sun, 11 May 2014 11:05:33 GMT 
Server:Apache-Coyote/1.1 

这里要注意post请求的Content-Type为application/x-www-form-urlencoded,参数是在请求体中,即上面请求中的Form Data。

在servlet中,可以通过request.getParameter(name)的形式来获取表单参数。

而如果使用原生AJAX POST请求的话:

function getXMLHttpRequest() {  
          var xhr;  
          if(window.ActiveXObject) {  
                   xhr= new ActiveXObject("Microsoft.XMLHTTP");  
          }else if (window.XMLHttpRequest) {  
                   xhr= new XMLHttpRequest();  
          }else {  
                   xhr= null;  
          }  
          return xhr;  
}  
  
function save() {  
          var xhr = getXMLHttpRequest();  
          xhr.open("post","http://127.0.0.1:8080/test/test.do");  
          var data = "name=mikan&address=street...";  
          xhr.send(data);  
          xhr.onreadystatechange= function() {  
                   if(xhr.readyState == 4 && xhr.status == 200) {  
                            alert("returned:"+ xhr.responseText);  
                   }  
          };  
}  


通过chrome的开发者工具看到请求头如下:

RequestURL:http://127.0.0.1:8080/test/test.do  
Request Method:POST  
Status Code:200 OK  
   
Request Headers  
Accept:*/*  
Accept-Encoding:gzip,deflate,sdch  
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6  
AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2  
Connection:keep-alive  
Content-Length:28  
Content-Type:text/plain;charset=UTF-8  
Cookie:JSESSIONID=C40C7823648E952E7C6F7D2E687A0A89  
Host:127.0.0.1:8080  
Origin:http://127.0.0.1:8080  
Referer:http://127.0.0.1:8080/test/index.jsp  
User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36  
   
Request Payload  
name=mikan&address=street  
   
Response Headers  
Content-Length:2  
Date:Sun, 11 May 2014 11:49:23 GMT  
Server:Apache-Coyote/1.1  


注意请求的Content-Type为text/plain;charset=UTF-8,而请求表单参数在RequestPayload中。

那么servlet中通过request.getParameter(name)却是空。为什么呢?而这样的参数又该怎么样获取呢?

为了搞明白这个问题,查了些资料,也看了Tomcat7.0.53关于请求参数处理的源码,终于搞明白了是怎么回事。

HTTP POST表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使用原生AJAX的POST请求如果不指定请求头RequestHeader,默认使用的Content-Type是text/plain;charset=UTF-8。

由于Tomcat对于Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)做了“特殊处理”。下面来看看相关的处理代码。

Tomcat的HttpServletRequest类的实现类为org.apache.catalina.connector.Request(实际上是org.apache.coyote.Request),而它对处理请求参数的方法为protected void parseParameters(),这个方法中对Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)的处理代码如下:

protectedvoid parseParameters() {  
           //省略部分代码......  
           parameters.handleQueryParameters();// 这里是处理url中的参数  
           //省略部分代码......  
           if ("multipart/form-data".equals(contentType)) { // 这里是处理文件上传请求  
                parseParts();  
                success = true;  
                return;  
           }  
   
           if(!("application/x-www-form-urlencoded".equals(contentType))) {// 这里如果是非POST请求直接返回,不再进行处理  
                success = true;  
                return;  
           }  
           //下面的代码才是处理POST请求参数  
           //省略部分代码......  
           try {  
                if (readPostBody(formData, len)!= len) { // 读取请求体数据  
                    return;  
                }  
           } catch (IOException e) {  
                // Client disconnect  
                if(context.getLogger().isDebugEnabled()) {  
                    context.getLogger().debug(  
                            sm.getString("coyoteRequest.parseParameters"),e);  
                }  
                return;  
           }  
           parameters.processParameters(formData, 0, len); // 处理POST请求参数,把它放到requestparameter map中(即request.getParameterMap获取到的Map,request.getParameter(name)也是从这个Map中获取的)  
           // 省略部分代码......  
}  
   
   protected int readPostBody(byte body[], int len)  
       throws IOException {  
   
       int offset = 0;  
       do {  
           int inputLen = getStream().read(body, offset, len - offset);  
           if (inputLen <= 0) {  
                return offset;  
           }  
           offset += inputLen;  
       } while ((len - offset) > 0);  
       return len;  
    }  


从上面代码可以看出,Content-Type不是application/x-www-form-urlencoded的POST请求是不会读取请求体数据和进行相应的参数处理的,即不会解析表单数据来放到request parameter map中。所以通过request.getParameter(name)是获取不到的。
那么这样提交的参数我们该怎么获取呢?

当然是使用最原始的方式,读取输入流来获取了,如下所示:

privateString getRequestPayload(HttpServletRequest req) {  
          StringBuildersb = new StringBuilder();  
          try(BufferedReaderreader = req.getReader();) {  
                   char[]buff = new char[1024];  
                   intlen;  
                   while((len = reader.read(buff)) != -1) {  
                            sb.append(buff,0, len);  
                   }  
          }catch (IOException e) {  
                   e.printStackTrace();  
          }  
          returnsb.toString();  
}  


当然,设置了application/x-www-form-urlencoded的POST请求也可以通过这种方式来获取。

所以,在使用原生AJAX POST请求时,需要明确设置Request Header,即:

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 


另外,如果使用jQuery,我使用1.11.0这个版本来测试,$.ajax post请求是不需要明确设置这个请求头的,其他版本的本人没有亲自测试过。相信在1.11.0之后的版本也是不需要设置的。不过之前有的就不一定了。这个没有测试过。


最近在看书时才真正搞明白,服务器为什么会对表单提交和文件上传做特殊处理,因为表单提交数据是名值对的方式,且Content-Type为application/x-www-form-urlencoded,而文件上传服务器需要特殊处理,普通的post请求(Content-Type不是application/x-www-form-urlencoded)数据格式不固定,不一定是名值对的方式,所以服务器无法知道具体的处理方式,所以只能通过获取原始数据流的方式来进行解析。

jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。
[/size]
分享到:
评论

相关推荐

    Servlet获取AJAX POST请求中参数以form data和request payload形式传输的方法

    本篇文章主要探讨如何在Servlet中处理AJAX POST请求,特别是当请求参数以`form data`和`request payload`两种不同形式传递时。 首先,理解HTTP请求的基本结构。GET请求的参数通常附加在URL后面,而POST请求的参数...

    python爬虫实现POST request payload形式的请求

    总之,理解`request payload`与`form data`的区别,并能用Python的`requests`库正确构造和发送POST请求,是Python爬虫开发中不可或缺的技能。在实际应用中,我们应根据目标网站的具体需求来选择合适的数据格式和方法...

    POST方法发送payload形式的请求1

    Form data是HTTP POST请求中最常见的数据格式,它在请求体中以`key1=value1&key2=value2`的形式存在,通常与HTML表单关联,Content-Type设置为`application/x-www-form-urlencoded`。然而,Request payload则常用于...

    如何用selenium封装post参数提交示例

    在描述中提到的,我们将探讨如何使用Selenium来封装POST参数并提交,以获取异步请求返回的JSON对象值。 首先,理解Selenium的基本结构是必要的。Selenium通常包含WebDriver接口,它提供了一种方式来控制浏览器,并...

    Python爬虫:Request Payload和Form Data的简单区别说明

    在POST请求中,数据的提交方式有两种主要的形式:`Request Payload`和`Form Data`。这两种方式的区别主要体现在`Content-Type`请求头的设置上。 1. **Form Data**: - `Form Data` 是指按照`application/x-...

    request payload传值解决-qs.min.js

    前端以 request payload形式传参,通过qs.min.js实现传参,实现后台接收 。

    UniApp中封装request网络请求包含GET、POST、PUT、DELETE等

    在这个封装中,我们为GET、POST、PUT和DELETE方法提供了统一的调用接口,并在`request`函数中处理了基础的请求配置,如URL前缀、数据序列化、添加认证头以及错误处理。`showLoading`和`loadingText`用于显示加载提示...

    C# post 传值 和接收值实例

    1. 在控制器方法中添加参数,框架会自动尝试将请求体中的数据绑定到这些参数: ```csharp [HttpPost] public ActionResult SaveData([FromBody] dynamic data) { var keyValue = data.key; // 假设请求体是{"key":...

    request-payload:Node.js模块获取HTTP请求的有效负载

    请求有效负载 获取HTTP请求的有效负载。 支持限制有效载荷的大小。 安装 npm install request-payload 用法 例子 var http = require ( 'http' ) ; var payload = require ( 'request-payload' ) ; ...

    Request Payload Too Large(解决方案).md

    Request Payload Too Large(解决方案).md

    使用Http post的方式调用webservice

    在调用WebService时,POST方法可以承载请求参数,将其封装在请求体中发送到服务端。 1. **构建HTTP请求** 在Java中,可以使用`java.net.URL`、`java.net.HttpURLConnection`或第三方库如Apache HttpClient来构建...

    request和response

    当调用此方法时,当前Servlet或JSP会将控制权交给目标资源,但请求和响应对象保持不变,这意味着目标资源可以访问到原始请求的所有数据,包括请求参数和通过`setAttribute()`方法设置的属性。这种方法的优点在于它...

    SpringBoot控制器统一的响应体加密与请求体解密的注解处理方式

    通过这种方式,我们可以在SpringBoot应用中实现控制器响应体的统一加密和请求体的解密,同时支持多种加密算法,从而增强系统的安全性。在项目`Licoy-encrypt-body-spring-boot-starter-ffe8b7a`中,应该包含了具体的...

    python爬虫请求—post

    Python爬虫技术是数据获取的...在`demo03_post请求参数.py`这个示例文件中,你可以找到具体实现这一过程的代码,通过阅读和运行这个文件,你可以更好地理解这一过程。请根据实际情况调整代码,以适应不同的登录场景。

    python中get和post有什么区别

    在Python编程中,GET和POST是HTTP协议中最常用的两种请求方法,它们主要在发送数据到服务器时有不同的行为和用途。 1. 数据传输位置: - GET:数据通过URL(Uniform Resource Locator)作为查询字符串附加在URL...

    解决Python发送Http请求时,中文乱码的问题

    在这个示例中,我们使用了一个特定的payload结构来模拟翻页操作,并且通过`json.dumps()`函数将Python对象转换为JSON格式的字符串,以便通过POST请求发送。此外,还提供了将JSON数据解析为Python字典的方法。 以上...

    FANUC机器人PAYLOAD设置.pdf

    FANUC机器人的有效负载...总的来说,FANUC机器人的PAYLOAD设置是一个涉及多个参数和步骤的过程,它对机器人的性能和安全性有着直接影响。正确地设置和管理有效负载是每个使用FANUC机器人的操作员和技术人员必备的技能。

    前台ajax与后台json传递

    在这个例子中,我们创建了一个新的XMLHttpRequest对象,设置请求方法为POST,目标URL为'/api/data',并指定了Content-Type为'application/json',表示我们将发送Json格式的数据。当请求状态改变时,我们检查...

Global site tag (gtag.js) - Google Analytics