使用HttpClinet保持session一致

来源:互联网 发布:java线程死锁是什么 编辑:程序博客网 时间:2024/06/16 22:54
我们在访问网路时,有时候会用到Android已经封装好的一个类——HttpClient,这个类就相当于一个小型的浏览器,集成了很多允许我们访问网络的方法,在普通的应用程序中,我们只需封装HttpRequest对象并传给HttpClient,使用HttpClient就可以访问网络了。如果请求的端口或者URL没有变化,可以采用单例模式来封装一个HttpClient。
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
         * 获得httpclient实例
         * @return
         */
        publicstatic synchronized HttpClient getHttpClient() {
 
                if(httpClient == null) {
                        HttpParams params = newBasicHttpParams();
                        // 设置一些基本参数
                        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                        HttpProtocolParams.setContentCharset(params, encoding);
                        HttpProtocolParams.setUseExpectContinue(params,true);
 
                        HttpProtocolParams
                                        .setUserAgent(
                                                        params,
                                                        "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
                                                                        +"AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");
                        // 超时设置
                        /* 从连接池中取连接的超时时间 */
                        ConnManagerParams.setTimeout(params, 1000);
                        /* 连接超时 */
                        HttpConnectionParams.setConnectionTimeout(params, 2000);
                        /* 请求超时 */
                        HttpConnectionParams.setSoTimeout(params,4000);
 
                        // 设置HttpClient支持HTTP和HTTPS两种模式
                        SchemeRegistry schReg = newSchemeRegistry();
                        schReg.register(newScheme("http", PlainSocketFactory
                                        .getSocketFactory(),80));
                        schReg.register(newScheme("https", SSLSocketFactory
                                        .getSocketFactory(),443));
 
                        // 使用线程安全的连接管理来创建HttpClient
                        ClientConnectionManager conMgr = newThreadSafeClientConnManager(
                                        params, schReg);
                        httpClient = newDefaultHttpClient(conMgr, params);
                }
                returnhttpClient;
        }

在需要调用的地方调用上面的方法,获得httpClient实例:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
publicstatic byte[] httpConnect(HttpRequest request) throwsException {
                HttpResponse response = null;
                if(request instanceofHttpGet) {
                         
                        HttpGet get = (HttpGet) request;
                        response = getHttpClient().execute(get);
 
                }elseif (request instanceofHttpPost) {
                        HttpPost post = (HttpPost) request;
                        response = getHttpClient().execute(post);
 
                }
                if(response != null
                                && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        HttpEntity resEntity = response.getEntity();
 
                        return(resEntity == null) ? null: EntityUtils
                                        .toByteArray(resEntity);
                }
                returnnull;
        }

这样就可以连接网络了。

但有些时候,情况会有些复杂,某些程序需要访问不同的端口,如果用单例模式,就需要手动的清除这个单例,在需要的地方再重新实例化,这样会造成程序上的混乱,而我们不用单例模式的话,每次访问网络是都一个新的httpClient对象,又会造成每次的session值不一致,服务器会认为你的多次请求并非在一次会话中,从而出现问题,打个比方:程序第一次请求服务器是进行登录功能,请求成功,服务器返回给response一个sessionid用作本次会话的标示,然而再下一次访问的时候,因为我们不用单例模式了,httpClient会重新实例化一个对象,这次请求的时候如果在request对象中没有sessionid的设置,那么服务器会认为这次请求和上次的请求不在一个会话中,造成错误。
我木有找到如何有效的在单例模式中关闭httpClient的方法,所以我的解决办法是手动的将每次的request请求保持一致
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
         * 获得httpclient实例
         *
         * @return
         */
        privatestatic synchronized HttpClient getHttpClient(HttpRequest request) {
 
                HttpParams params = newBasicHttpParams();
                // 设置一些基本参数
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setUseExpectContinue(params,true);
                HttpProtocolParams
                                .setUserAgent(
                                                params,
                                                "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
                                                                +"AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");
                // 超时设置
                /* 从连接池中取连接的超时时间 */
                ConnManagerParams.setTimeout(params, 1000 * 8);
                /* 连接超时 */
                HttpConnectionParams.setConnectionTimeout(params, 1000 * 10);
                /* 请求超时 */
                HttpConnectionParams.setSoTimeout(params,1000* 10);
 
                // 设置HttpClient支持HTTP和HTTPS两种模式
                SchemeRegistry schReg = newSchemeRegistry();
                schReg.register(newScheme("http", PlainSocketFactory
                                .getSocketFactory(), getHttpPort(request)));
                schReg.register(newScheme("https",
                                SSLSocketFactory.getSocketFactory(), getHttpPort(request)));
 
                // 使用线程安全的连接管理来创建HttpClient
                ClientConnectionManager conMgr = newThreadSafeClientConnManager(
                                params, schReg);
 
                returnnew DefaultHttpClient(conMgr, params);
 
        }

之后在调用处:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
         * 通过HttpRequest实例连接网络
         *
         * @param request
         *            网络请求,支持get和post<br>
         *            若为get方式,需要传入HttpGet实例,若为post方式,传入HttpPost实例
         * <a href="\"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a> 服务器的返回内容,这里将响应的内容处理为byte数组
         * @throws Exception
         */
        privatestatic byte[] httpConnect(HttpRequest request) throwsException {
//                Log.e("请求", CommonDefines.SESSIONID);
                HttpResponse response = null;
                if(CommonDefines.SESSIONID != null||CommonDefines.SESSIONID!="") {
                        //设置sessionid,把第一次请求的id放在之后要请求的request报文头里
                        request.setHeader("Cookie", CommonDefines.SESSIONID);
                         
                }
                if(request instanceofHttpGet) {
                        HttpGet get = (HttpGet) request;
                        response = getHttpClient(request).execute(get);
 
                }elseif (request instanceofHttpPost) {
                        HttpPost post = (HttpPost) request;
                        response = getHttpClient(request).execute(post);
 
                }
                if(response != null
                                && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        HttpEntity resEntity = response.getEntity();
                        Header[] headers = response.getHeaders("set-cookie");
                        //保存服务器返回的session
                        for(inti = 0; i < headers.length; i++) {
//                                Log.e("sessionid", headers<i>.getValue());
                                String value = headers<i>.getValue();
                                CommonDefines.SESSIONID = value
                                                .substring(0, value.indexOf(";"));
                        }
 
                        return(resEntity == null) ? null: EntityUtils
                                        .toByteArray(resEntity);
                }
                returnnull;
        }</i></i>

OK,这样就解决了在httpClient中保持session一致的问题了。
原创粉丝点击