您的位置:首页 > 理论基础 > 计算机网络

轻松把玩HttpAsyncClient之模拟post请求示例

2016-08-22 14:14 507 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载请声明:【转自 http://blog.csdn.net/xiaoxian8023

如果看到过我前些天写过的《轻松把玩HttpClient之模拟post请求示例》这篇文章,你再看本文就是小菜一碟了,如果你顺便懂一些NIO,基本上是毫无压力了。因为HttpAsyncClient相对于HttpClient,就多了一个NIO,这也是为什么支持异步的原因。

不过我有一个疑问,虽说NIO是同步非阻塞IO,但是HttpAsyncClient提供了回调的机制,这点儿跟netty很像,所以可以模拟类似于AIO的效果。但是官网上的例子却基本上都是使用Future<HttpResponse>
future = httpclient.execute(request, null);来同步获得执行结果。

好吧,反正我是用回调的方式实现的。代码基本上跟httpClient那篇一致。不一样的地方主要有这么2个地方:配置ssl时不一样;调用execute方式时,使用回调。具体代码如下:

[java] view
plain copy

print?

package com.tgb.ccl.http.simpledemo;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.Reader;

import java.security.KeyManagementException;

import java.security.KeyStore;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import java.security.cert.CertificateException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;

import org.apache.http.HttpHost;

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.ParseException;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.concurrent.FutureCallback;

import org.apache.http.config.Registry;

import org.apache.http.config.RegistryBuilder;

import org.apache.http.conn.ssl.TrustSelfSignedStrategy;

import org.apache.http.impl.conn.DefaultProxyRoutePlanner;

import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;

import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;

import org.apache.http.impl.nio.client.HttpAsyncClients;

import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;

import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;

import org.apache.http.impl.nio.reactor.IOReactorConfig;

import org.apache.http.message.BasicNameValuePair;

import org.apache.http.nio.conn.NoopIOSessionStrategy;

import org.apache.http.nio.conn.SchemeIOSessionStrategy;

import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import org.apache.http.nio.reactor.ConnectingIOReactor;

import org.apache.http.ssl.SSLContexts;

import org.apache.http.util.EntityUtils;

/**

* HttpAsyncClient模拟post请求简单示例

*

* @author arron

* @date 2015年11月1日 下午2:23:18

* @version 1.0

*/

public class SimpleHttpAsyncClientDemo {

/**

* 设置信任自定义的证书

*

* @param keyStorePath 密钥库路径

* @param keyStorepass 密钥库密码

* @return

*/

public static SSLContext custom(String keyStorePath, String keyStorepass) {

SSLContext sc = null;

FileInputStream instream = null;

KeyStore trustStore = null;

try {

trustStore = KeyStore.getInstance(KeyStore.getDefaultType());

instream = new FileInputStream(new File(keyStorePath));

trustStore.load(instream, keyStorepass.toCharArray());

// 相信自己的CA和所有自签名的证书

sc = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();

} catch (KeyStoreException | NoSuchAlgorithmException| CertificateException | IOException | KeyManagementException e) {

e.printStackTrace();

} finally {

try {

instream.close();

} catch (IOException e) {

}

}

return sc;

}

/**

* 绕过验证

*

* @return

* @throws NoSuchAlgorithmException

* @throws KeyManagementException

*/

public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {

SSLContext sc = SSLContext.getInstance("SSLv3");

// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法

X509TrustManager trustManager = new X509TrustManager() {

@Override

public void checkClientTrusted(

java.security.cert.X509Certificate[] paramArrayOfX509Certificate,

String paramString) throws CertificateException {

}

@Override

public void checkServerTrusted(

java.security.cert.X509Certificate[] paramArrayOfX509Certificate,

String paramString) throws CertificateException {

}

@Override

public java.security.cert.X509Certificate[] getAcceptedIssuers() {

return null;

}

};

sc.init(null, new TrustManager[] { trustManager }, null);

return sc;

}

/**

* 设置代理

* @param builder

* @param hostOrIP

* @param port

*/

public static HttpAsyncClientBuilder proxy(String hostOrIP, int port){

// 依次是代理地址,代理端口号,协议类型

HttpHost proxy = new HttpHost(hostOrIP, port, "http");

DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);

return HttpAsyncClients.custom().setRoutePlanner(routePlanner);

}

/**

* 模拟请求

*

* @param url 资源地址

* @param map 参数列表

* @param encoding 编码

* @param handler 结果处理类

* @return

* @throws NoSuchAlgorithmException

* @throws KeyManagementException

* @throws IOException

* @throws ClientProtocolException

*/

public static void send(String url, Map<String,String> map,final String encoding, final AsyncHandler handler) throws KeyManagementException, NoSuchAlgorithmException, ClientProtocolException, IOException {

//绕过证书验证,处理https请求

SSLContext sslcontext = createIgnoreVerifySSL();

// 设置协议http和https对应的处理socket链接工厂的对象

Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()

.register("http", NoopIOSessionStrategy.INSTANCE)

.register("https", new SSLIOSessionStrategy(sslcontext))

.build();

//配置io线程

IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setIoThreadCount(Runtime.getRuntime().availableProcessors()).build();

//设置连接池大小

ConnectingIOReactor ioReactor;

ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);

PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor, null, sessionStrategyRegistry, null);

//创建自定义的httpclient对象

final CloseableHttpAsyncClient client = proxy("127.0.0.1", 8087).setConnectionManager(connManager).build();

// CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();

//创建post方式请求对象

HttpPost httpPost = new HttpPost(url);

//装填参数

List<NameValuePair> nvps = new ArrayList<NameValuePair>();

if(map!=null){

for (Entry<String, String> entry : map.entrySet()) {

nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));

}

}

//设置参数到请求对象中

httpPost.setEntity(new UrlEncodedFormEntity(nvps, encoding));

System.out.println("请求地址:"+url);

System.out.println("请求参数:"+nvps.toString());

//设置header信息

//指定报文头【Content-type】、【User-Agent】

httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");

httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

// Start the client

client.start();

//执行请求操作,并拿到结果(异步)

client.execute(httpPost, new FutureCallback<HttpResponse>() {

@Override

public void failed(Exception ex) {

handler.failed(ex);

close(client);

}

@Override

public void completed(HttpResponse resp) {

String body="";

//这里使用EntityUtils.toString()方式时会大概率报错,原因:未接受完毕,链接已关

try {

HttpEntity entity = resp.getEntity();

if (entity != null) {

final InputStream instream = entity.getContent();

try {

final StringBuilder sb = new StringBuilder();

final char[] tmp = new char[1024];

final Reader reader = new InputStreamReader(instream,encoding);

int l;

while ((l = reader.read(tmp)) != -1) {

sb.append(tmp, 0, l);

}

body = sb.toString();

} finally {

instream.close();

EntityUtils.consume(entity);

}

}

} catch (ParseException | IOException e) {

e.printStackTrace();

}

handler.completed(body);

close(client);

}

@Override

public void cancelled() {

handler.cancelled();

close(client);

}

});

}

/**

* 关闭client对象

*

* @param client

*/

private static void close(CloseableHttpAsyncClient client) {

try {

client.close();

} catch (IOException e) {

e.printStackTrace();

}

}

static class AsyncHandler implements IHandler{

@Override

public Object failed(Exception e) {

System.err.println(Thread.currentThread().getName()+"--失败了--"+e.getClass().getName()+"--"+e.getMessage());

return null;

}

@Override

public Object completed(String respBody) {

System.out.println(Thread.currentThread().getName()+"--获取内容:"+respBody);

return null;

}

@Override

public Object cancelled() {

System.out.println(Thread.currentThread().getName()+"--取消了");

return null;

}

}

/**

* 回调处理接口

*

* @author arron

* @date 2015年11月10日 上午10:05:40

* @version 1.0

*/

public interface IHandler {

/**

* 处理异常时,执行该方法

* @return

*/

Object failed(Exception e);

/**

* 处理正常时,执行该方法

* @return

*/

Object completed(String respBody);

/**

* 处理取消时,执行该方法

* @return

*/

Object cancelled();

}

}

来一个测试类:

[java] view
plain copy

print?

public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, ClientProtocolException, IOException {

AsyncHandler handler = new AsyncHandler();

String url = "http://php.weather.sina.com.cn/iframe/index/w_cl.php";

Map<String, String> map = new HashMap<String, String>();

map.put("code", "js");

map.put("day", "0");

map.put("city", "上海");

map.put("dfc", "1");

map.put("charset", "utf-8");

send(url, map, "utf-8", handler);

System.out.println("-----------------------------------");

map.put("city", "北京");

send(url, map, "utf-8", handler);

System.out.println("-----------------------------------");

}

测试结果如下:



很简单吧,其实基于HttpAsyncClient的工具类我也进行了封装,跟HttpClient工具类差不多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: