HTTPClient系统学习
HTTP協議時Internet上使用的很多也很重要的一個協議,越來越多的java應用程序需要通過HTTP協議來訪問網絡資源。
HTTPClient提供的主要功能:
1、實現了所有HTTP的方法(GET、POST、等PUT、HEAD);
2、支持自動轉向;
3、支持HTTPS協議;
4、支持代理服務器等。
使用HttpClient需要以下6個步驟:
HTTP GET方法應用:
應用一:
應用二:
public String getRequest(String url, String requestStr) {logger.debug("the getRest'params : url = " + "http://" + url + "?" + requestStr); String respStr = null;try { // 定義HttpClient DefaultHttpClient client = new DefaultHttpClient(); // 實例化HTTP方法 HttpGet request = new HttpGet();url = url + "?" + requestStr;url = URLEncoder.encode(url, "UTF-8");request.setURI(new URI("http://" + url)); HttpResponse response = client.execute(request); logger.debug("response status : " + response.getStatusLine().getStatusCode());/**請求發送成功,并得到響應**/if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {/**讀取服務器返回過來的數據**/respStr = EntityUtils.toString(response.getEntity());} else {logger.error("get request fail:" + url);}}catch(Exception e){logger.error("get request fail:" + url, e); }return respStr; }HTTP POST方法應用:
POST方法用來向目的服務器發出請求,要求它接受被附在請求后的實體,并把它當作請求隊列(Request-Line)中請求URI所指定資源的附加新子項。
應用一:
注意:(自動轉向問題的代碼實現)
// HttpClient對于要求接受后繼服務的請求,象POST和PUT等不能自動處理轉發 // 301(永久移走)或者302(暫時轉向) if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 從頭中取出轉向的地址 Header locationHeader = (Header) postMethod.getResponseHeader("location"); if (locationHeader != null) {String location = locationHeader.getValue();logger.info("The page was redirected to:" + location); } else {logger.info("Location field value is null."); }應用二:
public static JSONObject httpPost(String url,JSONObject jsonParam, boolean noNeedResponse){//post請求返回結果DefaultHttpClient httpClient = new DefaultHttpClient();JSONObject jsonResult = null;HttpPost method = new HttpPost(url);try {if (null != jsonParam) {//解決中文亂碼問題StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");entity.setContentEncoding("UTF-8");entity.setContentType("application/json");method.setEntity(entity);}HttpResponse result = httpClient.execute(method);url = URLDecoder.decode(url, "UTF-8");/**請求發送成功,并得到響應**/if (result.getStatusLine().getStatusCode() == 200) {String str = "";try {/**讀取服務器返回過來的json字符串數據**/str = EntityUtils.toString(result.getEntity());if (noNeedResponse) {return null;}/**把json字符串轉換成json對象**/jsonResult = JSONObject.fromObject(str);} catch (Exception e) {logger.error("post請求提交失敗:" + url, e);}}} catch (IOException e) {logger.error("post請求提交失敗:" + url, e);}return jsonResult; }使用HttpClient調用webservice服務:
import java.nio.charset.Charset; import org.apache.http.HttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; /*** 使用HttpClient調用webservice服務* @author lmb* @date 2017-4-18*/ public class HttpClientCallSoapUtil {private static final Logger logger = Logger.getLogger(HttpClientCallSoapUtil.class);static int socketTimeout = 60000;static int connectTimeout = 60000;public static void main(String[] args) {String soapXml = "<?xml version = \"1.0\" ?>" + "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://webservices.b.com\">" + " <soapenv:Header/>" + " <soapenv:Body>" + " <web:query soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + " <in0 xsi:type=\"web:QueryRequest\">" + " <endTime xsi:type=\"xsd:dateTime\">?</endTime>" + " <mobile xsi:type=\"soapenc:string\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">?</mobile>" + " <startTime xsi:type=\"xsd:dateTime\">?</startTime>" + " </in0>" + " </web:query>" + " </soapenv:Body>" + "</soapenv:Envelope>"; String postUrl = "http://localhost:8381/services/WebService"; doPostSoap(postUrl, soapXml, ""); }/*** HttpClient發送soap請求* @param postUrl 請求webservice地址* @param soapXml 請求報文* @param soapAction* @return*/public static String doPostSoap(String postUrl, String soapXml, String soapAction) { String retStr = ""; // 創建HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); // HttpClient CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); HttpPost httpPost = new HttpPost(postUrl); // 設置請求和傳輸超時時間 RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(socketTimeout) .setConnectTimeout(connectTimeout).build(); httpPost.setConfig(requestConfig); try { httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8"); httpPost.setHeader("SOAPAction", soapAction); StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8")); httpPost.setEntity(data); CloseableHttpResponse response = closeableHttpClient .execute(httpPost); HttpEntity httpEntity = response.getEntity(); if (httpEntity != null) { // 打印響應內容 retStr = EntityUtils.toString(httpEntity, "UTF-8"); logger.info("response:" + retStr); } // 釋放資源 closeableHttpClient.close(); } catch (Exception e) { logger.error("exception in doPostSoap1_1", e); } return retStr; } }HttpClient常用方法總結:
import java.io.File; import java.io.FileInputStream; import java.security.KeyStore; import java.util.ArrayList; import java.util.List; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.cookie.Cookie; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; /*** HttpClient常用方法總結* @param args* @author lmb* @date 2017-4-18*/ public class HttpClientUtil {//總結一:**********當httpClient的示例不在需要時,可以使用連接管理器關閉**********httpClient.getConnectionManager().shutdown();//總結二:**********針對HTTPs的協議的HttpClient請求必須用戶和密碼 **********httpclient.getCredentialsProvider() .setCredentials(new AuthScope("localhost", 443), new UsernamePasswordCredentials("username", "password"));//總結三:**********如果不想獲取HTTPClient返回的信息**********httpclient.abort(); //總結四:**********httpclient傳送文件的方式********** HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://www.apache.org"); File file = new File(""); InputStreamEntity reqEntity = new InputStreamEntity( new FileInputStream(file), -1); reqEntity.setContentType("binary/octet-stream"); reqEntity.setChunked(true); // It may be more appropriate to use FileEntity class in this particular // instance but we are using a more generic InputStreamEntity to demonstrate // the capability to stream out data from any arbitrary source // // FileEntity entity = new FileEntity(file, "binary/octet-stream"); httppost.setEntity(reqEntity); System.out.println("executing request " + httppost.getRequestLine()); HttpResponse response = httpclient.execute(httppost);//總結五:**********獲取Cookie的信息********** HttpClient httpclient = new DefaultHttpClient(); // 創建一個本地Cookie存儲的實例 CookieStore cookieStore = new BasicCookieStore(); //創建一個本地上下文信息 HttpContext localContext = new BasicHttpContext(); //在本地上下問中綁定一個本地存儲 localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); //設置請求的路徑 HttpGet httpget = new HttpGet("http://www.google.com/"); //傳遞本地的http上下文給服務器 HttpResponse response = httpclient.execute(httpget, localContext); //獲取本地信息 HttpEntity entity = response.getEntity(); System.out.println(response.getStatusLine()); if (entity != null) { System.out.println("Response content length: " + entity.getContentLength()); } //獲取cookie中的各種信息 List<Cookie> cookies = cookieStore.getCookies(); for (int i = 0; i < cookies.size(); i++) { System.out.println("Local cookie: " + cookies.get(i)); } //獲取消息頭的信息 Header[] headers = response.getAllHeaders(); for (int i = 0; i<headers.length; i++) { System.out.println(headers[i]); } //總結六:**********針對典型的SSL請求的處理********** DefaultHttpClient httpclient = new DefaultHttpClient(); //獲取默認的存儲密鑰類 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); //加載本地的密鑰信息 FileInputStream instream = new FileInputStream(new File("my.keystore")); try { trustStore.load(instream, "nopassword".toCharArray()); } finally { instream.close(); } //創建SSLSocketFactory,創建相關的Socket SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore); //設置協議的類型和密鑰信息,以及斷開信息 Scheme sch = new Scheme("https", socketFactory, 443); //在連接管理器中注冊中信息 httpclient.getConnectionManager().getSchemeRegistry().register(sch);//總結七:**********設置請求的參數的幾種方式********** //A.在請求的路徑中以查詢字符串格式傳遞參數 //B.在請求的實體中添加參數 List <NameValuePair> nvps = new ArrayList <NameValuePair>(); nvps.add(new BasicNameValuePair("IDToken1", "username")); nvps.add(new BasicNameValuePair("IDToken2", "password")); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); }以下內容來自百度百科:
下面介紹在使用HttpClient過程中常見的一些問題。
1、字符編碼
某目標頁的編碼可能出現在兩個地方,第一個地方是服務器返回的http頭中,另外一個地方是得到的html/xml頁面中。
在http頭的Content-Type字段可能會包含字符編碼信息。例如可能返回的頭會包含這樣子的信息:Content-Type: text/html; charset=UTF-8。這個頭信息表明該頁的編碼是UTF-8,但是服務器返回的頭信息未必與內容能匹配上。比如對于一些雙字節語言國家,可能服務器返回的編碼類型是UTF-8,但真正的內容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁面的編碼信息;但是如果服務器返回的編碼不是UTF-8,而是具體的一些編碼,比如gb2312等,那服務器返回的可能是正確的編碼信息。通過method對象的getResponseCharSet()方法就可以得到http頭中的編碼信息。
對于象xml或者html這樣的文件,允許作者在頁面中直接指定編碼類型。比如在html中會有<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>這樣的標簽;或者在xml中會有<?xml version="1.0" encoding="gb2312"?>這樣的標簽,在這些情況下,可能與http頭中返回的編碼信息沖突,需要用戶自己判斷到底那種編碼類型應該是真正的編碼。
2、自動轉向
根據RFC2616中對自動轉向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當返回的是301,則表示請求的資源已經被移到一個固定的新地方,任何向該地址發起請求都會被轉到新的地址上。302表示暫時的轉向,比如在服務器端的servlet程序調用了sendRedirect方法,則在客戶端就會得到一個302的代碼,這時服務器返回的頭信息中location的值就是sendRedirect轉向的目標地址。
HttpClient支持自動轉向處理,但是象POST和PUT方式這種要求接受后繼服務的請求方式,暫時不支持自動轉向,因此如果碰到POST方式提交后返回的是301或者302的話需要自己處理。就像剛才在POSTMethod中舉的例子:如果想進入登錄BBS后的頁面,必須重新發起登錄的請求,請求的地址可以在頭字段location中得到。不過需要注意的是,有時候location返回的可能是相對路徑,因此需要對location返回的值做一些處理才可以發起向新地址的請求。
另外除了在頭中包含的信息可能使頁面發生重定向外,在頁面中也有可能會發生頁面的重定向。引起頁面自動轉發的標簽是:<meta http-equiv="refresh" content="5; url=....">。如果你想在程序中也處理這種情況的話得自己分析頁面來實現轉向。需要注意的是,在上面那個標簽中url的值也可以是一個相對地址,如果是這樣的話,需要對它做一些處理后才可以轉發。
HTTPClient詳細教程參看:HTTPClient教程
總結
以上是生活随笔為你收集整理的HTTPClient系统学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【myeclipse】java.lang
- 下一篇: java信息管理系统总结_java实现科