HttpClient使用与session的维持,connection pool shut down httpclient解决方案

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zyb2017/article/details/79362760

一 前言

本篇文章是再看了https://www.cnblogs.com/lixiuming521125/p/7058446.html之后写的,在原代码上重新写了一个方法实验,用到了原文中的地址

本篇目的为维持session的使用,用户的cookie携带,思路为首先请求index页面提示需要登录,改为请求login页面后,携带Referer,UA以及cookie重新请求index页面,返回正确页面信息

二 Pom

<dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
</dependency>
<dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.2</version>
</dependency>

三 测试

所有的步骤都有注释

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
 * TestLogin
 *
 * @author TransientBa
 * @date 2018/02/24
 */
public class TestLogin {
    /** 登陆 Url **/
    private static String LOGIN_URL = "http://139.196.40.80:3000/login";
    /** 需登陆后访问的 Url **/
    private static String DATA_URL = "http://139.196.40.80:3000/index";

    /**模拟请求index页面**/
    public static void toDataUrl() {
        //创建默认的HttpClients   CloseableHttpClient为HttpClient的实例  继承了HttpClient接口
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建get请求
        HttpGet get = new HttpGet(DATA_URL);
        //用来接收执行后的返回结果
        CloseableHttpResponse response = null;
        try{
            response = httpClient.execute(get);
            //如果响应不为空并且返回的状态码为200
            if(response != null && response.getStatusLine().getStatusCode() == 200){
                //接收报文实体
                HttpEntity entity =  response.getEntity();
                System.out.println(EntityUtils.toString(entity));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
           try{
               if (null != response) {
                   response.close();
               }
           }catch (IOException e){
               e.printStackTrace();
           }
        }
    }


    /**模拟请求login页面后携带cookie请求index   下面代码为上面链接中的原代码**/
    public static void showResponseBody(){
        HttpClient httpClient = new HttpClient();
        // 模拟登陆,按实际服务器端要求选用 Post 或 Get 请求方式
        PostMethod postMethod = new PostMethod(LOGIN_URL);

        // 设置登陆时要求的信息,用户名和密码
        NameValuePair[] data = { new NameValuePair("username", "lixiuming"),
                new NameValuePair("password", "lixiuming") };
        postMethod.setRequestBody(data);
        try {
            // 设置 HttpClient 接收 Cookie,用与浏览器一样的策略
            httpClient.getParams().setCookiePolicy(
                    CookiePolicy.BROWSER_COMPATIBILITY);
            httpClient.executeMethod(postMethod);
            // 获得登陆后的 Cookie
            Cookie[] cookies = httpClient.getState().getCookies();
            StringBuffer tmpcookies = new StringBuffer();
            for (Cookie c : cookies) {
                tmpcookies.append(c.toString() + ";");
            }
            //Get请求index页面
            GetMethod getMethod = new GetMethod(DATA_URL);
            //每次访问需授权的网址时需带上前面的 cookie 作为通行证
            getMethod.setRequestHeader("cookie", tmpcookies.toString());
            // 你还可以通过 PostMethod/GetMethod 设置更多的请求后数据
            // 例如,referer 从哪里来的,UA 像搜索引擎都会表名自己是谁,无良搜索引擎除外
            postMethod.setRequestHeader("Referer", LOGIN_URL);
            postMethod.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36");
            httpClient.executeMethod(getMethod);
            // 打印出返回数据,检验一下是否成功
            String text = getMethod.getResponseBodyAsString();
            System.out.println(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public static void main(String[] args) {
          toDataUrl();
//        showResponseBody();
    }
}

toDataUrl返回为需要登录,showResponseBody返回正常的index页面

四 维持session

对于session维持在其他前辈的博客里被很好的分成了两种
http://blog.csdn.net/qq_34601366/article/details/51672699

//第一种方式 httpclient保存于session,每次请求均为同一httpclient,httpclient维持cookies
//HttpClient client =(HttpClient) request.getSession().getAttribute("HTTPCLIENT");

//第二种方式 每次请求带入之前请求获取的cookies。
   HttpClient client=new HttpClient();
   client.getState().addCookies(cookies);

五 注意

在上面测试的代码并不完善,有两点需要注意

5.1 当压力过大时线程数超出规定报错

connection pool shut down httpclient

你的代码中可能使用了HttpResponse去接收execute的返回值,接收集并没有被释放导致掉,使用的线程数超过了创建时规定的setDefaultMaxPerRoute 数量,我们可以看下org.apache.http.impl.client包中HttpClientBuilder的源码
这里写图片描述
改为像以上代码用CloseableHttpResponse,CloseableHttpResponse继承了HttpResponse, Closeable,并在使用后对response进行close,

5.2 对于append的使用

  Cookie[] cookies = httpClient.getState().getCookies();
            StringBuffer tmpcookies = new StringBuffer();
            for (Cookie c : cookies) {
                tmpcookies.append(c.toString() + ";");
            }

文中为cookie,但我们经常会用StringBuffer去append返回实体,当返回实体ResponseBody大到一定程度的时,会不会发生超出读取长度的限制?是否可以改成new StringBuffer(ResponseBody)?这个没试验过,下次遇到了在更新此处。

猜你喜欢

转载自blog.csdn.net/zyb2017/article/details/79362760