In HTTP request, if it is a get request, the form parameter is attached to the url in the form of name=value&name1=value1. If it is a post request, the form parameter is in the request body, and is also in the request body in the form of name=value&name1=value1. Through the chrome developer tools, you can see the following (here is a readable form, not a real HTTP request protocol request format):
get request:
RequestURL:http://127.0.0.1:8080/test/?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/
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 request:
RequestURL:http://127.0.0.1:8080/test/
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/
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
Here we should note that the Content-Type of the post request is application/x-www-form-urlencoded, and the parameter is in the request body, that is, the Form Data in the above request.
In a servlet, form parameters can be obtained in the form of (name).
And if using native AJAX POST request:
function getXMLHttpRequest() {
var xhr;
if() {
xhr= new ActiveXObject("");
}else if () {
xhr= new XMLHttpRequest();
}else {
xhr= null;
}
return xhr;
}
function save() {
var xhr = getXMLHttpRequest();
("post","http://127.0.0.1:8080/test/");
var data = "name=mikan&address=street...";
(data);
= function() {
if( == 4 && == 200) {
alert("returned:"+ );
}
};
}
Through Chrome's developer tools, see the request header as follows:
RequestURL:http://127.0.0.1:8080/test/
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/
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
Note that the requested Content-Type is text/plain;charset=UTF-8, and the request form parameter is in RequestPayload.
Then the pass (name) in the servlet is empty. Why? And how should such parameters be obtained?
In order to understand this problem, I looked up some information and read the source code of Tomcat7.0.53 on request parameter processing, and finally figured out what was going on.
When submitting HTTP POST form requests, the Content-Type used is application/x-www-form-urlencoded. If the request header RequestHeader is not specified, the Content-Type used by default is text/plain; charset=UTF-8.
Because Tomcat does "special processing" for Content-Type multipart/form-data (file upload) and application/x-www-form-urlencoded (POST request). Let’s take a look at the relevant processing code below.
The implementation class of Tomcat's HttpServletRequest class is (actually), and its method of processing request parameters is protected void parseParameters(). The processing codes for Content-Type multipart/form-data (file upload) and application/x-www-form-urlencoded (POST request) in this method are as follows:
protectedvoid parseParameters() {
//Omit some code...
();// Here is the parameters in the url
//Omit some code...
if ("multipart/form-data".equals(contentType)) { // Here is the process of file upload request
parseParts();
success = true;
return;
}
if(!("application/x-www-form-urlencoded".equals(contentType))) {// If it is a non-POST request, it will not be processed.
success = true;
return;
}
//The following code is the POST request parameter
//Omit some code...
try {
if (readPostBody(formData, len)!= len) { // Read request body data
return;
}
} catch (IOException e) {
// Client disconnect
if(().isDebugEnabled()) {
().debug(
(""),e);
}
return;
}
(formData, 0, len); // Process the POST request parameter and put it in the requestparameter map (that is, the obtained map, (name) is also obtained from this map)
// Some codes are omitted...
}
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;
}
From the above code, we can see that the POST request of Content-Type is not application/x-www-form-urlencoded will not read the request body data and perform corresponding parameter processing, that is, it will notAnalysisPut the form data into the request parameter map. Therefore, it cannot be obtained through (name).
So how do we obtain the parameters submitted in this way?
Of course, it is the most primitive method to read the input stream to obtain it, as shown below:
privateString getRequestPayload(HttpServletRequest req) {
StringBuildersb = new StringBuilder();
try(BufferedReaderreader = ();) {
char[]buff = new char[1024];
intlen;
while((len = (buff)) != -1) {
(buff,0, len);
}
}catch (IOException e) {
();
}
();
}
Of course, POST requests with application/x-www-form-urlencoded set can also be obtained in this way.
Therefore, when using native AJAX POST request, you need to explicitly set the Request Header, that is:
("Content-Type","application/x-www-form-urlencoded");
In addition, if you use jquery, I use the 1.11.0 version to test it. The $.ajax post request does not need to set this request header explicitly, and I have not tested it myself for other versions. I believe that versions after 1.11.0 do not need to be set. But some before may not be certain. This has not been tested.
2015-04-17 Postscript:
I really understood why the server does special processing for form submission and file upload, because the form submission data is a name-value pair, and the Content-Type is application/x-www-form-urlencoded, while the file upload server needs special processing. The data format of ordinary post requests (Content-Type is not application/x-www-form-urlencoded) is not fixed, and it is not necessarily a name-value pair, so the server cannot know the specific processing method, so it can only parse by obtaining the original data stream.
When jquery executes a post request, it sets Content-Type to application/x-www-form-urlencoded, so the server can parse correctly. When using native ajax request, if Content-Type is not displayed, the default is text/plain. At this time, the server does not know how to parse the data, so it can only parse the request data by obtaining the original data stream.