一 前言
本篇文章是再看了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)?这个没试验过,下次遇到了在更新此处。