Http協議的重要性相信不用我多說了,HttpClient相比傳統JDK自帶的URLConnection,增加了易用性和靈活性(具體區別,日后我們再討論),它不僅是客戶端發送Http請求變得容易,而且也方便了開發人員測試接口(基於Http協議的),即提高了開發的效率,也方便提高代碼的健壯性。因此熟練掌握HttpClient是很重要的必修內容,掌握HttpClient后,相信對於Http協議的了解會更加深入。
org.apache.commons.httpclient.HttpClient與org.apache.http.client.HttpClient的區別
Commons的HttpClient項目現在是生命的盡頭,不再被開發,
已被Apache HttpComponents項目HttpClient和的HttpCore
模組取代,提供更好的性能和更大的靈活性。
一、簡介
HttpClient是Apache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包,並且它支持HTTP協議最新的版本和建議。HttpClient已經應用在很多的項目中,比如Apache Jakarta上很著名的另外兩個開源項目Cactus和HTMLUnit都使用了HttpClient。
下載地址: http://hc.apache.org/downloads.cgi
二、特性
1. 基於標准、純凈的java語言。實現了Http1.0和Http1.1
2. 以可擴展的面向對象的結構實現了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
3. 支持HTTPS協議。
4. 通過Http代理建立透明的連接。
5. 利用CONNECT方法通過Http代理建立隧道的https連接。
6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos認證方案。
7. 插件式的自定義認證方案。
8. 便攜可靠的套接字工廠使它更容易的使用第三方解決方案。
9. 連接管理器支持多線程應用。支持設置最大連接數,同時支持設置每個主機的最大連接數,發現並關閉過期的連接。
10. 自動處理Set-Cookie中的Cookie。
11. 插件式的自定義Cookie策略。
12. Request的輸出流可以避免流中內容直接緩沖到socket服務器。
13. Response的輸入流可以有效的從socket服務器直接讀取相應內容。
14. 在http1.0和http1.1中利用KeepAlive保持持久連接。
15. 直接獲取服務器發送的response code和 headers。
16. 設置連接超時的能力。
17. 實驗性的支持http1.1 response caching。
18. 源代碼基於Apache License 可免費獲取。
三、使用方法
使用HttpClient發送請求、接收響應很簡單,一般需要如下幾步即可。
1. 創建HttpClient對象。
2. 創建請求方法的實例,並指定請求URL。如果需要發送GET請求,創建HttpGet對象;如果需要發送POST請求,創建HttpPost對象。
3. 如果需要發送請求參數,可調用HttpGet、HttpPost共同的setParams(HetpParams params)方法來添加請求參數;對於HttpPost對象而言,也可調用setEntity(HttpEntity entity)方法來設置請求參數。
4. 調用HttpClient對象的execute(HttpUriRequest request)發送請求,該方法返回一個HttpResponse。
5. 調用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;調用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。
6. 釋放連接。無論執行方法是否成功,都必須釋放連接
相關jar包
commons-cli-1.2.jar commons-codec-1.9.jar commons-logging-1.2.jar fluent-hc-4.5.1.jar httpclient-4.5.1.jar httpclient-cache-4.5.1.jar httpclient-win-4.5.1.jar httpcore-4.4.3.jar httpcore-ab-4.4.3.jar httpcore-nio-4.4.3.jar httpmime-4.5.1.jar jna-4.1.0.jar jna-platform-4.1.0.jar
最簡單post請求, 源自 http://my.oschina.net/xinxingegeya/blog/282683
package a; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; public class First { public static void main(String[] args) throws Exception{ List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("account", "")); formparams.add(new BasicNameValuePair("password", "")); HttpEntity reqEntity = new UrlEncodedFormEntity(formparams, "utf-8"); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000)//一、連接超時:connectionTimeout-->指的是連接一個url的連接等待時間 .setSocketTimeout(5000)// 二、讀取數據超時:SocketTimeout-->指的是連接上一個url,獲取response的返回等待時間 .setConnectionRequestTimeout(5000) .build(); HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("http://cnivi.com.cn/login"); post.setEntity(reqEntity); post.setConfig(requestConfig); HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity resEntity = response.getEntity(); String message = EntityUtils.toString(resEntity, "utf-8"); System.out.println(message); } else { System.out.println("請求失敗"); } } }
四、實例
主文件
package com.test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; 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.List; import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; 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.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.apache.http.client.config.RequestConfig; import org.junit.Test; public class HttpClientTest { //方法見下........ }
HttpClientUtils工具類
package com.bobo.code.web.controller.technology.httpcomponents; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.util.*; public class HttpClientUtils { private static PoolingHttpClientConnectionManager connectionManager = null; private static HttpClientBuilder httpBuilder = null; private static RequestConfig requestConfig = null; private static int MAXCONNECTION = 10; private static int DEFAULTMAXCONNECTION = 5; private static String IP = "cnivi.com.cn"; private static int PORT = 80; static { //設置http的狀態參數 requestConfig = RequestConfig.custom() .setSocketTimeout(5000) .setConnectTimeout(5000) .setConnectionRequestTimeout(5000) .build(); HttpHost target = new HttpHost(IP, PORT); connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(MAXCONNECTION);//客戶端總並行鏈接最大數 connectionManager.setDefaultMaxPerRoute(DEFAULTMAXCONNECTION);//每個主機的最大並行鏈接數 connectionManager.setMaxPerRoute(new HttpRoute(target), 20); httpBuilder = HttpClients.custom(); httpBuilder.setConnectionManager(connectionManager); } public static CloseableHttpClient getConnection() { CloseableHttpClient httpClient = httpBuilder.build(); return httpClient; } public static HttpUriRequest getRequestMethod(Map<String, String> map, String url, String method) { List<NameValuePair> params = new ArrayList<NameValuePair>(); Set<Map.Entry<String, String>> entrySet = map.entrySet(); for (Map.Entry<String, String> e : entrySet) { String name = e.getKey(); String value = e.getValue(); NameValuePair pair = new BasicNameValuePair(name, value); params.add(pair); } HttpUriRequest reqMethod = null; if ("post".equals(method)) { reqMethod = RequestBuilder.post().setUri(url) .addParameters(params.toArray(new BasicNameValuePair[params.size()])) .setConfig(requestConfig).build(); } else if ("get".equals(method)) { reqMethod = RequestBuilder.get().setUri(url) .addParameters(params.toArray(new BasicNameValuePair[params.size()])) .setConfig(requestConfig).build(); } return reqMethod; } public static void main(String args[]) throws IOException { Map<String, String> map = new HashMap<String, String>(); map.put("account", ""); map.put("password", ""); HttpClient client = getConnection(); HttpUriRequest post = getRequestMethod(map, "http://cnivi.com.cn/login", "post"); HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); String message = EntityUtils.toString(entity, "utf-8"); System.out.println(message); } else { System.out.println("請求失敗"); } } }
get方式
/** * 發送 get請求 */ public void get() { CloseableHttpClient httpclient = HttpClients.createDefault(); try { // 創建httpget. HttpGet httpget = new HttpGet("http://www.baidu.com/"); System.out.println("executing request " + httpget.getURI()); // 執行get請求. CloseableHttpResponse response = httpclient.execute(httpget); try { // 獲取響應實體 HttpEntity entity = response.getEntity(); System.out.println("--------------------------------------"); // 打印響應狀態 System.out.println(response.getStatusLine()); if (entity != null) { // 打印響應內容長度 System.out.println("Response content length: " + entity.getContentLength()); // 打印響應內容 System.out.println("Response content: " + EntityUtils.toString(entity)); } System.out.println("------------------------------------"); } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 關閉連接,釋放資源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } }
post方式
/** * 發送 post請求訪問本地應用並根據傳遞參數不同返回不同結果 */ public void post() { // 創建默認的httpClient實例. CloseableHttpClient httpclient = HttpClients.createDefault(); // 創建httppost HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceJ.action"); // 創建參數隊列 List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("type", "house")); UrlEncodedFormEntity uefEntity; try { uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); httppost.setEntity(uefEntity); System.out.println("executing request " + httppost.getURI()); CloseableHttpResponse response = httpclient.execute(httppost); try { HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("--------------------------------------"); System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8")); System.out.println("--------------------------------------"); } } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 關閉連接,釋放資源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } }
post方式亂碼補充
如果有亂碼,可以償試使用 StringEntity 來替換HttpEntity:
StringEntity content =new StringEntity(soapRequestData.toString(), Charset.forName("UTF-8"));// 第二個參數,設置后才會對,內容進行編碼 content.setContentType("application/soap+xml; charset=UTF-8"); content.setContentEncoding("UTF-8"); httppost.setEntity(content);
具體SOAP協議代碼如下:
package com.isoftstone.core.service.impl; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.Scanner; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.EntityBuilder; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.Element; import com.isoftstone.core.common.constant.RequestConstants; import com.isoftstone.core.common.tools.XmlTool; import com.isoftstone.core.service.intf.ServiceOfStringPara; /** * 德勤定價系統,由核心主動調用 * @author King * */ public class DeloittePricingSingleCarImpl implements ServiceOfStringPara { private String serviceUrl = "http://10.30.0.35:7001/ZSInsUW/Auto/PricingService"; private static Logger log = Logger.getLogger(DeloittePricingSingleCarImpl.class.getName()); public String invoke(String sRequest) { StringBuffer soapRequestData = new StringBuffer(); soapRequestData.append("<soapenv:Envelope"); soapRequestData.append(" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" "); soapRequestData.append(" xmlns:prov=\"http://provider.webservice.zsins.dtt.com/\">"); soapRequestData.append(" <soapenv:Header/> "); soapRequestData.append("<soapenv:Body>"); soapRequestData.append("<prov:executePrvPricing>"); soapRequestData.append("<arg0>"); soapRequestData.append("<![CDATA[" + sRequest + "]]>"); soapRequestData.append("</arg0>"); soapRequestData.append("</prov:executePrvPricing>"); soapRequestData.append(" </soapenv:Body>"); soapRequestData.append("</soapenv:Envelope>"); HttpClient httpclient = HttpClients.createDefault(); HttpPost httppost = new HttpPost(serviceUrl); StringEntity content =new StringEntity(soapRequestData.toString(), Charset.forName("UTF-8"));// 第二個參數,設置后才會對,內容進行編碼 content.setContentType("application/soap+xml; charset=UTF-8"); content.setContentEncoding("UTF-8"); httppost.setEntity(content); //用下面的服務器端以UTF-8接收到的報文會亂碼,原因未知 // HttpEntity reqEntity = EntityBuilder.create().setContentType( // ContentType.TEXT_PLAIN) // .TEXT_PLAIN // .setText(soapRequestData.toString()).build(); // httppost.setEntity(reqEntity); // httppost.addHeader("Content-Type", // "application/soap+xml; charset=utf-8"); HttpResponse response = null; Document doc = null; String returnXml = null; String sentity = null; try { response = httpclient.execute(httppost); HttpEntity resEntity = response.getEntity(); if (resEntity != null) { sentity = EntityUtils.toString(resEntity, "UTF-8"); doc = XmlTool.getDocument(sentity, RequestConstants.ENCODE); System.out.println(doc.toString()); Element eRoot = doc.getRootElement(); Element body = eRoot.getChild("Body", eRoot.getNamespace()); Element resp = (Element) body.getChildren().get(0); Element returnele = resp.getChild("return"); returnXml = returnele.getText().toString(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { log.info("發送給德勤定價系統的請求報文:\n" + soapRequestData.toString()); log.info("德勤定價系統返回的響應報文:\n" + sentity); log.info("返回給核心的的報文:\n" + returnXml); } return returnXml; } public String getServiceUrl() { return serviceUrl; } public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; } public static void main(String[] args) throws Exception{ File file = new File("D:/浙商項目資料/z浙江資料/t唐建華/德勤定價調試報文.txt"); System.out.println(file.exists()); String temp2 = null; StringBuilder sb2 = new StringBuilder(); InputStreamReader isr = new InputStreamReader(new FileInputStream(file),"GBK"); BufferedReader br = new BufferedReader(isr); temp2 = br.readLine(); while( temp2 != null ){ sb2.append(temp2); temp2 = br.readLine(); } String sss = sb2.toString(); // System.out.println(sss.toString()); new DeloittePricingSingleCarImpl().invoke(sss); } }
post提交表單
/** * post方式提交表單(模擬用戶登錄請求) */ public void postForm() { // 創建默認的httpClient實例. CloseableHttpClient httpclient = HttpClients.createDefault(); // 創建httppost HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceJ.action"); // 創建參數隊列 List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("username", "admin")); formparams.add(new BasicNameValuePair("password", "123456")); UrlEncodedFormEntity uefEntity; try { uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); httppost.setEntity(uefEntity); System.out.println("executing request " + httppost.getURI()); CloseableHttpResponse response = httpclient.execute(httppost); try { HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("--------------------------------------"); System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8")); System.out.println("--------------------------------------"); } } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 關閉連接,釋放資源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } }
文件上傳
/** * 上傳文件 */ public void upload() { CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceFile.action"); FileBody bin = new FileBody(new File("F:\\image\\sendpix0.jpg")); StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN); HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("bin", bin).addPart("comment", comment).build(); httppost.setEntity(reqEntity); System.out.println("executing request " + httppost.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httppost); try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); HttpEntity resEntity = response.getEntity(); if (resEntity != null) { System.out.println("Response content length: " + resEntity.getContentLength()); } EntityUtils.consume(resEntity); } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } }
ssl連接
/** * HttpClient連接SSL */ public void ssl() { CloseableHttpClient httpclient = null; try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStream instream = new FileInputStream(new File("d:\\tomcat.keystore")); try { // 加載keyStore d:\\tomcat.keystore trustStore.load(instream, "123456".toCharArray()); } catch (CertificateException e) { e.printStackTrace(); } finally { try { instream.close(); } catch (Exception ignore) { } } // 相信自己的CA和所有自簽名的證書 SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(); // 只允許使用TLSv1協議 SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); // 創建http請求(get方式) HttpGet httpget = new HttpGet("https://localhost:8443/myDemo/Ajax/serivceJ.action"); System.out.println("executing request" + httpget.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httpget); try { HttpEntity entity = response.getEntity(); System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); if (entity != null) { System.out.println("Response content length: " + entity.getContentLength()); System.out.println(EntityUtils.toString(entity)); EntityUtils.consume(entity); } } finally { response.close(); } } catch (ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } finally { if (httpclient != null) { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } } }
關於RequestConfig的配置:
源自:
http://segmentfault.com/a/1190000000587944
http://blog.csdn.net/walkerjong/article/details/51710945
public void requestConfig(){ // 新建一個RequestConfig: RequestConfig defaultRequestConfig = RequestConfig.custom() //一、連接目標服務器超時時間:ConnectionTimeout-->指的是連接一個url的連接等待時間 .setConnectTimeout(5000) //二、讀取目標服務器數據超時時間:SocketTimeout-->指的是連接上一個url,獲取response的返回等待時間 .setSocketTimeout(5000) //三、從連接池獲取連接的超時時間:ConnectionRequestTimeout .setConnectionRequestTimeout(5000) .build(); // 這個超時可以設置為客戶端級別,作為所有請求的默認值: CloseableHttpClient httpclient = HttpClients.custom() .setDefaultRequestConfig(defaultRequestConfig) .build(); // httpclient.execute(httppost);的時候可以讓httppost直接享受到httpclient中的默認配置. // Request不會繼承客戶端級別的請求配置,所以在自定義Request的時候,需要將客戶端的默認配置拷貝過去: HttpGet httpget = new HttpGet("http://www.apache.org/"); RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig) .setProxy(new HttpHost("myotherproxy", 8080)) .build(); httpget.setConfig(requestConfig); // httpget可以單獨地使用新copy的requestConfig請求配置,不會對別的request請求產生影響 }
httpGet或httpPost 的abort()和releaseConnection()差異
//httpPost.abort();//中斷請求,接下來可以開始另一段請求,所以個人理應,用這個應該可以在session中虛擬登錄 //httpPost.releaseConnection();//釋放請求.如果釋放了相當於要清空session
根所以上差異,可知模擬登錄可以如下: 源自 http://bbs.csdn.net/topics/390195343
package com.bms.core; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import com.bms.util.CommonUtil; public class Test2 { /** * @param args * @throws IOException * @throws ClientProtocolException */ public static void main(String[] args) throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("http://www.baidu.com"); String body = ""; HttpResponse response; HttpEntity entity; response = httpclient.execute(httpGet); entity = response.getEntity(); body = EntityUtils.toString(entity);//這個就是頁面源碼了 httpGet.abort();//中斷請求,接下來可以開始另一段請求 System.out.println(body); //httpGet.releaseConnection();//釋放請求.如果釋放了相當於要清空session //以下是post方法 HttpPost httpPost = new HttpPost("http://www.baidu.com");//一定要改成可以提交的地址,這里用百度代替 List <NameValuePair> nvps = new ArrayList <NameValuePair>(); nvps.add(new BasicNameValuePair("name", "1"));//名值對 nvps.add(new BasicNameValuePair("account", "xxxx")); httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); response = httpclient.execute(httpPost); entity = response.getEntity(); body = EntityUtils.toString(entity); System.out.println("Login form get: " + response.getStatusLine());//這個可以打印狀態 httpPost.abort(); System.out.println(body); httpPost.releaseConnection(); } }
源自 http://blog.csdn.net/wangpeng047/article/details/19624529#reply
其它相關資料: 非CloseableHttpClient HTTPClient模塊的HttpGet和HttpPost
我項目中用到的HttpClientUtil (2016/12/17)
package com.isoftstone.pcis.isc.util; import java.io.IOException; import java.io.InterruptedIOException; import java.net.UnknownHostException; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import com.isoftstone.pcis.isc.util.ProperUtil; public class HttpClientUtil { private static CloseableHttpClient httpclient = null; static final int maxTotal=Integer.valueOf(ProperUtil.get("maxTotal")).intValue();//總最大連接數 static final int defaultMaxPerRoute=Integer.valueOf(ProperUtil.get("corePoolSize")).intValue();//每條線路最大連接數 = 本系統核心線程數 , 這樣永遠不會超過最大連接 public static CloseableHttpClient getHttpClient() { if (null == httpclient) { synchronized (HttpClientUtil.class) { if (null == httpclient) { httpclient = getNewHttpClient(); } } } return httpclient; } private static CloseableHttpClient getNewHttpClient() { // 設置連接池 ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory(); Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", plainsf).register("https", sslsf).build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry); // 配置最大連接數 cm.setMaxTotal(maxTotal); // 配置每條線路的最大連接數 cm.setDefaultMaxPerRoute(defaultMaxPerRoute); // 請求重試處理 HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 2) {// 如果已經重試了2次,就放棄 return false; } if (exception instanceof NoHttpResponseException) {// 如果服務器丟掉了連接,那么就重試 return true; } if (exception instanceof SSLHandshakeException) {// 不要重試SSL握手異常 return false; } if (exception instanceof InterruptedIOException) {// 超時 return false; } if (exception instanceof UnknownHostException) {// 目標服務器不可達 return false; } if (exception instanceof ConnectTimeoutException) {// 連接被拒絕 return false; } if (exception instanceof SSLException) {// SSL握手異常 return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); if (!(request instanceof HttpEntityEnclosingRequest)) { return true; } return false; } }; CloseableHttpClient newHttpclient=null; newHttpclient = HttpClients.custom() .setConnectionManager(cm) // .setDefaultRequestConfig(requestConfig) .setRetryHandler(httpRequestRetryHandler) .build(); return newHttpclient; } }
我自己整理的HttpClientTool (2017/06/01)
package com.isoftstone.core.util; import java.io.IOException; import java.io.InterruptedIOException; import java.net.UnknownHostException; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; /** * org.apache.http.impl.client.CloseableHttpClient鏈接池生成工具 * @reference http://www.cnblogs.com/whatlonelytear/articles/4835538.html * @author King * @date 20170601 */ public class HttpClientTool { // org.apache.http.impl.client.CloseableHttpClient private static CloseableHttpClient httpclient = null; // 這里就直接默認固定了,因為以下三個參數在新建的method中仍然可以重新配置並被覆蓋. static final int connectionRequestTimeout = 5000;// ms毫秒,從池中獲取鏈接超時時間 static final int connectTimeout = 5000;// ms毫秒,建立鏈接超時時間 static final int socketTimeout = 30000;// ms毫秒,讀取超時時間 // 總配置,主要涉及是以下兩個參數,如果要作調整沒有用到properties會比較后麻煩,但鑒於一經粘貼,隨處可用的特點,就不再做依賴性配置化處理了. // 而且這個參數同一家公司基本不會變動. static final int maxTotal = 500;// 最大總並發,很重要的參數 static final int maxPerRoute = 100;// 每路並發,很重要的參數 // 正常情況這里應該配成MAP或LIST // 細化配置參數,用來對每路參數做精細化處理,可以管控各ip的流量,比如默認配置請求baidu:80端口最大100個並發鏈接, static final String detailHostName = "http://www.baidu.com";// 每個細化配置之ip(不重要,在特殊場景很有用) static final int detailPort = 80;// 每個細化配置之port(不重要,在特殊場景很有用) static final int detailMaxPerRoute = 100;// 每個細化配置之最大並發數(不重要,在特殊場景很有用) public static CloseableHttpClient getHttpClient() { if (null == httpclient) { synchronized (HttpClientTool.class) { if (null == httpclient) { httpclient = init(); } } } return httpclient; } /** * 鏈接池初始化 這里最重要的一點理解就是. 讓CloseableHttpClient 一直活在池的世界里, 但是HttpPost卻一直用完就消掉. * 這樣可以讓鏈接一直保持着. * * @return */ private static CloseableHttpClient init() { CloseableHttpClient newHttpclient = null; // 設置連接池 ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory(); Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", plainsf).register("https", sslsf).build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry); // 將最大連接數增加 cm.setMaxTotal(maxTotal); // 將每個路由基礎的連接增加 cm.setDefaultMaxPerRoute(maxPerRoute); // 細化配置開始,其實這里用Map或List的for循環來配置每個鏈接,在特殊場景很有用. // 將每個路由基礎的連接做特殊化配置,一般用不着 HttpHost httpHost = new HttpHost(detailHostName, detailPort); // 將目標主機的最大連接數增加 cm.setMaxPerRoute(new HttpRoute(httpHost), detailMaxPerRoute); // cm.setMaxPerRoute(new HttpRoute(httpHost2), // detailMaxPerRoute2);//可以有細化配置2 // cm.setMaxPerRoute(new HttpRoute(httpHost3), // detailMaxPerRoute3);//可以有細化配置3 // 細化配置結束 // 請求重試處理 HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 2) {// 如果已經重試了2次,就放棄 return false; } if (exception instanceof NoHttpResponseException) {// 如果服務器丟掉了連接,那么就重試 return true; } if (exception instanceof SSLHandshakeException) {// 不要重試SSL握手異常 return false; } if (exception instanceof InterruptedIOException) {// 超時 return false; } if (exception instanceof UnknownHostException) {// 目標服務器不可達 return false; } if (exception instanceof ConnectTimeoutException) {// 連接被拒絕 return false; } if (exception instanceof SSLException) {// SSL握手異常 return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); // 如果請求是冪等的,就再次嘗試 if (!(request instanceof HttpEntityEnclosingRequest)) { return true; } return false; } }; // 配置請求的超時設置 RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build(); newHttpclient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build(); return newHttpclient; } }
異常列表


而服務端返回HTTP/1.1 404 Not Found 代表能連上主機,只是目標主機沒有提供這個服務(請求的服務路徑可能寫錯)
FROM:http://www.cnblogs.com/whatlonelytear/articles/4835538.html
