在上一篇文章中,简单介绍了httpclient的最基本的使用方式,并且通过httpclient获取里百度首页的页面信息,但是有没有发现一个问题,这么简单的一个操作,却写了不少的代码!程序员其实都挺懒的,这么不优雅的编程方式肯定受不了啊,那现在,我们再定一个小目标,我们将对httpclient进一步封装,封装完成之后,希望最好通过一行代码就能获取某个网页的信息!
既然要封装,那首先需要建一个class,就取名叫MyHttpClient吧,这里面需要两个方法,分别是以get、post方式获取网页信息,信息以字符串的形式返回,我们先来搭好框架,代码如下所示:
public class MyHttpClient {
public MyHttpClient() {
}
/**
* 以get的方式请求网页
*
* @param url 网址
* @param charset 编码
* @param headers 请求头
* @return 网页信息
* @throws Exception
*/
public synchronized static String get(String url, String charset, Map<String, String> headers) throws Exception {
return "";
}
/**
* 以post的方式请求网页
*
* @param url 网址
* @param charset 编码
* @param headers 请求头
* @return 网页信息
* @throws Exception
*/
public synchronized static String post(String url, String charset, Map<String, String> headers) throws Exception {
return "";
}
}
接下来,需要稍微讲解一下httpclient是如何管理连接的,通过阅读源代码,发现它在执行请求的时候,是委托给了ConnectionManager去创建连接的,ConnectionManager有多个子类,在这里,我们就使用MultiThreadedHttpConnectionManager去管理连接,MultiThreadedHttpConnectionManager使用了连接池的思想,在性能和资源消耗等方面都比较好。由于MultiThreadedHttpConnectionManager管理器一般只需设置一次即可,所以可以将其写成static的,代码如下:
private static MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
static {
//超时
Integer MAX_TIME_OUT = 5000;
//最大连接数
Integer MAX_CONN = 5000;
connectionManager.closeIdleConnections(MAX_TIME_OUT);
connectionManager.getParams().setParameter("http.connection-manager.max-total", MAX_CONN);
}
最后,就可以将上一篇文章中的代码稍作修改,填入MyHttpClient中的get和post方法中了,完整代码如下所示:
public class MyHttpClient {
public MyHttpClient() {
}
private static MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
static {
//超时
Integer MAX_TIME_OUT = 5000;
//最大连接数
Integer MAX_CONN = 5000;
connectionManager.closeIdleConnections(MAX_TIME_OUT);
connectionManager.getParams().setParameter("http.connection-manager.max-total", MAX_CONN);
}
/**
* 以get的方式请求网页
*
* @param url 网址
* @param charset 编码
* @param headers 请求头
* @return 网页信息
* @throws Exception
*/
public synchronized static String get(String url, String charset, Map<String, String> headers) throws Exception {
//使用connectionManager实例化HttpClient
HttpClient httpClient = new HttpClient(connectionManager);
//按照指定编码去请求网页
httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charset);
//以GET的方式获取数据
HttpMethod method = new GetMethod(url);
//设置请求头
if (headers != null) {
Set<String> keys = headers.keySet();
for (String k : keys) {
method.setRequestHeader(k, headers.get(k));
}
}
//执行,发送请求
httpClient.executeMethod(method);
//页面内容
String result = method.getResponseBodyAsString();
//释放连接
method.releaseConnection();
return result;
}
/**
* 以post的方式请求网页
*
* @param url 网址
* @param charset 编码
* @param headers 请求头
* @return 网页信息
* @throws Exception
*/
public synchronized static String post(String url, String charset, Map<String, String> headers) throws Exception {
//使用connectionManager实例化HttpClient
HttpClient httpClient = new HttpClient(connectionManager);
//按照指定编码去请求网页
httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charset);
//以GET的方式获取数据
HttpMethod method = new PostMethod(url);
//设置请求头
if (headers != null) {
Set<String> keys = headers.keySet();
for (String k : keys) {
method.setRequestHeader(k, headers.get(k));
}
}
//执行,发送请求
httpClient.executeMethod(method);
//页面内容
String result = method.getResponseBodyAsString();
//释放连接
method.releaseConnection();
return result;
}
}
最后,来使用一下,过程就相当简单了,还是以获取百度首页的信息为例,其核心的代码其实就只有一行而已,具体的代码如下所示:
public static void main(String[] args) throws Exception {
//需要获取数据的url
String url = "https://www.baidu.com";
//指定编码
String charset = "utf-8";
//设置请求头
Map<String, String> headers = new HashMap<>();
headers.put("Host", "www.baidu.com");
headers.put("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/66.0.3359.181 Safari/537.36");
//调用封装好的方法,请求网页,仅仅这一行是核心代码
String html = MyHttpClient.get(url, charset, headers);
System.out.println(html);
}
至此,我们就将httpclient做了进一步的封装,之后获取某个网页信息都可以如此使用,在之后的文章中,也就默认使用这里面的方法了。