HttpClient和HttpGet 引數的優先順序

zhanlijun發表於2013-09-01

http://www.cnblogs.com/LBSer/p/3295584.html

一般在使用HttpClient時,我們提前設定好引數,比如超時時間(一般socket超時和連線超時)

private DefaultHttpClient createHttpClient() { //程式碼1
        ThreadSafeClientConnManager connectMag = new ThreadSafeClientConnManager();
        ...
        client = new DefaultHttpClient(connectMag);
        client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
                "...");
        client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
                2000);
        client.getParams().setIntParameter(
                CoreConnectionPNames.CONNECTION_TIMEOUT, 1000);
        return client;
    }

但是我們也可以通過HttpUriRequest來設定引數,比如HttpGet、HttpPost。

httpGet.getParams().setIntParameter(
                    CoreConnectionPNames.SO_TIMEOUT, 5000);
            httpGet.getParams().setIntParameter(
                    CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.execute(httpGet, new BasicResponseHandler());

 

 

這裡的問題是:當我們既在HttlClent設定了超時時間,又在HttpGet設定了超時時間,那麼到底以哪個設定為準?

仔細檢視程式碼,發現httpclient.execute最終呼叫了以下程式碼,建立了RequestDirector director,在建立director中通過determineParams(request))函式設定了引數。

 

public final HttpResponse execute(HttpHost target, HttpRequest request,
                                      HttpContext context)
        throws IOException, ClientProtocolException {

        if (request == null) {
            throw new IllegalArgumentException
                ("Request must not be null.");
        }
        // a null target may be acceptable, this depends on the route planner
        // a null context is acceptable, default context created below

        HttpContext execContext = null;
        RequestDirector director = null;

        // Initialize the request execution context making copies of
        // all shared objects that are potentially threading unsafe.
        synchronized (this) {

            HttpContext defaultContext = createHttpContext();
            if (context == null) {
                execContext = defaultContext;
            } else {
                execContext = new DefaultedHttpContext(context, defaultContext);
            }
            // Create a director for this request
            director = createClientRequestDirector(
                    getRequestExecutor(),
                    getConnectionManager(),
                    getConnectionReuseStrategy(),
                    getConnectionKeepAliveStrategy(),
                    getRoutePlanner(),
                    getProtocolProcessor(),
                    getHttpRequestRetryHandler(),
                    getRedirectStrategy(),
                    getTargetAuthenticationHandler(),
                    getProxyAuthenticationHandler(),
                    getUserTokenHandler(),
                    determineParams(request)); //設定了引數
        }

        try {
            return director.execute(target, request, execContext);
        } catch(HttpException httpException) {
            throw new ClientProtocolException(httpException);
        }
    }

 

 

那determineParams(request))函式幹了什麼呢?其實是建立了個HttpParams,也就是ClientParamsStack(ClientParamsStack extends AbstractHttpParams,而AbstractHttpParams implements HttpParams)。

ClientParamsStack拿來幹什麼用的呢?Represents a stack of parameter collections. When retrieving a parameter, the stack is searched in a fixed order and the first match returned. Setting parameters via the stack is not supported. To minimize overhead, the stack has a fixed size and does not maintain an internal array. The supported stack entries, sorted by increasing priority (摘自:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/ClientParamsStack.html)

 

上面大意是:ClientParamsStack是個引數棧,這個引數棧裡有四個引數,引數優先順序是越來越高的,i.e. applicationParams < clientParams < requestParams < overrideParams,從這裡可以看出requestParams優先順序比clientParams高(在本例中,requestParams是從HttpGet設定的,而clientParams是HttpClient設定的),也就是說當HttpGet和HttpClient同時設定了超時時,以HttpGet設定的為準!

 

protected HttpParams determineParams(HttpRequest req) {
        return new ClientParamsStack
            (null, getParams(), req.getParams(), null);
    }

 

 

 

public ClientParamsStack(HttpParams aparams, HttpParams cparams,
                             HttpParams rparams, HttpParams oparams) {
        applicationParams = aparams;
        clientParams      = cparams;
        requestParams     = rparams;
        overrideParams    = oparams;
    }

 

 

既然各個引數有優先順序,那麼優先順序是如何實現的呢?其實原理很簡單,也就是按overrideParams、requestParams、clientParams、applicationParams的順序依次判斷,如果不為空就返回。(注:getParameter()函式經常被底層實現用到)

 

public Object getParameter(String name) {
        if (name == null) {
            throw new IllegalArgumentException
                ("Parameter name must not be null.");
        }

        Object result = null;

        if (overrideParams != null) {
            result = overrideParams.getParameter(name);
        }
        if ((result == null) && (requestParams != null)) {
            result = requestParams.getParameter(name);
        }
        if ((result == null) && (clientParams != null)) {
            result = clientParams.getParameter(name);
        }
        if ((result == null) && (applicationParams != null)) {
            result = applicationParams.getParameter(name);
        }
        return result;
    }



 

相關文章