`
ithero
  • 浏览: 143410 次
社区版块
存档分类
最新评论

httpclient总结

    博客分类:
  • J2EE
阅读更多

httpclient的一些学习心得
最近忙于一个项目,了解下httpclient,在这里总结出来,和大家一起学习分享,希望各位朋友提出宝贵的意见。

首先介绍一下项目的背景:
  目标:把国内一家保险公司的“WEB一账通”改成“WAP一账通”。
  资源:客户不提供任何的webservice接口。
  
本项目中用到的第三方组件是apache的httpclient,一个非常强大的网页抓取工具(抓这个字用得可能不太好), 这里和大家
一起讨论下httpclient的一些常用用法和要注意的地方。

本文引用的资源列表:

  httpclient入门:  http://www.ibm.com/developerworks/cn/opensource/os-httpclient/
  httpclient证书导入:http://www.blogjava.net/happytian/archive/2006/12/22/89447.html
  httpclient高级认识:http://laohuang.iteye.com/blog/55613
  httpclient官方文档:http://hc.apache.org/httpcomponents-client/index.html
  httpclient资源关闭:http://www.iteye.com/topic/234759
  
  
上面的文章写得很好,看完之后也就知道怎么用httpclient这个很好的工具了,但是在这里还是补充一些比较重要的东西,也是项目中经
常碰到的问题。

首先要注意的有以下几点:
1、httpclient连接后资源释放问题很重要,就跟我们用database connection要释放资源一样。
2、https网站采用ssl加密传输,证书导入要注意。
3、做这样的项目最好先了解下http协义,比如302,301,200,404返回代码的含义(这是最基本的),cookie,session的机制。
4、httpclient的redirect状态默认是自动的,这在很大程度上给开发者很大的方便(如一些授权获得cookie),但是有时要手动管理下,比如
  有时会遇到CircularRedirectException异常,出现这样的情况是因为返回的头文件中location值指向之前重复(端口号可以不同)地址,导致可能会出现死
  循环递归重定向,这时可以手动关闭:method.setFollowRedirects(false)
5、有的网站会先判别用户的请求是否是来自浏览器,如不是,则返回不正确的文本,所以用httpclient抓取信息时在头部加入如下信息:
  header.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 1.7; .NET CLR 1.1.4322; CIBA; .NET CLR 2.0.50727)");
6、当post请求提交数据时要改变默认编码,不然的话提交上去的数据会出现乱码。重写postMethod的setContentCharSet()方法就可以了:

 

 

  
下面写一个通用类来处理request请求返回的文本:

/*
 * HttpRequestProxy.java
 *
 * Created on November 3, 2008, 9:53 AM
 */

package cn.com.mozat.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

import cn.com.mozat.exception.CustomException;

/**
 * 
 * @author bird  email:lihongfu-84@163.com
 *
 * 2008-11-4  09:49:48
 */
public class HttpRequestProxy{
    //超时间隔
    private static int connectTimeOut = 60000;
 //让connectionmanager管理httpclientconnection时是否关闭连接
    private static boolean alwaysClose = false;
 //返回数据编码格式
    private String encoding = "UTF-8";
    
    private final HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));
 
    public HttpClient getHttpClient(){
        return client;
    }
      
    /**
     * 用法:
     * HttpRequestProxy hrp = new HttpRequestProxy();
     * hrp.doRequest("http://www.163.com",null,null,"gbk");
     * 
     * @param url  请求的资源URL
     * @param postData  POST请求时form表单封装的数据 没有时传null
     * @param header   request请求时附带的头信息(header) 没有时传null
     * @param encoding response返回的信息编码格式 没有时传null
     * @return  response返回的文本数据
     * @throws CustomException 
     */
    public String doRequest(String url,Map postData,Map header,String encoding) throws CustomException{
     String responseString = null;
     //头部请求信息
     Header[] headers = null;
     if(header != null){
      Set entrySet = header.entrySet();
         int dataLength = entrySet.size();
          headers= new Header[dataLength];
         int i = 0;
         for(Iterator itor = entrySet.iterator();itor.hasNext();){
          Map.Entry entry = (Map.Entry)itor.next();
          headers[i++] = new Header(entry.getKey().toString(),entry.getValue().toString());
         }
     }
     //post方式
        if(postData!=null){
         PostMethod postRequest = new PostMethod(url.trim());
         if(headers != null){
          for(int i = 0;i < headers.length;i++){
           postRequest.setRequestHeader(headers[i]);
          }
         }
         Set entrySet = postData.entrySet();
         int dataLength = entrySet.size();
         NameValuePair[] params = new NameValuePair[dataLength];
         int i = 0;
         for(Iterator itor = entrySet.iterator();itor.hasNext();){
          Map.Entry entry = (Map.Entry)itor.next();
          params[i++] = new NameValuePair(entry.getKey().toString(),entry.getValue().toString());
         }
         postRequest.setRequestBody(params);
         try {
    responseString = this.executeMethod(postRequest,encoding);
   } catch (CustomException e) {
    throw e;
   } finally{
    postRequest.releaseConnection();
   }
        }
      //get方式
        if(postData == null){
         GetMethod getRequest = new GetMethod(url.trim());
         if(headers != null){
          for(int i = 0;i < headers.length;i++){
           getRequest.setRequestHeader(headers[i]);
          }
         }
         try {
    responseString = this.executeMethod(getRequest,encoding);
   } catch (CustomException e) {
                e.printStackTrace();
    throw e;
   }finally{
    getRequest.releaseConnection();
   }
        }
 
        return responseString;
    }

 private String executeMethod(HttpMethod request, String encoding) throws CustomException{
  String responseContent = null;
  InputStream responseStream = null;
  BufferedReader rd = null;
  try {
   this.getHttpClient().executeMethod(request);
   if(encoding != null){
    responseStream = request.getResponseBodyAsStream();
     rd = new BufferedReader(new InputStreamReader(responseStream,
                      encoding));
              String tempLine = rd.readLine();
              StringBuffer tempStr = new StringBuffer();
              String crlf=System.getProperty("line.separator");
              while (tempLine != null)
              {
                  tempStr.append(tempLine);
                  tempStr.append(crlf);
                  tempLine = rd.readLine();
              }
              responseContent = tempStr.toString();
   }else
    responseContent = request.getResponseBodyAsString();
           
   Header locationHeader = request.getResponseHeader("location");
   //返回代码为302,301时,表示页面己经重定向,则重新请求location的url,这在
   //一些登录授权取cookie时很重要
   if (locationHeader != null) {
             String redirectUrl = locationHeader.getValue();
             this.doRequest(redirectUrl, null, null,null);
         }
  } catch (HttpException e) {
   throw new CustomException(e.getMessage());
  } catch (IOException e) {
   throw new CustomException(e.getMessage());

  } finally{
   if(rd != null)
    try {
     rd.close();
    } catch (IOException e) {
     throw new CustomException(e.getMessage());
    }
    if(responseStream != null)
     try {
      responseStream.close();
     } catch (IOException e) {
      throw new CustomException(e.getMessage());

     }
  }
  return responseContent;
 }
 
   
 /**
  * 特殊请求数据,这样的请求往往会出现redirect本身而出现递归死循环重定向
  * 所以单独写成一个请求方法
  * 比如现在请求的url为:http://localhost:8080/demo/index.jsp
  * 返回代码为302 头部信息中location值为:http://localhost:8083/demo/index.jsp
  * 这时httpclient认为进入递归死循环重定向,抛出CircularRedirectException异常
  * @param url
  * @return
  * @throws CustomException 
  */
 public String doSpecialRequest(String url,int count,String encoding) throws CustomException{
  String str = null;
  InputStream responseStream = null;
  BufferedReader rd = null;
  GetMethod getRequest = new GetMethod(url);
  //关闭httpclient自动重定向动能
  getRequest.setFollowRedirects(false);
  try {
   
   this.client.executeMethod(getRequest);
   Header header = getRequest.getResponseHeader("location");
   if(header!= null){
    //请求重定向后的URL,count同时加1
    this.doSpecialRequest(header.getValue(),count+1, encoding);
   }
   //这里用count作为标志位,当count为0时才返回请求的URL文本,
   //这样就可以忽略所有的递归重定向时返回文本流操作,提高性能
   if(count == 0){
    getRequest = new GetMethod(url);
    getRequest.setFollowRedirects(false);
    this.client.executeMethod(getRequest);
    responseStream = getRequest.getResponseBodyAsStream();
    rd = new BufferedReader(new InputStreamReader(responseStream,
                      encoding));
             String tempLine = rd.readLine();
             StringBuffer tempStr = new StringBuffer();
             String crlf=System.getProperty("line.separator");
             while (tempLine != null)
             {
                 tempStr.append(tempLine);
                 tempStr.append(crlf);
                 tempLine = rd.readLine();
             }
             str = tempStr.toString();
   }
   
  } catch (HttpException e) {
   throw new CustomException(e.getMessage());
  } catch (IOException e) {
   throw new CustomException(e.getMessage());
  } finally{
   getRequest.releaseConnection();
   if(rd !=null)
    try {
     rd.close();
    } catch (IOException e) {
     throw new CustomException(e.getMessage());
    }
    if(responseStream !=null)
     try {
      responseStream.close();
     } catch (IOException e) {
      throw new CustomException(e.getMessage());
     }
  }
  return str;
 }
 
 
 
 
 public static void main(String[] args) throws Exception{
  HttpRequestProxy hrp = new HttpRequestProxy();
   Map header = new HashMap();
         header.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 1.7; .NET CLR 1.1.4322; CIBA; .NET CLR 2.0.50727)");
  String str = hrp.doRequest("http://www.cma-cgm.com/en/eBusiness/Tracking/Default.aspx?BolNumber=GZ2108827", null, header,null);
  System.out.println(str.contains("row_CRXU1587647"));
//  System.out.println(str);
 }
   
}

分享到:
评论

相关推荐

    HttpClient总结.doc

    借助Java Secure Socket Extension (JSSE),HttpClient全面支持Secure Sockets Layer (SSL)或IETF Transport Layer Security (TLS)协议上的HTTP。

    HttpClient学习总结.docx

    HttpClient学习总结.docx

    [享学Feign] 九、Feign + OkHttp和Feign + Apache HttpClient哪个更香?

    目录前言正文OkHttp使用示例源码解析Apache HttpClient使用示例源码解析GoogleHttpClient哪个更香?总结声明 前言 前八篇文章介绍完了feign-core核心内容,从本篇开始将介绍它的“其它模块”。其实核心模块可以独立...

    C#HTTPclient 实例应用

    学习C#必经之路,入门级知识总结,笔记本知识概况,走一步再走一步

    HttpClient PostMethod 上传文件

    本人自己总结的httpClient PostMethod 上传文件完整实例 以及 使用java PostMethod 和GetMethod 发送请求实例 及乱码处理

    httpclient4

    httpclient,关于模拟登录的问题。从网站上下载下来的,归于一个总结

    使用 HttpClient 和 HtmlParser 实现简易爬虫

    使用HttpClient和HtmlParser实现网页爬虫,这个文档是我在学习使用后的总结,希望能帮助需要正在学习这方面的同学,能够更快的入门,以及一些更深入的了解。

    详解使用angular的HttpClient搭配rxjs

    一、原Http使用总结 使用方法 1.在根模块或核心模块引入HttpModule 即在AppModule或CoreModule中引入HttpModule: import { HttpModule } from '@angular/http'; @NgModule({ import: [ HttpModule ] // ... })...

    HTTP Client请求公共方法HttpUtils

    不同的服务,不同的系统之前的数据交互是在所难免的, HttpClient在不同的服务之前请求数据使用广泛,而且也会有各种各样的问题,SO 总结一些公共方法,避免重复造车

    android开发常用网络样例总结

    分别使用6个框架HttpURLConnection、HttpClient、AndroidAsyncHttp、Volley、OkHttp、Retrofit2 包中有服务器数据,可做样例数据使用 详细总结:http://blog.csdn.net/ahmclishihao/article/details/52861285#t0

    WebSerices异步调用方法总结

    研究Webservice异步调用的实现, 1、通过异步调用的方式实现高性能的使用WebService的API

    java研究室,包含了各种小程序:文件上传,httpclient操作,数据库访问,图片操作等,方便在工作中快速取用.zip

    总结来说,【小程序名称】凭借其小巧便携、快捷高效的特性,不仅节省了用户的手机存储空间,更为用户提供了无缝衔接的便利服务,是现代生活中不可或缺的一部分,真正实现了“触手可及”的智能生活新体验。...

    BSP Async SSP ASP 的比较

    分布式机器学习四种同步机制的简单总结,包括BSP(Bulk Synchronous Parallel)批量同步并行、Async(Asynchronous Parallel)全异步并行、SSP(Stale Synchronous Parallel)延迟同步并行、ASP大概同步并行。

    PB_WinCE.rar_Platform Builder 5_platform builder_wince fat_windo

    5 总结 9 Platform Builder之旅(一) 10 Platform Builder之旅(二) 12 Platform Builder之旅(三) 15 一、源码配置文件 15 二、镜像配置文件: 16 Platform Builder之旅(四) 22 【Windows CE安装目录】 22 ...

    最常用的java技术总结

    本xmind包含:Springmvc,Mybatis,HttpClient,shiro,redis,Mysql,Elasticsearch,ActiveMQ,nginx,SpringTest,jsonp,阿里大鱼,echarts/higcharte

    java 网络及通信

    java网络及通信、httpClient、socket通信、HttpURLConnection、java 中常用的几种网络通信方式。在此总结、希望对需要的同仁有所帮助。

    手把手从零搭建新冠疫情防控指挥作战平台视频教程

    3,综合运用HttpClient+Jsoup+Kafka+SparkStreaming+StructuredStreaming+SpringBoot+Echarts等多种实用技术 适用人群 1、对大数据感兴趣的在校生及应届毕业生。 2、对目前职业有进一步提升要求,希望从事大数据...

    Android开发技巧总汇(个人总结)

    17.通过HttpClient从指定server获取数据 22 18.拖动Button获得位置 23 19.代码安装apk包 25 20.给模拟器打电话发短信 26 21.从google搜索内容 26 22.浏览网页 26 23.显示地图 26 25.拨打电话 27 26.调用发...

    Android使用http协议与服务器通信的实例

    因此,自己对此做了些总结,给出了我的一个解决方案。 首先,需要明确一下http通信流程,Android目前提供两种http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较...

    文件上传源码 客户端服务端

    socket httpclient 这个功能经常需要用到,索性完整的总结一下,包括客户端服务端,上传至sae

Global site tag (gtag.js) - Google Analytics