本文介绍如何利用apache的HttpClient包进行http操作,包括get操作和post操作。

一、下面的代码是对HttpClient包的封装,以便于更好的编写应用代码。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map; import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.lang.StringUtils; public class MyHttpClient {
private HttpClient httpClient;
private String cookies; public MyHttpClient(String ip) {
this(ip, 80);
} public MyHttpClient(String ip, int port) {
httpClient = new HttpClient();
httpClient.getHostConfiguration().setHost(ip, port, "http");
httpClient.getParams().setCookiePolicy(
CookiePolicy.BROWSER_COMPATIBILITY);
} public String getCookies(){
return cookies;
} public void setCookies(String cookies){
this.cookies = cookies;
} public String doGet(String url) throws IOException{
return doGet(url,null);
} public String doGet(String url, String paras) throws IOException {
GetMethod method = new GetMethod(url);
if (StringUtils.isNotBlank(paras)) {
method.setQueryString(URIUtil.encodeQuery(paras));
}
return sendRequest(method);
} public String doPost(String url) throws IOException{
return doPost(url,new HashMap<String,String>());
} public String doPost(String url, String paras) throws IOException {
Map<String,String> paraMap = new HashMap<String,String>();
String[] values = paras.split("&");
for(String value:values){
String[] item = value.split("=");
if(item.length==2){
paraMap.put(item[0].trim(), item[1].trim());
}
}
return doPost(url,paraMap);
} public String doPost(String url, Map<String,String> paras) throws IOException{
int index=0;
NameValuePair[] data = new NameValuePair[paras.size()];
for(Map.Entry<String,String> entry:paras.entrySet()){
data[index++] = new NameValuePair(entry.getKey(),entry.getValue());
}
return doPost(url,data);
} private String doPost(String url, NameValuePair[] data) throws IOException{
PostMethod method = new PostMethod(url);
method.setRequestBody(data);
method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
return sendRequest(method);
} private String sendRequest(HttpMethod method) throws IOException{
StringBuffer response = new StringBuffer();
try {
method.setRequestHeader("Cookie", cookies);
httpClient.executeMethod(method); if (method.getStatusCode() == HttpStatus.SC_OK) {
response.append(getResponseBody(method));
}else if(method.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY){
//302 重定向
response.append(getResponseHeader(method));
}else {
System.out.println("response statuscode : "
+ method.getStatusCode());
throw new IllegalStateException("response statuscode : "
+ method.getStatusCode());
}
fetchCookies();
}finally {
method.releaseConnection();
}
return response.toString();
} private void fetchCookies(){
Cookie[] values = httpClient.getState().getCookies();
StringBuffer cookieBuffer = new StringBuffer();
for (Cookie c : values)
{
cookieBuffer.append(c.toString()).append(";");
}
cookies = cookieBuffer.toString();
} private String getResponseBody(HttpMethod method) throws IOException, IOException {
StringBuffer response = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
response.append(line).append(
System.getProperty("line.separator"));
}
}finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
return response.toString();
} private String getResponseHeader(HttpMethod method){
StringBuffer response = new StringBuffer();
Header[] headers = method.getResponseHeaders();
for(Header header:headers){
String line = header.getName()+" : "+header.getValue();
response.append(line);
response.append(System.getProperty("line.separator"));
}
return response.toString();
} }

说明:上面代码中doGet方法中的 语句 String encodeQuery = URIUtil.encodeQuery(paras);

存在一点问题,当url部门有特殊字符,如空格、+ 号等,这些字符需要被编码。

这时需要换成 String encodeQuery = URIUtil.encodePath(paras); 语句,即用encodePath方法替代encodeQuery方法。

二、下面来进行实际的使用举例

1、简单的get操作

下面的代码完成对一个url的get操作。我们封装了两个doGet操作,一个是带参数的,一个是不带参数的。待参数的参数格式如 name1=value1&name2=value2

MyHttpClient httpClient = new MyHttpClient("xxxx");  //xxxx是web服务器的地址
  String result = httpClient.doGet(url);  //url是请求的url地址
  System.out.println(result);

2、简单的post操作

下面的代码完成对一个url的post操作.

MyHttpClient httpClient = new MyHttpClient("localhost");
Map<String,String> paras = new HashMap<String,String>();
paras.put("para1", "value1");
paras.put("para2", "value2"); String result = httpClient.doPost(url,paras);
System.out.println(result);

3、有重定向的get操作

如果发起的一个get操作,被服务器重定向到一个新的url。这时我们封装的doGet操作返回的是新的url(重定向后的)对应的信息。

4、有重定向的post操作

如果发起的一个post操作,被服务器重定向到一个新的url。我们封装的doPost操作,与doGet操作返回的结果不同,doPost是返回重定向头信息,而不是新的url的信息。如返回如下的信息,其中Location对应的值login就是重定向的url

Server : Apache-Coyote/1.1
Set-Cookie : JSESSIONID=8115A882086E7F27809FDF24213F82F5; Path=/boot/; HttpOnly
Set-Cookie :Expires=Thu, 01-Jan-1970 00:00:10 GMT
Location : login
Content-Length : 0
Date : Sat, 09 Jan 2016 07:41:21 GMT

5、需要登录的请求

有的web服务器有鉴权功能,当发起一个请求时,如果在该请求之前还没有登录,会自动重定向到登录页面,登录成功后才会跳转到想要请求的页面。

这时代码应该这样写:

MyHttpClient httpClient = new MyHttpClient("localhost");
//下面是登录请求
httpClient.doPost(loginUrl,"username=xxx&password=yyy");
//因为前面已经登录,下面的url将不会发生重定向。而是返回该url对应页面的本身信息。
String result = httpClient.doGet(url);
System.out.println(result);

6、与cookie有关的请求

有的web应用中,用到了cookie。所谓的cookie,就是希望浏览器操作关闭后,会在浏览器本地客户端机器上记录下一些信息。当下次打开浏览器,操作相关的页面后,这些信息能被带到服务器。我们封装的这个功能对此也支持。具体通过例子说明:

MyHttpClient httpClient = new MyHttpClient("localhost");
//下面的操作,会产生cookie
httpClient.doPost(url,paras);
//获取本次会话产生的cookie
String cookies = httpClient.getCookies(); //开启一个新的会话
MyHttpClient otherHttpClient = new MyHttpClient("localhost");
//将上次会话的cookie设置到本次会话中,以便于cookie能带到服务器
otherHttpClient.setCookies(cookies);
//这次请求就会上个会话产生的cookie带到服务器
String result = otherHttpClient.doGet(otherUrl);
System.out.println(result);

三、小结

我们封装的这个httpclient类,可以很方便的完成http请求的一些基本操作。并且对有鉴权控制、cookie功能的网站也能较好的满足。

Java网络编程:利用apache的HttpClient包进行http操作的更多相关文章

  1. Java网络编程基础之TCP粘包拆包

    TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想象河里的流水,他们是连成一片的,其间并没有分界线.TCP底层并不了解上层业务数据的具体含义,他会根据TCP缓冲区的实 ...

  2. Java网络编程和NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector

    Java网络编程与NIO详解4:浅析NIO包中的Buffer.Channel 和 Selector 转自https://www.javadoop.com/post/nio-and-aio 本系列文章首 ...

  3. java网络编程socket解析

    转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...

  4. java网络编程框架

    虽然写过一些网络编程方面的东西,但还没有深入研究过这方面的内容,直接摘录一些文章,后续整理 原文地址:http://blog.csdn.net/lwuit/article/details/730613 ...

  5. Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型

    本文转自:http://www.sohu.com/a/203838233_827544 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 ht ...

  6. 20145212 实验五《Java网络编程》

    20145212 实验五<Java网络编程> 一.实验内容 1.运行下载的TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成 ...

  7. java 网络编程复习(转)

    好久没有看过Java网络编程了,现在刚好公司有机会接触,顺便的拾起以前的东西 参照原博客:http://www.cnblogs.com/linzheng/archive/2011/01/23/1942 ...

  8. java网络编程serversocket

    转载:http://www.blogjava.net/landon/archive/2013/07/24/401911.html Java网络编程精解笔记3:ServerSocket详解ServerS ...

  9. 20145210实验五《Java网络编程》

    20145210实验五<Java网络编程> 实验内容 1.运行下载的TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成代码, ...

随机推荐

  1. C/C++ 笔试、面试题目大汇总(转)

    这些东西有点烦,有点无聊.如果要去C++面试就看看吧.几年前网上搜索的.刚才看到,就整理一下,里面有些被我改了,感觉之前说的不对或不完善. 转自fangyukuan,地址http://www.cnbl ...

  2. VC获取屏幕分辨率大小

    //以下两个函数获取的是显示屏幕的大小,不包括任务栏等区域 int screenwidth=GetSystemMetrics(SM_CXFULLSCREEN); int screenheight=Ge ...

  3. Css小技巧-图片垂直居中

    说明:样式设置主要是针对图片的父级元素,并非图片元素本身. Css代码[图片父级点的样式]: <style> .box { /*非IE的主流浏览器识别的垂直居中的方法*/ display: ...

  4. JDBC_批量处理语句提高处理速度

    •当需要成批插入或者更新记录时.可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理.通常情况下比单独提交处理更有效率 •JDBC的批量处理语句包括下面两个方法: –addB ...

  5. SAN简介

    转自IBM资料库:https://community.emc.com/people/Jeffey/blog/2013/06/18/san%E5%8D%8F%E8%AE%AE SAN(Storage A ...

  6. 面向对象程序设计-C++ Finial exam review NOTES【第十六次上课笔记】

    写在前面: 我记得也不全,如果有记录的更全的同学可以留言,我会添加哒 :) 常量 内敛函数 为什么需要内敛函数 内敛函数适用于什么场合 内敛函数本身,最大优点是,避免了真正函数调用的开销 因为普通函数 ...

  7. hibernate 数据关联多对多 4.1

    多对多,必须有一张关系表来维持关系 数据库student,teacher student_teacher 三张表 但是在pojo中只需要建立student和teacher两个类,除非关系表也代表某种业 ...

  8. kinect for windows - DepthBasics-D2D详解之一

    Depth在kinect中经常被翻译为深度图,指的是图像到摄像头的距离,这些距离数据能让机器知道物理距离有多远.kinect通过两个红外摄像头来实现这个功能的.在这个例子里,就实现了深度图的提取和现实 ...

  9. Unity3D游戏开发之小地图的实现

    今天我们来讲一下在Unity3D中怎样实现小地图.首先,我们来一起看看终于实现的效果: 要实现小地图效果,须要实现对于小地图和角色的绘制,所以这里须要用到OnGUI()方法,我们一起来看代码: [cs ...

  10. android应用如何启动另外一个apk应用

    在开发的过程中,经常会遇到在一个应用中启动另外一个apk应用的情况 问题的核心点在于我们要拿到第三方apk的package名称跟class名称, 如:package名称是com.funcity.tax ...