在上一篇文章中,简单介绍了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做了进一步的封装,之后获取某个网页信息都可以如此使用,在之后的文章中,也就默认使用这里面的方法了。