? ? ?版權聲明:本文為博主原創文章,未經博主允許不得轉載。如需轉載請聲明:【轉自 http://blog.csdn.net/xiaoxian8023 】
? ? ?在寫這個工具類的時候發現傳入的參數太多,以至于方法泛濫,只一個send方法就有30多個,所以對工具類進行了優化,把輸入參數封裝在一個對象里,這樣以后再擴展輸入參數,直接修改這個類就ok了。
? ? ?不多說了,先上代碼:
~~~
/**
* 請求配置類
*
* @author arron
* @date 2016年2月2日 下午3:14:32
* @version 1.0
*/
public class HttpConfig {
private HttpConfig(){};
/**
* 獲取實例
* @return
*/
public static HttpConfig custom(){
return new HttpConfig();
}
/**
* HttpClient對象
*/
private HttpClient client;
/**
* CloseableHttpAsyncClient對象
*/
private CloseableHttpAsyncClient asynclient;
/**
* 資源url
*/
private String url;
/**
* Header頭信息
*/
private Header[] headers;
/**
* 請求方法
*/
private HttpMethods method=HttpMethods.GET;
/**
* 請求方法名稱
*/
private String methodName;
/**
* 用于cookie操作
*/
private HttpContext context;
/**
* 傳遞參數
*/
private Map<String, Object> map;
/**
* 輸入輸出編碼
*/
private String encoding=Charset.defaultCharset().displayName();
/**
* 輸入編碼
*/
private String inenc;
/**
* 輸出編碼
*/
private String outenc;
/**
* 輸出流對象
*/
private OutputStream out;
/**
* 異步操作回調執行器
*/
private IHandler handler;
/**
* HttpClient對象
*/
public HttpConfig client(HttpClient client) {
this.client = client;
return this;
}
/**
* CloseableHttpAsyncClient對象
*/
public HttpConfig asynclient(CloseableHttpAsyncClient asynclient) {
this.asynclient = asynclient;
return this;
}
/**
* 資源url
*/
public HttpConfig url(String url) {
this.url = url;
return this;
}
/**
* Header頭信息
*/
public HttpConfig headers(Header[] headers) {
this.headers = headers;
return this;
}
/**
* 請求方法
*/
public HttpConfig method(HttpMethods method) {
this.method = method;
return this;
}
/**
* 請求方法
*/
public HttpConfig methodName(String methodName) {
this.methodName = methodName;
return this;
}
/**
* cookie操作相關
*/
public HttpConfig context(HttpContext context) {
this.context = context;
return this;
}
/**
* 傳遞參數
*/
public HttpConfig map(Map<String, Object> map) {
this.map = map;
return this;
}
/**
* 輸入輸出編碼
*/
public HttpConfig encoding(String encoding) {
//設置輸入輸出
inenc(encoding);
outenc(encoding);
this.encoding = encoding;
return this;
}
/**
* 輸入編碼
*/
public HttpConfig inenc(String inenc) {
this.inenc = inenc;
return this;
}
/**
* 輸出編碼
*/
public HttpConfig outenc(String outenc) {
this.outenc = outenc;
return this;
}
/**
* 輸出流對象
*/
public HttpConfig out(OutputStream out) {
this.out = out;
return this;
}
/**
* 異步操作回調執行器
*/
public HttpConfig handler(IHandler handler) {
this.handler = handler;
return this;
}
public HttpClient client() {
return client;
}
public CloseableHttpAsyncClient asynclient() {
return asynclient;
}
public Header[] headers() {
return headers;
}
public String url() {
return url;
}
public HttpMethods method() {
return method;
}
public String methodName() {
return methodName;
}
public HttpContext context() {
return context;
}
public Map<String, Object> map() {
return map;
}
public String encoding() {
return encoding;
}
public String inenc() {
return inenc == null ? encoding : inenc;
}
public String outenc() {
return outenc == null ? encoding : outenc;
}
public OutputStream out() {
return out;
}
public IHandler handler() {
return handler;
}
}
~~~
? ? ?將構造方法設置為private,然后提供一個custom()方法來獲取新的實例,所有的set方法,都是返回HttpConfig,這樣就支持鏈式調用(創建者模式)了。
? ? ?工具類的核心方法如下:
~~~
/**
* 請求資源或服務
*
* @param config
* @return
* @throws HttpProcessException
*/
public static String send(HttpConfig config) throws HttpProcessException {
return fmt2String(execute(config), config.outenc());
}
/**
* 請求資源或服務
*
* @param client client對象
* @param url 資源地址
* @param httpMethod 請求方法
* @param parasMap 請求參數
* @param headers 請求頭信息
* @param encoding 編碼
* @return 返回處理結果
* @throws HttpProcessException
*/
private static HttpResponse execute(HttpConfig config) throws HttpProcessException {
if(config.client()==null){//檢測是否設置了client
config.client(create(config.url()));
}
HttpResponse resp = null;
try {
//創建請求對象
HttpRequestBase request = getRequest(config.url(), config.method());
//設置header信息
request.setHeaders(config.headers());
//判斷是否支持設置entity(僅HttpPost、HttpPut、HttpPatch支持)
if(HttpEntityEnclosingRequestBase.class.isAssignableFrom(request.getClass())){
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
//檢測url中是否存在參數
config.url(Utils.checkHasParas(config.url(), nvps, config.inenc()));
//裝填參數
HttpEntity entity = Utils.map2List(nvps, config.map(), config.inenc());
//設置參數到請求對象中
((HttpEntityEnclosingRequestBase)request).setEntity(entity);
logger.info("請求地址:"+config.url());
if(nvps.size()>0){
logger.info("請求參數:"+nvps.toString());
}
}else{
int idx = config.url().indexOf("?");
logger.info("請求地址:"+config.url().substring(0, (idx>0 ? idx : config.url().length())));
if(idx>0){
logger.info("請求參數:"+config.url().substring(idx+1));
}
}
//執行請求操作,并拿到結果(同步阻塞)
resp = (config.context()==null)?config.client().execute(request) : config.client().execute(request, config.context()) ;
//獲取結果實體
return resp;
} catch (IOException e) {
throw new HttpProcessException(e);
}
}
//-----------華----麗----分----割----線--------------
//-----------華----麗----分----割----線--------------
//-----------華----麗----分----割----線--------------
/**
* 轉化為字符串
*
* @param entity 實體
* @param encoding 編碼
* @return
* @throws HttpProcessException
*/
public static String fmt2String(HttpResponse resp, String encoding) throws HttpProcessException {
String body = "";
try {
if (resp.getEntity() != null) {
// 按指定編碼轉換結果實體為String類型
body = EntityUtils.toString(resp.getEntity(), encoding);
logger.debug(body);
}
EntityUtils.consume(resp.getEntity());
} catch (ParseException | IOException e) {
throw new HttpProcessException(e);
}finally{
close(resp);
}
return body;
}
/**
* 轉化為流
*
* @param entity 實體
* @param out 輸出流
* @return
* @throws HttpProcessException
*/
public static OutputStream fmt2Stream(HttpResponse resp, OutputStream out) throws HttpProcessException {
try {
resp.getEntity().writeTo(out);
EntityUtils.consume(resp.getEntity());
} catch (ParseException | IOException e) {
throw new HttpProcessException(e);
}finally{
close(resp);
}
return out;
}
~~~
? ? ?再附上測試代碼:
~~~
public static void testOne() throws HttpProcessException{
System.out.println("--------簡單方式調用(默認post)--------");
String url = "http://tool.oschina.net/";
HttpConfig config = HttpConfig.custom();
//簡單調用
String resp = HttpClientUtil.get(config.url(url));
System.out.println("請求結果內容長度:"+ resp.length());
System.out.println("\n#################################\n");
System.out.println("--------加入header設置--------");
url="http://blog.csdn.net/xiaoxian8023";
//設置header信息
Header[] headers=HttpHeader.custom().userAgent("Mozilla/5.0").build();
//執行請求
resp = HttpClientUtil.get(config.headers(headers));
System.out.println("請求結果內容長度:"+ resp.length());
System.out.println("\n#################################\n");
System.out.println("--------代理設置(繞過證書驗證)-------");
url="https://www.facebook.com/";
HttpClient client= HCB.custom().timeout(10000).proxy("127.0.0.1", 8087).ssl().build();//采用默認方式(繞過證書驗證)
//執行請求
resp = HttpClientUtil.get(config.client(client));
System.out.println("請求結果內容長度:"+ resp.length());
System.out.println("\n#################################\n");
// System.out.println("--------代理設置(自簽名證書驗證)+header+get方式-------");
// url = "https://sso.tgb.com:8443/cas/login";
// client= HCB.custom().timeout(10000).ssl("D:\\keys\\wsriakey","tomcat").build();
// headers=HttpHeader.custom().keepAlive("false").connection("close").contentType(Headers.APP_FORM_URLENCODED).build();
// //執行請求
// resp = CopyOfHttpClientUtil.get(config.method(HttpMethods.GET));
// System.out.println("請求結果內容長度:"+ resp.length());
try {
System.out.println("--------下載測試-------");
url="http://ss.bdimg.com/static/superman/img/logo/logo_white_fe6da1ec.png";
FileOutputStream out = new FileOutputStream(new File("d://aaa//000.png"));
HttpClientUtil.down(HttpConfig.custom().url(url).out(out));
out.flush();
out.close();
System.out.println("--------下載測試+代理-------");
out = new FileOutputStream(new File("d://aaa//001.png"));
HttpClientUtil.down(HttpConfig.custom().client(client).url(url).out(out));
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("\n#################################\n");
}
~~~
? ? ?可以看到這樣調用會更顯得清晰明了。以后再添加功能時,改起來也會比較方便了。工具類也提供了輸出流的功能,可以用于下載文件或者加載驗證碼圖片,非常方便。
? ? ?最新的完整代碼請到GitHub上進行下載:https://github.com/Arronlong/httpclientUtil 。
- 前言
- HttpClient3.x之Get請求和Post請求示例
- httpclient3.x中使用HTTPS的方法
- 簡單的利用UrlConnection,后臺模擬http請求
- 輕松把玩HttpClient之模擬post請求示例
- 輕松把玩HttpClient之配置ssl,采用繞過證書驗證實現https
- 輕松把玩HttpClient之配置ssl,采用設置信任自簽名證書實現https
- 輕松把玩HttpClient之設置代理,可以訪問FaceBook
- 輕松把玩HttpClient之封裝HttpClient工具類(一)(現有網上分享中的最強大的工具類)
- 輕松把玩HttpClient之封裝HttpClient工具類(二),插件式配置HttpClient對象
- 輕松把玩HttpClient之封裝HttpClient工具類(三),插件式配置Header
- 輕松把玩HttpClient之封裝HttpClient工具類(四),單線程調用及多線程批量調用測試
- 輕松把玩HttpAsyncClient之模擬post請求示例
- 輕松把玩HttpClient之封裝HttpClient工具類(五),攜帶Cookie的請求
- 輕松把玩HttpClient之封裝HttpClient工具類(六),封裝輸入參數,簡化工具類