转自http://blog.163.com/liu-xian-xian/blog/static/57198219200911165825587/
HttpClient 功能介绍
(1)实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
(2)支持自动转向
(3)支持 HTTPS 协议
(4)支持代理服务器等
HttpClient 基本功能的使用:共要3个Jar包 commons-codec.jar commons-httpclient.jar commons-logging.jar
(1) GET方法
使用 HttpClient 需要以下 6 个步骤:
1. 创建 HttpClient 的实例
HttpClient httpClient = new HttpClient();
GetMethod method =null
2. 创建某种连接方法的实例。在构造函数中传入待连接的地址
method=new GetMethod(url);
3. 调用HttpClient的 execute 方法来执行GetMethod 实例
int retcode = httpClient.executeMethod(method);
if (retcode != HttpStatus.SC_OK) {// 发送不成功
facesMessages.add("查询出错不成功");
} else {
4. 读 response —— body = method.getResponseBodyAsString();
}
5. 释放连接。无论执行方法是否成功,都必须释放连接
if (method != null) {
method.releaseConnection();
}
6. 对得到后的内容进行处理
备注:
httpClient.getParams().setBooleanParameter("http.protocol.expect-continue", false); method.setRequestHeader("Connection", "close"); //解决Httpclient远程请求所造成Socket没有释放
method=new GetMethod(url);
method.addRequestHeader("Accept", "text/plain");
method.addRequestHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
(2)POST方法
POST方法用来向目的服务器发出请求,要求它接受被附在请求后的实体,并把它当作请求队列(Request-Line)中请求URI所指定资源的附加新子项。POST被设计成用统一的方法实现下列功能:
对现有资源的注释(Annotation of existing resources)
向电子公告栏、新闻组,邮件列表或类似讨论组发送消息
提交数据块,如将表单的结果提交给数据处理过程
通过附加操作来扩展数据库
1. 创建 HttpClient 的实例
HttpClient httpClient = new HttpClient();
PostMethod postMethod=null;
2. 创建某种连接方法的实例。在构造函数中传入待连接的地址
method=new GetMethod(url);
填入各个表单域的值
NameValuePair[] data = { new NameValuePair("id", "youUserName"),
new NameValuePair("passwd", "yourPwd") };
将表单的值放入postMethod中
postMethod.setRequestBody(data);
3. 调用HttpClient的 execute 方法来执行PostMethod实例
int statusCode = httpClient.executeMethod(method);
if (statusCode!= HttpStatus.SC_OK) {// 发送不成功
facesMessages.add("查询出错不成功");
} else {
4. 读 response —— body = method.getResponseBodyAsString();
}
5. 释放连接。无论执行方法是否成功,都必须释放连接
if (method != null) {
method.releaseConnection();
}
6. 对得到后的内容进行处理
备注:
HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发 // 301或者302
if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {// 从头中取出转向的地址
Header locationHeader = postMethod.getResponseHeader("location");
String location = null;
if (locationHeader != null) {
location = locationHeader.getValue();
System.out.println("The page was redirected to:" + location);
} else {
System.err.println("Location field value is null.");
}
return;
}
3使用HttpClient过程中常见的一些问题
字符编码
通过method对象的getResponseCharSet()方法就可以得到http头中的编码信息
自动转向
根据RFC2616中对自动转向的定义,主要有两种:301和302。301表示永久的移走 (Moved Permanently),当返回的是301,则表示请求的资源已经被移到一个固定的新地方,任何向该地址发起请求都会被转到新的地址上。302表示暂时 的转向,比如在服务器端的servlet程序调用了sendRedirect方法,则在客户端就会得到一个302的代码,这时服务器返回的头信息中 location的值就是sendRedirect转向的目标地址。
HttpClient支持自动转向处理,但是象POST和PUT方式这种要求接受后继服务的请求方式,暂时不支持自动转向,因此如果碰到POST方式提交 后返回的是301或者302的话需要自己处理。就像刚才在POSTMethod中举的例子:如果想进入登录BBS后的页面,必须重新发起登录的请求,请求的地址可以在头字段location中得到。不过需要注意的是,有时候location返回的可能是相对路径,因此需要对location返回的值做一些 处理才可以发起向新地址的请求。
另外除了在头中包含的信息可能使页面发生重定向外,在页面中也有可能会发生页面的重定向。引起页面自动转发的标签是:<meta http-equiv="refresh" content="5; url=....">。如果你想在程序中也处理这种情况的话得自己分析页面来实现转向。需要注意的是,在上面那个标签中url的值也可以是一个相对 地址,如果是这样的话,需要对它做一些处理后才可以转发
5 处理代理服务器
HttpClient中使用代理服务器非常简单,调用HttpClient中setProxy方法就可以,方法的第一个参数是代理服务器地址,第二个参数是端口号。另外HttpClient也支持SOCKS代理。
httpClient.getHostConfiguration().setProxy(hostName,port);
扩展阅读:
1.http://hc.apache.org/httpclient-3.x/ HttpClient官方网站
2.http://jakarta.apache.org/commons/httpclient/ HttpClient首页
3.http://hc.apache.org/downloads.cgi HttpClient下载
4.http://www.leadtoit.cn/subject.php?id=6 力度IT网HttpClient专题
5.http://www.blogjava.net/Alpha/archive/2007/01/22/95216.html HttpClient 学习整理
6.http://www.ibm.com/developerworks/cn/opensource/os-httpclient/ HttpClient入门
7.http://blog.csdn.net/ambitiontan/archive/2006/01/06/572171.aspx 应用HttpClient来对付各种顽固的WEB服务器
8.http://www.pmjava.com/Article/ShowInfo.asp?ID=2147 httpclient 4.0的例子
实例 :
private void send(String url,String requestXml){
String body = "";
PostMethod postMethod=null;
try {
HttpClient httpClient = new HttpClient();
httpClient.getParams().setBooleanParameter("http.protocol.expect-continue", false);
postMethod=new PostMethod(url);
NameValuePair[] dataxml = { new NameValuePair("data", requestXml)};
postMethod.setRequestBody(dataxml);
postMethod.addRequestHeader("Accept", "text/plain");
postMethod.addRequestHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
postMethod.setRequestHeader("Connection", "close");
int retcode = httpClient.executeMethod(postMethod);
if (retcode != HttpStatus.SC_OK) {// 发送不成功
facesMessages.add("查询出错不成功");
} else {
body = postMethod.getResponseBodyAsString();
if ("201".equals(body) ) {
facesMessages.add("您对编号为" + complaint.getNumber() + "的投诉做“待改进”操作成功,即发送其到了QSI系统!!");
} else {
facesMessages.add("您对编号为" + complaint.getNumber() + "的投诉做“待改进”操作失败!!");
}
}
} catch (Exception e) {
facesMessages.add("对不起,由于发生某种异常而未能正常查询订单信息。请重新再试!!!");
log.error("", e, "");
}finally{
if (postMethod != null) {
postMethod.releaseConnection();
}
}
}