之前一直使用jdk自帶的urlConnection來進行http通信,HttpClient與之相比,HttpClient更具備靈活度和易用性。HttpClient可以方便使用鏈接池,使用時須要從新建立鏈接,耗費巨大的鏈接時間。
css
目前Http協議版本爲1.1班,支持長鏈接,j2ee支持get,put,post,option,等方法。html
GET /link?url=chDeV_MryviuBdyQlKlkh0KwL0T4zzEU2jxSeOz2yD8ZPthCpAgRRufNz_4IKFP0AYKVcMkt2fLCmDsQ5a6m6p0PN1IcRz7KIN4R0ONTMrN97rr2JaH0bnFMD-M3Q1eX7W4b-5o-t96AIbNBOP_X05rXjAuw8bX-uNf_I3jPXAe HTTP/1.1 Host: baike.baidu.com User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Referer: http://www.baidu.com/link?url=chDeV_MryviuBdyQlKlkh0KwL0T4zzEU2jxSeOz2yD8ZPthCpAgRRufNz_4IKFP0AYKVcMkt2fLCmDsQ5a6m6p0PN1IcRz7KIN4R0ONTMrN97rr2JaH0bnFMD-M3Q1eX7W4b-5o-t96AIbNBOP_X05rXjAuw8bX-uNf_I3jPXAe&wd=&eqid=9adadb00000108a800000004555ea3a9 Cookie: bdshare_firstime=1423034727932; BIDUPSID=06ACBFD888B048E65E5EE3B6B3409EC8; BDUSS=XZtbDJ5eUZrcjNJTn5oTlF4dHFQQnVHbkt0TUJxZ1YwcEd4QndweW5KVWpsRzVWQVFBQUFBJCQAAAAAAAAAAAEAAACyEbBHem91cWYyMDA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMHR1UjB0dVa; ATS_PASS=9; locale=zh; BAIDUID=F3A2EE0D70C7D935C8A2F1505F627F7D:FG=1; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm; re__f=%20; BDRCVFR[2hu4KsUxzef]=mk3SLVN4HKm; BDRCVFR[i7zL5H8GeBs]=mk3SLVN4HKm; BDRCVFR[EJVTmGcXpQm]=mk3SLVN4HKm; H_PS_PSSID=1466_14335_13518_13075_10812_12868_14167_13692_10562_12723_14156_14173_14329_12038_13937_14177_8498_14194 Connection: keep-alive
HTTP/1.1 200 OK Server: JSP3/2.0.7 Date: Fri, 22 May 2015 06:11:46 GMT Content-Type: text/css Content-Length: 310 Connection: keep-alive Etag: "1886989" Last-Modified: Thu, 21 May 2015 01:38:06 GMT Expires: Sat, 20 Jun 2015 06:48:35 GMT Age: 84175 Cache-Control: max-age=2592000 Access-Control-Allow-Origin: * Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip
public class HttpTranfer { /* 定義日誌管理器 */ private final static Logger logger = Logger.getLogger(HttpTranfer.class); /* Http鏈接池只須要建立一個,所以採用單例模式的餓漢模式 */ private static PoolingHttpClientConnectionManager httpPoolManager = null; /* HttpClient */ private CloseableHttpClient httpClient = null; /* 鏈接池最大生成鏈接數200 */ private static int Pool_MaxTotal = 0; /* 鏈接池默認路由最大鏈接數,默認爲20 */ private static int Pool_MaxRoute = 0; /* 請求超時時間 */ private static int Request_TimeOut = 0; /*文件地址*/ private String fileUrl; /*判斷返回的是字符串仍是數據流*/ private boolean isString = true; /* 鏈接池參數配置 */ static { /*鏈接池總的最大生成鏈接數500 */ Pool_MaxTotal = 500; /* 鏈接池每一個路由的最大鏈接數,默認爲20 */ Pool_MaxRoute = 100; /* 請求超時時間 60 * 1000 */ Request_TimeOut = 60000; /* 建立鏈接池 */ if (httpPoolManager == null) { /* 初始化連世界管理器 */ httpPoolManager = new PoolingHttpClientConnectionManager(); // 鏈接池總的最大生成鏈接數 httpPoolManager.setMaxTotal(Pool_MaxTotal); // 設置每一個route最大鏈接數 httpPoolManager.setDefaultMaxPerRoute(Pool_MaxRoute); } } /** * 建立HttpClient * */ public HttpClient getHttpClient() { CookieStore cookieStore = new BasicCookieStore(); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); RequestConfig defaultRequestConfig = RequestConfig .custom() .setConnectTimeout(Request_TimeOut) .setConnectionRequestTimeout(Request_TimeOut) .setSocketTimeout(Request_TimeOut) .setCookieSpec(CookieSpecs.DEFAULT) .setExpectContinueEnabled(true) .setTargetPreferredAuthSchemes( Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)) .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)) .build(); // 設置重定向策略 LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy(); // 建立httpClient CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(httpPoolManager) .setDefaultCookieStore(cookieStore) .setDefaultCredentialsProvider(credentialsProvider) .setDefaultRequestConfig(defaultRequestConfig) .setRedirectStrategy(redirectStrategy) .build(); this.httpClient = httpClient; return httpClient; } /** * form的enctype=application/x-www-form-urlencoded或text/plain的posten通信 * * @throws IOException * @throws ClientProtocolException * */ public Object httpPostString(String url, HashMap<String, String> postMap) throws ClientProtocolException, IOException { long beginTime = System.currentTimeMillis(); /* 返回內容 */ Object returnContent = null; /* 建立HttpPost */ HttpPost httpPost = new HttpPost(url); /* 在header中添加token */ httpPost.setHeader("token", "puji"); /* 拼接Post傳輸參數 */ UrlEncodedFormEntity encoderFormData = formatData(postMap); httpPost.setEntity(encoderFormData); /* 執行post請求 */ CloseableHttpResponse httpResponse = (CloseableHttpResponse) getHttpClient() .execute(httpPost); /* 讀取通信返回的status code */ int responseStatus = httpResponse.getStatusLine().getStatusCode(); /* 若通信正常 */ if (responseStatus == HttpStatus.SC_OK) { /* 獲取相應的消息實體 */ HttpEntity responsehttpEntity = httpResponse.getEntity(); /* 讀取utf-8格式的返回內容 */ returnContent = getResponseData(responsehttpEntity); logger.error(returnContent); } /* 關閉響應實體 */ httpResponse.close(); /* 關閉httpClient鏈接 */ closeHttpClient(); long endTime = System.currentTimeMillis(); /* post耗時時間 */ logger.error(String.format("===== post cost time =[%d] =====", endTime - beginTime)); return returnContent; } /** * form的multipart/form的posten通信 multipart/form只能經過get方式傳遞參數 * * @throws IOException * @throws ClientProtocolException * * 目前該方法存在服務端沒法接收到addPart提交的數據,須要進一步調試 * */ public Object httpPostStream(String url, HashMap<String, Object> postMap) throws ClientProtocolException, IOException { long beginTime = System.currentTimeMillis(); /* 返回內容 */ Object returnContent = null; /* 建立HttpPost */ HttpPost httpPost = new HttpPost(url); /* 在header中添加token */ httpPost.setHeader("token", "puji"); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder .create(); /* 拼接字符串,傳輸參數 */ if (postMap != null && !postMap.isEmpty()) { Iterator<Entry<String, Object>> iterator = postMap.entrySet() .iterator(); while (iterator.hasNext()) { Entry<String, Object> entry = iterator.next(); String keyName = entry.getKey(); Object keyValue = entry.getValue(); ContentType contentType = ContentType.create("text/plain", Consts.UTF_8); /* 如果字符參數 */ if (keyValue instanceof String) { StringBody stringBody = new StringBody((String) keyValue, contentType); multipartEntityBuilder.addPart(keyName, stringBody); /* 文件參數 */ } else { FileBody fileBody = new FileBody((File) keyValue); multipartEntityBuilder.addPart(keyName, fileBody); } } } HttpEntity requestHttpEntity = multipartEntityBuilder.build(); httpPost.setEntity(requestHttpEntity); /* 執行post請求 */ CloseableHttpResponse httpResponse = (CloseableHttpResponse) getHttpClient() .execute(httpPost); /* 讀取通信返回的status code */ int responseStatus = httpResponse.getStatusLine().getStatusCode(); /* 若通信正常 */ if (responseStatus == HttpStatus.SC_OK) { /* 獲取相應的消息實體 */ HttpEntity responseHttpEntity = httpResponse.getEntity(); /* 讀取utf-8格式的返回內容 */ returnContent = getResponseData(responseHttpEntity); logger.error(returnContent); } /* 關閉響應實體 */ httpResponse.close(); /* 關閉httpClient鏈接 */ closeHttpClient(); long endTime = System.currentTimeMillis(); /* post耗時時間 */ logger.error(String.format("===== post cost time =[%d] =====", endTime - beginTime)); return returnContent; } /** * get通信 * * @throws IOException * @throws ClientProtocolException * */ public Object httpGet(String url) throws ClientProtocolException, IOException { long beginTime = System.currentTimeMillis(); /* 返回內容 */ Object returnContent = null; /* 建立HttpGet */ HttpGet httpGet = new HttpGet(url); /* 執行請求 */ CloseableHttpResponse httpResponse = (CloseableHttpResponse) getHttpClient() .execute(httpGet); // 獲取響應狀態碼 int statusCode = httpResponse.getStatusLine().getStatusCode(); /* 通信正常 */ if (statusCode == HttpStatus.SC_OK) { /* 得到響應的消息實體 */ HttpEntity responseHttpEntity = httpResponse.getEntity(); /* 讀取utf-8格式的返回內容 */ returnContent = getResponseData((HttpEntity) responseHttpEntity); logger.error(returnContent); } /* 關閉響應實體 */ httpResponse.close(); /* 關閉httpClient鏈接 */ closeHttpClient(); long endTime = System.currentTimeMillis(); /* post耗時時間 */ logger.error(String.format("===== post cost time =[%d] =====", endTime - beginTime)); return returnContent; } /* 拼接Post傳輸參數,並設定爲utf-8,只支持拼接String的字符,不支持流模式 */ private UrlEncodedFormEntity formatData(HashMap<String, String> postMap) throws UnsupportedEncodingException { List<NameValuePair> nvps = new ArrayList<NameValuePair>(); if (postMap != null && !postMap.isEmpty()) { Iterator<Entry<String, String>> iterator = postMap.entrySet() .iterator(); while (iterator.hasNext()) { Map.Entry<String, String> map = iterator.next(); String keyName = (String) map.getKey(); String keyValue = (String) map.getValue(); nvps.add(new BasicNameValuePair(keyName, keyValue)); } } UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, "UTF-8"); return uefEntity; } /* 判斷返回的http實體是字符串仍是流,仍是文件 */ private Object getResponseData(HttpEntity responseHttpEntity) throws ParseException, IOException { if (responseHttpEntity != null) { Header contentType = responseHttpEntity.getContentType(); if (contentType != null) { /* 如果數據流 */ if (contentType.getValue().indexOf("application/octet-stream") >= 0) { isString = false; InputStream inputStream = responseHttpEntity.getContent(); /*數據流處理*/ File file = doInputStream(inputStream); EntityUtils.consume(responseHttpEntity); return file; } else { /* 對返回的內容進行編碼 */ String responseContent = EntityUtils.toString( responseHttpEntity, "UTF-8"); EntityUtils.consume(responseHttpEntity); return responseContent; } } else { return null; } } else { return null; } } /*返回數據流處理*/ private File doInputStream(InputStream inputStream) throws IOException{ int size = 0; byte[] buffer = new byte[4096]; if(fileUrl != null && fileUrl.length() > 0){ File file = new File(fileUrl); FileOutputStream fileOutputStream = new FileOutputStream(file); while((size = inputStream.read(buffer)) != -1){ fileOutputStream.write(buffer, 0, size); } fileOutputStream.close(); inputStream.close(); return file; }else{ while((size = inputStream.read(buffer)) != -1){} inputStream.close(); return null; } } /*關閉客戶端*/ private void closeHttpClient() throws IOException { //httpClient.close(); } /*設定文件地址*/ public void setFileUrl(String fileUrl){ this.fileUrl = fileUrl; } /*判斷返回的是字符串仍是數據流*/ public boolean isString(){ return this.isString; } }
PoolingHttpClientConnectionManager鏈接池中HttpClient默認的路由參數爲2個,默認的最大鏈接數爲20個。鏈接池中路由的概念就是客戶端鏈接到目標服務器的通道。好比client 鏈接到 目標服務器A 和client鏈接到目標服務器B,表示client 有兩個路由通道。若是是單臺目標服務器鏈接池中的路由最大鏈接參數參數和最大鏈接數能夠設置一致。java
如果多臺目標服務器,PoolingHttpClientConnectionManager中的每一個路由鏈接數參數不能太小,不然即便最大鏈接數設置很大,可是每一個路由鏈接參數偏小,仍然沒法實現併發效果。好比按照默認設定鏈接池參數,目標服務器爲一個,那麼最大併發鏈接數只能爲2個,那麼剩下的18個鏈接只能空閒等待,並不是爲這臺目標服務器工做。
apache
要實現Servlet 3.0的原生態文件上傳支持,須要配置@MultipartConfig註解。配置完畢後,能夠經過request.getPart(「inputName」)接收上傳文件。如果多文件上傳能夠經過遍歷request.getParts()接收文件。api
一、@MultipartConfig有四個屬性服務器
fileSizeThreshold:當數據量大於該值時,內容將被寫入文件。
location:存放生成的文件地址。當調用完write()方法後,自動刪除該地址文件
maxFileSize:容許上傳的文件最大值。默認值爲 -1,表示沒有限制。
maxRequestSize:針對該 multipart/form-data 請求的最大數量,默認值爲 -1,表示沒有限制。cookie
二、經過getPart()或getParts()接收上傳文件併發
/*服務端遍歷全部上傳數據*/ try { /*文件存儲路徑*/ String path = "/home/files"; Iterator<Part>iterator=request.getParts().iterator(); while (iterator.hasNext()) { Part part = (Part) iterator.next(); String partName = part.getName(); /*如果input的name屬性含有file 表示是file域, name屬性在客戶端中根據value類型設定*/ if(partName.indexOf("file") >= 0){ /*獲取文件名*/ String header = part.getHeader("content-disposition"); String fileName = header.substring(header.indexOf("filename=\"") + 10, header.lastIndexOf("\"")); String filePath = path + fileName; part.write(filePath) }else{ /*輸出字符串參數*/ String value = ""; InputStream inputStream = part.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); while ((value += bufferedReader.readLine()) != null) {} System.out.println("________________value="+value); } } }catch (Exception e) { e.printStackTrace(); }
指定文件接收路徑也能夠經過@MultipartConfig(location="/home/files")方式來指定
app
一、request.getParameter("name") 能夠獲取到經過addTextBody()方法添加的String類型的數據 。
ide
二、request.getPart("name") 能夠獲取到經過addPart()、addBinaryBody()、addTextBody()添加的數據,返回類型爲Part。
三、request.getParts() 獲得Collection<Part>類型對象,能夠接受addBinaryBody()、addPart()、addTextBody()添加的數據。
四、上面接收文件也能夠經過FileOutputStream 接收
private void write(String fileName, InputStream in, String path) throws IOException, FileNotFoundException { OutputStream out = new FileOutputStream(filePath + filename); byte[] buffer = new byte[1024]; int length = -1; while ((length = in.read(buffer)) != -1) { out.write(buffer, 0, length); } in.close(); out.close(); }
String url = "D:\\rrtong\\xvid1.h"; File file = new File(url); String fileName = file.getName(); int fileSize = (int) file.length(); /*定義返回的編碼*/ response.setStatus(200); /*定義編碼格式*/ response.setCharacterEncoding("UTF-8"); /*定義內容類型,application/octet-stream表示通用類型*/ response.setContentType("application/octet-stream; charset=utf-8"); /*定義返回文件名稱*/ response.setHeader("Content-disposition", "attachment; filename="+ fileName); /*定義文件長度*/ response.setIntHeader("Content_Length", fileSize); /*生成文件流*/ InputStream fileInputStrream = new FileInputStream(file); OutputStream outputStream = response.getOutputStream(); /*輸出文件流*/ int byteSize = 0; byte arrByte[] = new byte[1024]; while((byteSize = fileInputStrream.read(arrByte)) != -1){ outputStream.write(arrByte,0, byteSize); } outputStream.flush(); fileInputStrream.close(); outputStream.close();
http://backend.blog.163.com/blog/static/2022941262014029105618173/
http://niuzhenxin.iteye.com/blog/2100100
http://www.yeetrack.com/?p=773
http://hc.apache.org/httpcomponents-client-4.4.x/httpclient/apidocs/org/apache/http/client/methods/CloseableHttpResponse.html
http://blog.csdn.net/fengyuzhengfan/article/details/39941851
http://www.cppblog.com/iuranus/archive/2010/07/04/119311.html
http://www.yeetrack.com/?p=773 http://www.yeetrack.com/?p=782 http://www.yeetrack.com/?p=822 http://www.yeetrack.com/?p=825 http://www.yeetrack.com/?p=832 http://www.yeetrack.com/?p=844