1. 程式人生 > >輕鬆把玩HttpAsyncClient之模擬post請求示例

輕鬆把玩HttpAsyncClient之模擬post請求示例

       如果看到過我前些天寫過的《輕鬆把玩HttpClient之模擬post請求示例》這篇文章,你再看本文就是小菜一碟了,如果你順便懂一些NIO,基本上是毫無壓力了。因為HttpAsyncClient相對於HttpClient,就多了一個NIO,這也是為什麼支援非同步的原因。

       不過我有一個疑問,雖說NIO是同步非阻塞IO,但是HttpAsyncClient提供了回撥的機制,這點兒跟netty很像,所以可以模擬類似於AIO的效果。但是官網上的例子卻基本上都是使用Future<HttpResponse> future = httpclient.execute(request, null);來同步獲得執行結果。

       好吧,反正我是用回撥的方式實現的。程式碼基本上跟httpClient那篇一致。不一樣的地方主要有這麼2個地方:配置ssl時不一樣;呼叫execute方式時,使用回撥。具體程式碼如下:

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();
	}
	
}
       來一個測試類:
	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工具類差不多。

       httpclientUtil (QQ交流群:548452686 httpclientUtil交流

相關推薦

輕鬆把玩HttpAsyncClient模擬post請求示例

       如果看到過我前些天寫過的《輕鬆把玩HttpClient之模擬post請求示例》這篇文章,你再看本文就是小菜一碟了,如果你順便懂一些NIO,基本上是毫無壓力了。因為HttpAsyncClient相對於HttpClient,就多了一個NIO,這也是為什麼支援非同步的

輕鬆把玩HttpClient模擬post請求示例

 HttpClient 是 Apache Jakarta Common 下的子專案,可以用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。當前官網最新版介紹頁是:http://hc.apache.org/

HttpClient4.xPost請求示例

Post操作相對於Get操作變化並不是很大,我們只是需要將原來的HttpGet改成HttpPost。不瞭解獲取提交操作的可以參看我的另一篇部落格HttpClient4.x之獲取請求示例  。但是如果需要進行表單提交,我們需要構造從表單相關操作。這裡httpClinet通過NameVal

輕鬆把玩HttpClient封裝HttpClient工具類(五),攜帶Cookie的請求

       最近更新了一下HttpClientUtil工具類程式碼,主要是添加了一個引數HttpContext,這個是用來幹嘛的呢?其實是用來儲存和傳遞Cookie所需要的。因為我們有很多時候都需要登

PostMan模擬Post請求模擬用戶登錄狀態

測試 .com cnblogs post請求 技術 head com post 調試 1.打開Chrome 登錄要測試的網站 2.打開開發者調試工具,點開NetWork,復制Cookie 3.將整段Cookie復制到PostMan的Headers裏 4.大功告成!可以開

apache bench(ab)壓力測試模擬POSt請求

使用 csharp light post數據 tro con nts 格式 not ab命令格式: -N|--count 總請求數,缺省 : 5w -C|--clients 並發數, 缺省 : 100 -R|--rounds 測試次數, 缺省 : 10 次 -S|-slee

接口自動化測試系列PHPUnit-POST請求接口測試方法

phpunit 小強測試品牌 測試幫日記 自動化測試 接口測試 post請求接口測試-加強通用版知道了get請求接口如何寫了,post就非常簡單了,基本上就是照貓畫虎即可,主要註意下參數,代碼如下:本文出自 “小強性能自動化測試品牌” 博客,請務必保留此出處http://xqtesting

httpclient模擬post請求json封裝表單數據

readline turn ast acc [] 選擇 encoding 效率 set 1 public static String httpPostWithJSON(String url) throws Exception { 2 3

Fiddler模擬POST請求

pri 模擬post clas 工具 url 技術分享 www water http 在進行接口測試時,會模擬post請求,發送不同的請求參數,返回不同的結果,今天我們就來分享一下,怎麽用Fiddler工具模擬post請求: 打開Fiddler工具,在右側點擊“compo

curl模擬post請求

time lan local admin amp hid .com gin nbsp curl -d "begin_time=2018-10-10 10:31:53&end_time=2018-10-13 10:31:53&worker_no=admin"

node總結GET/POST請求的傳送和接收了解下

在我們的現實場景中,我們的node伺服器都需要跟使用者的瀏覽器打交道,也就是說建立一個互動的關係。那麼,這個關係之間的通訊基本上比較熟悉的就是get/post這種方式了。咱們這刺激來簡單看下在node中,是如何接收和處理這些關係的。 由於GET請求直接被嵌入在路徑中,URL是完整的請求路徑,

http模擬post請求

public class HttpSender extends Thread{ private static final String COMPLEX_JSON_STR ="{\n" + " \"order\": {\n" + "

Java 和 HTTP 的那些事模擬 HTTP 請求

一、使用 HttpURLConnection 傳送 HTTP 請求 Java 自帶的 java.net 這個包中包含了很多與網路請求相關的類,但是對於我們來說,最關心的應該是 HttpURLConnection 這個類了。 1.1 建立 HTTP 連線物件 要得到一個 

輕鬆把玩HttpClient配置ssl,採用繞過證書驗證實現https

上篇文章說道httpclient不能直接訪問https的資源,這次就來模擬一下環境,然後配置https測試一下。在前面的文章中,分享了一篇自己生成並在tomcat中配置ssl的文章《Tomcat配置SSL》,大家可以據此來在本地配置https。我已經配置好了,效果是這樣滴:

java模擬post請求

HttpURLConnection模擬POST請求 public class HttpUtilTest { public String sendPost(String url, String Params) throws IOException {

輕鬆把玩HttpClient封裝HttpClient工具類(七),新增驗證碼識別功能

       這個HttpClientUtil工具類分享在GitHub上已經半年多的時間了,並且得到了不小的關注,有25顆star,被fork了38次。有了大家的鼓勵,工具類一直也在完善中。最近比較忙,兩個多月前的修改在今天剛修改測試完成,今天再次分享給大家。       驗

scrapy基礎知識傳送POST請求

可以使用 yield scrapy.FormRequest(url, formdata, callback)方法傳送POST請求。如果希望程式執行一開始就傳送POST請求,可以重寫Spider類的start_requests(self) 方法,並且不再呼叫start_url

python 爬蟲(三)模擬post請求,爬取資料

import urllib.request import urllib.parse url =r"http://www.baidu.com" #將要傳送的資料合成一個字典 #字典的鍵值在網頁裡找 data = { "username":"1507", "password":"230

輕鬆把玩HttpClient封裝HttpClient工具類(三),外掛式配置Header

       上篇文章介紹了外掛式配置HttpClient,本文將介紹外掛式配置Header。       為什麼要配置header在前面已經提到了,還裡再簡單說一下,要使用HttpClient模擬請求,去訪問各種介面或者網站資源,都有可能有各種限制,比如說java客戶端模擬

JAVA url型別的post請求示例

 /**   * 開放平臺介面的請求方法   * */  public static String readContentFromPost(String url,String requestCode,String platform, String params) throws IOException {