There is a problem with asynchronous threads using Request

overview

If we requestpass 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 requestobjects are reused.

Source code analysis

1. Get parameters

Let’s look at a very important method first. getParameterThe 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);

    }
}

insert image description here

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);
    }

insert image description here

4. Add parameters to paramHashValues

When the program executes here, the parameters will be added to paramHashValuesthis map, and when the parameters are obtained, they are directly mapobtained 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

Guess you like

Origin blog.csdn.net/qq_25775675/article/details/126973115