之前一直使用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