visão geral
Se request
o passarmos para um thread assíncrono, podemos não obter os parâmetros e isso causará solicitações subsequentes e haverá problemas ao usar este thread.
A razão é que request
os objetos são reutilizados.
Análise do código-fonte
1. Obter parâmetros
Vejamos primeiro um método muito importante. getParameter
Na primeira vez que o método é chamado, os parâmetros serão analisados e, em seguida, não serão mais analisados.
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. Analisando parâmetros
É esse método que realmente analisa os parâmetros 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. Processe a string de consulta como um parâmetro
/**
* 将查询字符串处理为参数
*/
public void handleQueryParameters() {
if (didQueryParameters) {
//判断是否已经处理过了
return;
}
didQueryParameters = true;
......
processParameters(decodedQuery, queryStringCharset);
}
4. Adicione parâmetros a paramHashValues
Quando o programa for executado aqui, os parâmetros serão adicionados a paramHashValues
este map
, e quando os parâmetros forem obtidos, eles serão map
obtidos diretamente deste.
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. Solicitação de liberação
O código da requisição final irá para este local, e os parâmetros da requisição serão limpos aqui, e então será reutilizado para a próxima requisição.
O método é chamado de recycle, indicando que está reciclando, no qual os parâmetros de armazenamento do Map serão limpos e didQueryParameters será definido como false novamente.
public void recycle() {
parameterCount = 0;
paramHashValues.clear();
didQueryParameters = false;
charset = DEFAULT_BODY_CHARSET;
decodedQuery.recycle();
parseFailedReason = null;
}
Há indicações de que a solicitação é reciclada no tomcat.
Referência:
https://blog.csdn.net/JavaMonsterr/article/details/126033884