descripción general
Si request
lo pasamos a un hilo asíncrono, es posible que no consigamos los parámetros, y provocará solicitudes posteriores, y habrá problemas al usar este hilo.
La razón es que request
los objetos se reutilizan.
Análisis de código fuente
1. Obtener parámetros
Veamos primero un método muy importante: getParameter
la primera vez que se llama al método, los parámetros se analizarán y luego ya no se analizarán.
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. Análisis de parámetros
Es este método el que realmente analiza los 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. Procese la cadena de consulta como un parámetro
/**
* 将查询字符串处理为参数
*/
public void handleQueryParameters() {
if (didQueryParameters) {
//判断是否已经处理过了
return;
}
didQueryParameters = true;
......
processParameters(decodedQuery, queryStringCharset);
}
4. Agregar parámetros a paramHashValues
Cuando el programa se ejecuta aquí, los parámetros se agregarán a paramHashValues
este map
, y cuando se obtienen los parámetros, se map
obtienen directamente de este.
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. Solicitud de liberación
El código de la solicitud final irá a este lugar, y los parámetros de la solicitud se borrarán aquí, y luego se reutilizará para la próxima solicitud.
El método se llama reciclar, lo que indica que está reciclando, en el que los parámetros de almacenamiento del mapa se borrarán y didQueryParameters se establecerá en falso nuevamente.
public void recycle() {
parameterCount = 0;
paramHashValues.clear();
didQueryParameters = false;
charset = DEFAULT_BODY_CHARSET;
decodedQuery.recycle();
parseFailedReason = null;
}
Hay indicaciones de que la solicitud se recicla en tomcat.
Referencia:
https://blog.csdn.net/JavaMonsterr/article/details/126033884