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. System.out.println(entity.getContentType());
  3. System.out.println(entity.getContentLength());
  4. 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. FileEntity fileEntity=new FileEntity(file, ContentType.create("text/plain""UTF-8"));//文件内容输入
  4. List<NameValuePair> formparams = new ArrayList<NameValuePair>();
  5. formparams.add(new BasicNameValuePair("param1""value1"));
  6. formparams.add(new BasicNameValuePair("param2""value2"));
  7. UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8");//form表单内容输入
  8. HttpPost post=new HttpPost("http://www.baidu.com");
  9. post.setEntity(fileEntity);

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

  1. ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {
  2. public byte[] handleResponse(
  3. HttpResponse response) throws ClientProtocolException, IOException {
  4. HttpEntity entity = response.getEntity();
  5. if (entity != null) {
  6. return EntityUtils.toByteArray(entity);
  7. else {
  8. return null;
  9. }
  10. }
  11. };
  12. byte[] response = httpclient.execute(httpget, handler);
  13. ResponseHandler<String> handler1=new BasicResponseHandler();
  14. 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. HttpVersion.HTTP_1_0); // Default to HTTP 1.0
  3. httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,
  4. "UTF-8");
  5. HttpGet httpget = new HttpGet("http://www.google.com.hk/");
  6. httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
  7. HttpVersion.HTTP_1_1); // Use HTTP 1.1 for this request only
  8. httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,
  9. 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. System.out.println(httpclient.getConnectionManager().getClass());//输出class org.apache.http.impl.conn.BasicClientConnectionManager
  3. //下面采用PoolingClientConnectionManager连接池管理,该连接池支持多线程操作    
  4. if(httpConnManger==null)
  5. {
  6. SchemeRegistry schemeRegistry = new SchemeRegistry();
  7. schemeRegistry.register(
  8. new Scheme("http"80, PlainSocketFactory.getSocketFactory()));
  9. httpConnManger=new PoolingClientConnectionManager(schemeRegistry);
  10. httpConnManger.setMaxTotal(10);
  11. httpConnManger.setDefaultMaxPerRoute(20);
  12. }
  13. HttpParams params=new BasicHttpParams();
  14. params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIME);
  15. HttpClient httpClient=new DefaultHttpClient(httpConnManger,params);
  16. HttpGet httpGet=new HttpGet(urlAddr);
  17. HttpResponse response;
  18. try {
  19. response = httpClient.execute(httpGet);
  20. catch (ClientProtocolException e) {
  21. log.error(e.getMessage());
  22. return null;
  23. catch (IOException e) {
  24. log.error(e.getMessage());
  25. return null;
  26. }

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

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

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

  1. httpclient.getCredentialsProvider().setCredentials(
  2. new AuthScope("localhost"443),
  3. new UsernamePasswordCredentials("username""password"));
  4. HttpGet httpget = new HttpGet("https://localhost/protected");
  5. System.out.println("executing request" + httpget.getRequestLine());
  6. HttpResponse response = httpclient.execute(httpget);
  7. HttpEntity entity = response.getEntity();
  8. System.out.println("----------------------------------------");
  9. System.out.println(response.getStatusLine());
  10. if (entity != null) {
  11. System.out.println("Response content length: " + entity.getContentLength());
  12. }
  13. EntityUtils.consume(entity);