HttpClient学习

(1)下面列举几个主要的Http相关概念的类

类名 描述
HttpClient 建立请求客户端
HttpGet 代表请求方法,类似的还有HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace,  HttpOptions等
HttpResponse 表示请求的响应(包括响应状态、协议等头信息,Header封装各种头信息,头信息又包括HeaderElement,都可以采用迭代器的方式进行迭代读取)
HttpEntity 表示相应的实体,用于存放传送的内容,也就是body体,存在于request和response中,request只有post和put方法有,response中都有Entity,除了一些特殊情况不包含内容。Entity根据来源分为三种:streamed,一次读取;wrapping,从其他entity封装;self-contained,从内存中读取,可反复读。
URIBuilder 工具类用来生成url,主要是设置协议、域名和路径,还有各种参数等

(2)HttpEntity的几个主要函数

函数 描述
getContentType 获取内容类型
getContentLength 获取内容长度
getContent 获取内容的输入流InputStream

 

   
   
   
   
  1. HttpEntity entity=response.getEntity(); 
  2.  
  3.             System.out.println(entity.getContentType()); 
  4.  
  5.             System.out.println(entity.getContentLength()); 
  6.  
  7.             InputStream in=entity.getContent();//直接获取输入流,一次读取 

(3)HttpEntity直接获取的streamed流

   
   
   
   
  1. 只能读取一次,如果想读取多次,就要进行缓存,利用wrapping方式将streamed进行包装BufferedHttpEntity 
  2. BufferedHttpEntity bufEntity=new BufferedHttpEntity(entity);//通过构造形式封装进缓存,可多次读取 

(4)HttpEntity也可放在post和put方法的请求中

   
   
   
   
  1. 作为请求传递的内容。内容可以是文件,也可以提交form参数 
  2.             File file=new File("out.txt"); 
  3.  
  4.             FileEntity fileEntity=new FileEntity(file, ContentType.create("text/plain""UTF-8"));//文件内容输入 
  5.  
  6.   
  7.  
  8.             List formparams = new ArrayList(); 
  9.  
  10.             formparams.add(new BasicNameValuePair("param1""value1")); 
  11.  
  12.             formparams.add(new BasicNameValuePair("param2""value2")); 
  13.  
  14.             UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8");//form表单内容输入 
  15.  
  16.             HttpPost post=new HttpPost("http://www.baidu.com"); 
  17.  
  18.             post.setEntity(fileEntity); 

(5)response处理类最方便的是ResponseHandler类,它的功能是将entity转化为不同的内容格式

   
   
   
   
  1. ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() { 
  2.  
  3.               public byte[] handleResponse( 
  4.  
  5.                        HttpResponse response) throws ClientProtocolException, IOException { 
  6.  
  7.                    HttpEntity entity = response.getEntity(); 
  8.  
  9.                   if (entity != null) { 
  10.  
  11.                       return EntityUtils.toByteArray(entity); 
  12.  
  13.                   } else { 
  14.  
  15.                       return null
  16.  
  17.                   } 
  18.  
  19.               } 
  20.  
  21.           }; 
  22.  
  23.  
  24.  
  25.           byte[] response = httpclient.execute(httpget, handler); 
  26.  
  27.            ResponseHandler handler1=new BasicResponseHandler(); 
  28.  
  29.            String response1= httpclient.execute(httpget,handler1);        

(6)request请求时可以设置一些http参数httpparam

和httpcontext相似,httpclient可以设置客户端范围的,httprequest也可以设置,但是请求范围的。

参数名 描述
CoreProtocolPNames.PROTOCOL_VERSION='http.protocol.version' 协议版本
CoreProtocolPNames.HTTP_ELEMENT_CHARSET='http.protocol.element-charset' 协议元素编码
CoreProtocolPNames.HTTP_CONTENT_CHARSET='http.protocol.content-charset' 协议内容编码
CoreProtocolPNames.USER_AGENT='http.useragent' 用户端,写爬虫的时候有用
CoreProtocolPNames.STRICT_TRANSFER_ENCODING='http.protocol.strict-transfer-encoding' (...
CoreProtocolPNames.USE_EXPECT_CONTINUE='http.protocol.expect-continue' ...
CoreProtocolPNames.WAIT_FOR_CONTINUE='http.protocol.wait-for-continue' ...

 

   
   
   
   
  1. httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,  
  2.  
  3.   HttpVersion.HTTP_1_0); // Default to HTTP 1.0 
  4.  
  5.   httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,  
  6.  
  7.      "UTF-8"); 
  8.  
  9.  
  10.  
  11.   HttpGet httpget = new HttpGet("http://www.google.com.hk/"); 
  12.  
  13.   httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,  
  14.  
  15.       HttpVersion.HTTP_1_1); // Use HTTP 1.1 for this request only 
  16.  
  17.   httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,  
  18.  
  19.       Boolean.FALSE); 

(7)httpclient完成了对connection的控制

但是上面的方法都没有涉及连接的设置,这里提供一些参数可以进行设置通过HttpParam设置

参数 描述
CoreConnectionPNames.SO_TIMEOUT='http.socket.timeout' 等待数据的最大时间,也就是两段连续数据读取之间的间隔
CoreConnectionPNames.TCP_NODELAY='http.tcp.nodelay' bool值,设置是否应用Naple算法,该算法最小化发送的包数,因此每个包很大,占带宽,有延迟
CoreConnectionPNames.SOCKET_BUFFER_SIZE='http.socket.buffer-size' 设置接发数据的缓冲区大小
CoreConnectionPNames.SO_LINGER='http.socket.linger' ...
CoreConnectionPNames.CONNECTION_TIMEOUT='http.connection.timeout' 设置连接超时
CoreConnectionPNames.STALE_CONNECTION_CHECK='http.connection.stalecheck' ...
CoreConnectionPNames.MAX_LINE_LENGTH='http.connection.max-line-length' 设置每行最大长度
CoreConnectionPNames.MAX_HEADER_COUNT='http.connection.max-header-count' 设置头最大数量
ConnConnectionPNames.MAX_STATUS_LINE_GARBAGE='http.connection.max-status-line-garbage' ...

(8)实际应用的中,从连接池里获取连接是比较好的方法,连接池负责管理连接。

   
   
   
   
  1. BasicClientConnectionManager man=new BasicClientConnectionManager();//最基本的连接池,一次只维护一个连接 
  2.  
  3. System.out.println(httpclient.getConnectionManager().getClass());//输出class org.apache.http.impl.conn.BasicClientConnectionManager 
  4.  
  5.  
  6.  
  7. //下面采用PoolingClientConnectionManager连接池管理,该连接池支持多线程操作     
  8.  
  9.    if(httpConnManger==null
  10.  
  11.   { 
  12.  
  13.      SchemeRegistry schemeRegistry = new SchemeRegistry(); 
  14.  
  15.      schemeRegistry.register( 
  16.  
  17.   new Scheme("http"80, PlainSocketFactory.getSocketFactory())); 
  18.  
  19.    httpConnManger=new PoolingClientConnectionManager(schemeRegistry); 
  20.  
  21.    httpConnManger.setMaxTotal(10); 
  22.  
  23.    httpConnManger.setDefaultMaxPerRoute(20); 
  24.  
  25.  
  26.  HttpParams params=new BasicHttpParams(); 
  27.  
  28.  params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIME); 
  29.  
  30.  HttpClient httpClient=new DefaultHttpClient(httpConnManger,params); 
  31.  
  32.  HttpGet httpGet=new HttpGet(urlAddr); 
  33.  
  34.  HttpResponse response; 
  35.  
  36. try { 
  37.  
  38.   response = httpClient.execute(httpGet); 
  39.  
  40. catch (ClientProtocolException e) { 
  41.  
  42.   log.error(e.getMessage()); 
  43.  
  44.  return null
  45.  
  46. catch (IOException e) { 
  47.  
  48.   log.error(e.getMessage()); 
  49.  
  50.  return null
  51.  

(9)需要代理的请求,设置HttpProxy

   
   
   
   
  1. HttpHost proxy = new HttpHost("127.0.0.1"8080"http"); 
  2.  
  3. DefaultHttpClient httpclient = new DefaultHttpClient(); 
  4.  
  5. httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 
  6.  
  7. HttpHost target = new HttpHost("issues.apache.org"443"https"); 
  8.  
  9. HttpGet req = new HttpGet("/"); 
  10.  
  11. System.out.println("executing request to " + target + " via " + proxy); 
  12.  
  13. HttpResponse rsp = httpclient.execute(target, req); 
  14.  
  15. HttpEntity entity = rsp.getEntity(); 

(10)需要登录验证的请求

   
   
   
   
  1. httpclient.getCredentialsProvider().setCredentials( 
  2.  
  3.                   new AuthScope("localhost"443), 
  4.  
  5.                   new UsernamePasswordCredentials("username""password")); 
  6.  
  7.  
  8.  
  9.            HttpGet httpget = new HttpGet("https://localhost/protected"); 
  10.  
  11.  
  12.  
  13.            System.out.println("executing request" + httpget.getRequestLine()); 
  14.  
  15.            HttpResponse response = httpclient.execute(httpget); 
  16.  
  17.            HttpEntity entity = response.getEntity(); 
  18.  
  19.  
  20.  
  21.            System.out.println("----------------------------------------"); 
  22.  
  23.            System.out.println(response.getStatusLine()); 
  24.  
  25.           if (entity != null) { 
  26.  
  27.                System.out.println("Response content length: " + entity.getContentLength()); 
  28.  
  29.           } 
  30.  
  31.            EntityUtils.consume(entity);