HTTPClient系统学习
HTTP協(xié)議時Internet上使用的很多也很重要的一個協(xié)議,越來越多的java應(yīng)用程序需要通過HTTP協(xié)議來訪問網(wǎng)絡(luò)資源。
HTTPClient提供的主要功能:
1、實現(xiàn)了所有HTTP的方法(GET、POST、等PUT、HEAD);
2、支持自動轉(zhuǎn)向;
3、支持HTTPS協(xié)議;
4、支持代理服務(wù)器等。
使用HttpClient需要以下6個步驟:
HTTP GET方法應(yīng)用:
應(yīng)用一:
應(yīng)用二:
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());/**請求發(fā)送成功,并得到響應(yīng)**/if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {/**讀取服務(wù)器返回過來的數(shù)據(jù)**/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方法應(yīng)用:
POST方法用來向目的服務(wù)器發(fā)出請求,要求它接受被附在請求后的實體,并把它當(dāng)作請求隊列(Request-Line)中請求URI所指定資源的附加新子項。
應(yīng)用一:
注意:(自動轉(zhuǎn)向問題的代碼實現(xiàn))
// HttpClient對于要求接受后繼服務(wù)的請求,象POST和PUT等不能自動處理轉(zhuǎn)發(fā) // 301(永久移走)或者302(暫時轉(zhuǎn)向) if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 從頭中取出轉(zhuǎn)向的地址 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."); }應(yīng)用二:
public static JSONObject httpPost(String url,JSONObject jsonParam, boolean noNeedResponse){//post請求返回結(jié)果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");/**請求發(fā)送成功,并得到響應(yīng)**/if (result.getStatusLine().getStatusCode() == 200) {String str = "";try {/**讀取服務(wù)器返回過來的json字符串?dāng)?shù)據(jù)**/str = EntityUtils.toString(result.getEntity());if (noNeedResponse) {return null;}/**把json字符串轉(zhuǎn)換成json對象**/jsonResult = JSONObject.fromObject(str);} catch (Exception e) {logger.error("post請求提交失敗:" + url, e);}}} catch (IOException e) {logger.error("post請求提交失敗:" + url, e);}return jsonResult; }使用HttpClient調(diào)用webservice服務(wù):
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調(diào)用webservice服務(wù)* @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發(fā)送soap請求* @param postUrl 請求webservice地址* @param soapXml 請求報文* @param soapAction* @return*/public static String doPostSoap(String postUrl, String soapXml, String soapAction) { String retStr = ""; // 創(chuàng)建HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); // HttpClient CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); HttpPost httpPost = new HttpPost(postUrl); // 設(shè)置請求和傳輸超時時間 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) { // 打印響應(yīng)內(nèi)容 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常用方法總結(jié):
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常用方法總結(jié)* @param args* @author lmb* @date 2017-4-18*/ public class HttpClientUtil {//總結(jié)一:**********當(dāng)httpClient的示例不在需要時,可以使用連接管理器關(guān)閉**********httpClient.getConnectionManager().shutdown();//總結(jié)二:**********針對HTTPs的協(xié)議的HttpClient請求必須用戶和密碼 **********httpclient.getCredentialsProvider() .setCredentials(new AuthScope("localhost", 443), new UsernamePasswordCredentials("username", "password"));//總結(jié)三:**********如果不想獲取HTTPClient返回的信息**********httpclient.abort(); //總結(jié)四:**********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);//總結(jié)五:**********獲取Cookie的信息********** HttpClient httpclient = new DefaultHttpClient(); // 創(chuàng)建一個本地Cookie存儲的實例 CookieStore cookieStore = new BasicCookieStore(); //創(chuàng)建一個本地上下文信息 HttpContext localContext = new BasicHttpContext(); //在本地上下問中綁定一個本地存儲 localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); //設(shè)置請求的路徑 HttpGet httpget = new HttpGet("http://www.google.com/"); //傳遞本地的http上下文給服務(wù)器 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]); } //總結(jié)六:**********針對典型的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(); } //創(chuàng)建SSLSocketFactory,創(chuàng)建相關(guān)的Socket SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore); //設(shè)置協(xié)議的類型和密鑰信息,以及斷開信息 Scheme sch = new Scheme("https", socketFactory, 443); //在連接管理器中注冊中信息 httpclient.getConnectionManager().getSchemeRegistry().register(sch);//總結(jié)七:**********設(shè)置請求的參數(shù)的幾種方式********** //A.在請求的路徑中以查詢字符串格式傳遞參數(shù) //B.在請求的實體中添加參數(shù) 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)); }以下內(nèi)容來自百度百科:
下面介紹在使用HttpClient過程中常見的一些問題。
1、字符編碼
某目標(biāo)頁的編碼可能出現(xiàn)在兩個地方,第一個地方是服務(wù)器返回的http頭中,另外一個地方是得到的html/xml頁面中。
在http頭的Content-Type字段可能會包含字符編碼信息。例如可能返回的頭會包含這樣子的信息:Content-Type: text/html; charset=UTF-8。這個頭信息表明該頁的編碼是UTF-8,但是服務(wù)器返回的頭信息未必與內(nèi)容能匹配上。比如對于一些雙字節(jié)語言國家,可能服務(wù)器返回的編碼類型是UTF-8,但真正的內(nèi)容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁面的編碼信息;但是如果服務(wù)器返回的編碼不是UTF-8,而是具體的一些編碼,比如gb2312等,那服務(wù)器返回的可能是正確的編碼信息。通過method對象的getResponseCharSet()方法就可以得到http頭中的編碼信息。
對于象xml或者html這樣的文件,允許作者在頁面中直接指定編碼類型。比如在html中會有<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>這樣的標(biāo)簽;或者在xml中會有<?xml version="1.0" encoding="gb2312"?>這樣的標(biāo)簽,在這些情況下,可能與http頭中返回的編碼信息沖突,需要用戶自己判斷到底那種編碼類型應(yīng)該是真正的編碼。
2、自動轉(zhuǎn)向
根據(jù)RFC2616中對自動轉(zhuǎn)向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當(dāng)返回的是301,則表示請求的資源已經(jīng)被移到一個固定的新地方,任何向該地址發(fā)起請求都會被轉(zhuǎn)到新的地址上。302表示暫時的轉(zhuǎn)向,比如在服務(wù)器端的servlet程序調(diào)用了sendRedirect方法,則在客戶端就會得到一個302的代碼,這時服務(wù)器返回的頭信息中l(wèi)ocation的值就是sendRedirect轉(zhuǎn)向的目標(biāo)地址。
HttpClient支持自動轉(zhuǎn)向處理,但是象POST和PUT方式這種要求接受后繼服務(wù)的請求方式,暫時不支持自動轉(zhuǎn)向,因此如果碰到POST方式提交后返回的是301或者302的話需要自己處理。就像剛才在POSTMethod中舉的例子:如果想進入登錄BBS后的頁面,必須重新發(fā)起登錄的請求,請求的地址可以在頭字段location中得到。不過需要注意的是,有時候location返回的可能是相對路徑,因此需要對location返回的值做一些處理才可以發(fā)起向新地址的請求。
另外除了在頭中包含的信息可能使頁面發(fā)生重定向外,在頁面中也有可能會發(fā)生頁面的重定向。引起頁面自動轉(zhuǎn)發(fā)的標(biāo)簽是:<meta http-equiv="refresh" content="5; url=....">。如果你想在程序中也處理這種情況的話得自己分析頁面來實現(xiàn)轉(zhuǎn)向。需要注意的是,在上面那個標(biāo)簽中url的值也可以是一個相對地址,如果是這樣的話,需要對它做一些處理后才可以轉(zhuǎn)發(fā)。
HTTPClient詳細教程參看:HTTPClient教程
總結(jié)
以上是生活随笔為你收集整理的HTTPClient系统学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【myeclipse】java.lang
- 下一篇: HttpURLConnection总结