overview
If we request
pass it to an asynchronous thread, we may not be able to get the parameters, and it will cause subsequent requests, and there will be problems when using this thread.
The reason is that request
objects are reused.
Source code analysis
1. Get parameters
Let’s look at a very important method first. getParameter
The first time the method is called, the parameters will be parsed, and then it will no longer be parsed.
package org.apache.catalina.connector;
public class Request implements HttpServletRequest {
/**
* 请求参数解析标志(默认为false)
*/
protected boolean parametersParsed = false;
@Override
public String getParameter(String name) {
if (!parametersParsed) {
//判断是否已经解析参数,如果没解析,则进行解析。
parseParameters();
}
return coyoteRequest.getParameters().getParameter(name);
}
}
2. Analyzing parameters
It is this method that actually parses the parameters parameters.handleQueryParameters();
.
/**
* 解析请求参数
*/
protected void parseParameters() {
parametersParsed = true;
Parameters parameters = coyoteRequest.getParameters();
boolean success = false;
try {
......
parameters.handleQueryParameters(); //真正解析参数的方法
......
success = true;
} finally {
if (!success) {
parameters.setParseFailedReason(FailReason.UNKNOWN);
}
}
}
3. Process the query string as a parameter
/**
* 将查询字符串处理为参数
*/
public void handleQueryParameters() {
if (didQueryParameters) {
//判断是否已经处理过了
return;
}
didQueryParameters = true;
......
processParameters(decodedQuery, queryStringCharset);
}
4. Add parameters to paramHashValues
When the program executes here, the parameters will be added to paramHashValues
this map
, and when the parameters are obtained, they are directly map
obtained from this.
private final Map<String,ArrayList<String>> paramHashValues =
new LinkedHashMap<>();
public void addParameter( String key, String value )
throws IllegalStateException {
if( key==null ) {
return;
}
parameterCount ++;
if (limit > -1 && parameterCount > limit) {
// Processing this parameter will push us over the limit. ISE is
// what Request.parseParts() uses for requests that are too big
setParseFailedReason(FailReason.TOO_MANY_PARAMETERS);
throw new IllegalStateException(sm.getString(
"parameters.maxCountFail", Integer.valueOf(limit)));
}
ArrayList<String> values = paramHashValues.get(key);
if (values == null) {
values = new ArrayList<>(1);
paramHashValues.put(key, values);
}
values.add(value);
}
5. Release request
The code of the final request will go to this place, and the parameters of the request will be cleared here, and then it will be reused for the next request.
The method is called recycle, indicating that it is recycling, in which the Map storing parameters will be cleared, and didQueryParameters will be set to false again.
public void recycle() {
parameterCount = 0;
paramHashValues.clear();
didQueryParameters = false;
charset = DEFAULT_BODY_CHARSET;
decodedQuery.recycle();
parseFailedReason = null;
}
There are indications that request is recycled in tomcat.
Reference:
https://blog.csdn.net/JavaMonsterr/article/details/126033884