20141030
这个大三的时候写的,现在看起来感觉多线程上有一些不足之处,如果大家觉得可以当作参考自己改改吧。
后注:
以下的代码是JRE用的,如果用在android要修改的,比如说UrlConnection.getContentLongLength是没有的,要改成getContentLength(),还有就是一些导入的包要删改。我已经改好了android的版本。就不发了
还有就是由于本人刚从C#转JAVA对于JAVA的异常了解的不够,直接在工具类里catch异常了,然后e.print....我以为和C#一样是可以把catch到的异常直接throw出来的,于是又进行了修改。使用了throws回避异常
修改后的包android 或 JRE的想要的mail 164858843@qq.com
最近想在android上写个使用到http协议的小程序,发现没封装过的写的代码太繁琐,就自己动手花了一天时间构思封装,方便http相关操作, 提供一系列同步 、异步的方法, 也有文件下载相关的同步、异步方法 ,所有的异步方法都提供一系列的回调接口,使用线程池,方便快捷~
总共有这么几个类
Cookies.java
这个是借鉴网上的管理cookie的方法,为了实现cookie的保持,sessionID的传送,所封装的一个管理cookie的类
HttpConnProp.java
这个是http发送请求时请求报文里要设置的相关参数,直接new一个对象就是我设置的默认参数
ReturnData.java
http返回数据的的封装,有一个String是html文档,有一个HttpConnProp对象是请求完成后更新后的属性对象,特别的cookie和Referer,都是跟新后的
只要把返回的新的HttpConnProp对象给下一个连接,就可以保持session
HttpHelper.java
主类,里面有各种各样的方法
先看看我写的的工具库部分方法的使用效果:
异步get,post测试
HttpHelper.AysnGetHtml("http://www.baidu.com",
HttpConnProp.getDefaultHttpConnProp(), "gb2312",
new HttpHelper.AsynExecuteCallBack() {
@Override
public void exceptionOccored(Exception e) {
// TODO Auto-generated method stub
}
@Override
public void beforeExecute() {
// TODO Auto-generated method stub
System.out.println("执行之前");
}
@Override
public void afterExecute(ReturnData rData) {
// TODO Auto-generated method stub
System.out.println("执行之后");
//System.out.print(rData.getHtmlData());
}
});
HttpHelper.AysnPostHtml("http://web.61166.com/member/index_doajax.php",
"fmdo=login&dopost=login&userid=zhaozeyang&pwd=wodemima",
new HttpConnProp(), "gb2312",
new HttpHelper.AsynExecuteCallBack() {
@Override
public void exceptionOccored(Exception e) {
// TODO Auto-generated method stub
}
@Override
public void beforeExecute() {
// TODO Auto-generated method stub
}
@Override
public void afterExecute(ReturnData rData) {
// TODO Auto-generated method stub
System.out.println(rData.getHtmlData());
}
});
HttpHelper.shutTheThreadPoolDown();//等待所有线程完成后关闭线程池服务

下载文件测试
HttpHelper.downLoadFile("http://avatar.youkuaiyun.com/B/7/7/1_zwl230631.jpg",
"g://rfegr22g.jpg");
//异步下载测试
HttpHelper.AsynDownLoadFile("http://61.164.109.222/2345.zip",
"g://112121.rar", new HttpHelper.asynDownLoadCallBack() {
@Override
public void duringDownLoad(long hasDownedByte, long FileLength) {
// TODO Auto-generated method stub
if(FileLength != 0 )
System.out.println("已下载"+hasDownedByte + "总数" + FileLength + "百分比" +
(double)hasDownedByte/FileLength*100 +"%");
else{
System.out.println("已下载"+hasDownedByte);
}
}
@Override
public void downLoadFinished() {
// TODO Auto-generated method stub
System.out.println("下载完成");
}
@Override
public void downLoadErrorOccured(Exception e) {
// TODO Auto-generated method stub
System.out.println("err");
}
@Override
public void beforeDownLoad() {
// TODO Auto-generated method stub
System.out.println("开始下载");
}
});

接下来为我写的类库代码:
Cookies.java
package cn.zzy;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/**
*
* Cookie的封装
*
*
*/
public class Cookies {
private HashMap<String, String> hashMap;
public Cookies() {
hashMap = new HashMap<String, String>();
}
/**
*
* @return 返回一个空的Cookies对象
*/
public static final Cookies getEmptyCookieObj() {
return new Cookies();
}
/**
*
* 清除 Cookies 里面的所有 Cookie 记录
*/
public void clear() {
hashMap.clear();
}
/**
*
* 根据 key 获取对应的 Cookie 值
*
*
*
* @param key
*
* 要获取的 Cookie 值的 key
*
* @return 如果不存在 key 则返回 null
*/
public String getCookie(String key) {
return hashMap.get(key);
}
/**
*
* 在 Cookies 里设置一个 Cookie
*
*
*
* @param key
*
* 要设置的 Cookie 的 key
*
* @param value
*
* 要设置的 Cookie 的 value
*/
public void putCookie(String key, String value) {
hashMap.put(key, value);
}
/**
*
* 在 Cookies 里面设置传入的 cookies
* 格式 key=value
*
*
* @param cookies
*/
public void putCookies(String cookies) {
if (cookies == null)
return;
String[] strCookies = cookies.split(";");
for (int i = 0; i < strCookies.length; i++) {
for (int j = 0; j < strCookies[i].length(); j++) {
if (strCookies[i].charAt(j) == '=') {
this.putCookie(
strCookies[i].substring(0, j),
strCookies[i].substring(j + 1,
strCookies[i].length()));
}
}
}
}
/**
*
* 获取 Cookies 的字符串
*/
@Override
public String toString() {
// TODO Auto-generated method stub
if (hashMap.isEmpty())
return "";
Set<Entry<String, String>> set = hashMap.entrySet();
StringBuilder sb = new StringBuilder(set.size() * 50);
for (Entry<String, String> entry : set) {
sb.append(String.format("%s=%s;", entry.getKey(), entry.getValue()));
}
sb.delete(sb.length() - 1, sb.length());
return sb.toString();
}
}
HttpConnProp.java
package cn.zzy;
/**
*
* http链接的相关属性类
*/
public class HttpConnProp {
private String CONTENT_TYPE;
private String ACCEPT;
private String USER_AGENT;
private boolean IS_KEEP_ALIVE;
private boolean IS_USE_CACHE;
private boolean IS_INSTANCE_FOLLOW_REDIRECTS;
private int TIMEOUT;
private String REFERER;
private Cookies COOKIES = null;
/**
* 以默认属性构造一个属性类
* 详细修改可自己调用set函数进行逐个修改
* 使用默认的话直接new就可以了
*/
public HttpConnProp(){
this.CONTENT_TYPE = "application/x-www-form-urlencoded";
this.ACCEPT = "*/*";
this.USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1";
this.IS_KEEP_ALIVE = true;
this.IS_USE_CACHE = false;
this.IS_INSTANCE_FOLLOW_REDIRECTS = true;
this.TIMEOUT = 300000;
this.REFERER = "";
COOKIES = Cookies.getEmptyCookieObj();
}
/**
* 获得一个以默认属性构造的本类对象
* 也可以直接new 一个无参数的的本类对象,也是默认参数的
* @return
* httpConnProp对象
*/
public static HttpConnProp getDefaultHttpConnProp() {
return new HttpConnProp();
}
/**
*
* @param hcp
* 待复制的对象
* @return
* 复制好后的对象
*/
public static HttpConnProp copy(HttpConnProp hcp){
HttpConnProp hcp2 = new HttpConnProp();
hcp2.setAccept(hcp.getAccept());
hcp2.setContentType(hcp.getContentType());
hcp2.setCookies(hcp.getCookies());
hcp2.setIsInstanceFollowRedirects(hcp.getIsInstanceFollowRedirects());
hcp2.setIsKeepAlive(hcp.getIsKeepAlive());
hcp2.setISUseCaches(hcp.getIsUseCaches());
hcp2.setReferer(hcp.getReferer());
hcp2.setTimeOut(hcp.getTimeOut());
hcp2.setUserAgent(hcp.getUserAgent());
return hcp2;
}
public String getContentType(){return this.CONTENT_TYPE;}
public void setContentType(String ContentType){this.CONTENT_TYPE = ContentType;}
public String getAccept(){return this.ACCEPT;}
public void setAccept(String Accept){this.ACCEPT = Accept;}
public String getUserAgent(){return this.USER_AGENT;}
public void setUserAgent(String UserAgent){this.USER_AGENT = UserAgent;}
public boolean getIsKeepAlive(){return this.IS_KEEP_ALIVE;}
public void setIsKeepAlive(boolean isKeepAlive){this.IS_KEEP_ALIVE = isKeepAlive;}
public boolean getIsUseCaches(){return this.IS_USE_CACHE;}
public void setISUseCaches(boolean ISUseCaches){this.IS_USE_CACHE = ISUseCaches;}
public boolean getIsInstanceFollowRedirects(){return this.IS_INSTANCE_FOLLOW_REDIRECTS;}
public void setIsInstanceFollowRedirects(boolean ISInstanceFollowRedirects){this.IS_INSTANCE_FOLLOW_REDIRECTS = ISInstanceFollowRedirects;}
public String getReferer(){return this.REFERER;}
public void setReferer(String referer){this.REFERER = referer;}
public int getTimeOut(){return this.TIMEOUT;}
public void setTimeOut(int timeout){this.TIMEOUT = timeout; }
public Cookies getCookies(){return this.COOKIES;}
public void setCookies(Cookies cookies) {this.COOKIES = cookies;}
}
ReturnData.java
package cn.zzy;
import java.io.UnsupportedEncodingException;
/**
* http请求后返回的东西的包装类
*
* @author zzy
*
*
*/
public class ReturnData {
private String htmlData;
private HttpConnProp updatedProp;
private String encoding;
/**
*
* @param red
* 返回的html信息
* @param hcp
* 更新后的HttpConnProp,特别是cookie
* @param encoding
* 返回的string的编码
*/
public ReturnData(String red, HttpConnProp hcp, String encoding) {
this.htmlData = red;
this.updatedProp = hcp;
this.encoding = encoding;
}
/**
* 把结果的string 转byte[]
* @return byte[]数组
*/
public byte[] getReturnByteData() {
try {
return this.htmlData.getBytes(this.encoding);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public String getHtmlData() {
return this.htmlData;
}
public void setHtmlData(String setb) {
this.htmlData = setb;
}
public HttpConnProp getUpdateProp() {
return this.updatedProp;
}
public void setUpdateProp(HttpConnProp uprop) {
this.updatedProp = uprop;
}
public String getEncoding() {
return this.encoding;
}
public void setEncoding(String e) {
this.encoding = e;
}
};
HttpHelper.java
package cn.zzy;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 自己写的java用HttpHelper 方便http相关操作 提供一系列同步 异步的方法
* 也有文件下载相关的异步、同步方法
* 所有的异步方法都提供一系列的回调接口。方便快捷~
*
*
*/
public class HttpHelper {
/**
* 固定5个线程来执行类内异步方法(默认)
*/
private static ExecutorService executorService = Executors
.newFixedThreadPool(5);
/**
* 立刻停止线程池服务,若有线程在running,强制停止 PS:命令行程序最后必须执行shutdown停止线程池服务,否则程序结束不了
* 警告:若一旦结束线程池服务,将不能再添加执行异步任务,除非运行本类中的openNewExecutorService()
*/
public static void shutTheThreadPoolDownNow() {
executorService.shutdownNow();
}
/**
* 等待所有线程完成执行后关闭线程池服务 PS:命令行程序最后必须执行shutdown停止线程池服务,否则程序结束不了
* 警告:若一旦结束线程池服务,将不能再添加执行异步任务,除非运行本类中的openNewExecutorService()
*/
public static void shutTheThreadPoolDown() {
executorService.shutdown();
}
/**
* 关闭默认的线程池服务,新建一个新的线程池服务
*
* @param RunningThreadCount
*/
public static void openNewExecutorService(int RunningThreadCount) {
if (!executorService.isShutdown())
executorService.shutdown();
executorService = Executors.newFixedThreadPool(RunningThreadCount);
}
/**
*
* 用于异步通信的回调接口
*
*/
public interface AsynExecuteCallBack {
public void beforeExecute();
public void afterExecute(ReturnData rData);
public void exceptionOccored(Exception e);
}
/**
* 异步方法: 以get方式获得ReturnData对象,使用回调接口处理获得对象
*
* @param strUrl
* 请求的URL地址
* @param hcp
* 连接的属性类
* @param encoding
* 编码字符串 例如 ASCII gb2312 utf-8 等
* @param callback
* 回调接口
*/
public static void AysnGetHtml(final String strUrl, final HttpConnProp hcp,
final String encoding, final AsynExecuteCallBack callback) {
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
callback.beforeExecute();
try {
ReturnData rd = getHtmlBytes(strUrl, hcp, null, false,
encoding);
callback.afterExecute(rd);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
callback.exceptionOccored(e);
}
}
});
}
/**
* 异步方法: 添加一个任务 以post方式获取页面
*
* @param strUrl
* 网页的URL地址
* @param strPost
* POST的数据 注意POST属性的值如果是中文或含有特殊符号根据相应编码URLencode
* @param hcp
* http连接相应的属性类
* @param encoding
* 编码字符串 例如 ASCII gb2312 utf-8 等
* @param callback
* 一系列回调接口
*/
public static void AysnPostHtml(final String strUrl, final String strPost,
final HttpConnProp hcp, final String encoding,
final AsynExecuteCallBack callback) {
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
callback.beforeExecute();
try {
ReturnData rd = getHtmlBytes(strUrl, hcp, strPost, true,
encoding);
callback.afterExecute(rd);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
callback.exceptionOccored(e);
}
}
});
}
/**
* 同步方法: 以gb2312编码,默认的链接属性get页面
*
* @param strUrl
* 访问的URL地址
* @return 网页的html
*/
public static String getHtml(String strUrl) {
return getHtml(strUrl, new HttpConnProp(), "gb2312");
}
/**
* 同步方法: get方式取页面,返回html页面
*
* @param strUrl
* 网页URL地址
* @param hcp
* 访问属性的类对象
* @param encoding
* 编码字符串 例如 ASCII gb2312 utf-8 等
* @return 如果出现错误返回null,否则返回页面的String对象
*/
public static String getHtml(String strUrl, HttpConnProp hcp,
String encoding) {
try {
return getHtmlBytes(strUrl, hcp, null, false, encoding)
.getHtmlData();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* 同步方法: 以post方式获取页面
*
* @param strUrl
* 网页URL地址
* @param strPost
* POST的数据 注意POST属性的值如果是中文或含有特殊符号根据相应编码URLencode
* @param hcp
* http连接的属性对象
* @param encoding
* 返回的数据存储的编码和post的编码,例如'gb2312'、'utf-8'
* @return 返回得到的html
*/
public static String postHtml(String strUrl, String strPost,
HttpConnProp hcp, String encoding) {
try {
return getHtmlBytes(strUrl, hcp, strPost, true, encoding)
.getHtmlData();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* 同步方法:
*
* 本Helper中最主要的方法 其他的一些方法都是根据此方法进行包装
*
* @param strUrl
* 网页URL地址
* @param httpConnProp
* http连接的属性
* @param strPost
* POST的数据 注意POST属性的值如果是中文或含有特殊符号根据相应编码URLencode,如果是get
* isPost设置为false,请设置null
* @param isPost
* 是否是POST方法
* @param encoding
* 返回的数据存储的编码和post的编码,例如'gb2312'、'utf-8'
* @return 一个返回信息的包装,内部类ReturnData,里面有HttpConnProp的更新和请求得到的数据
* @throws IOException
*/
public static ReturnData getHtmlBytes(String strUrl,
HttpConnProp httpConnProp, String strPost, boolean isPost,
String encoding) throws IOException {
HttpURLConnection.setFollowRedirects(true);// 静态变量设置 防止某些服务出错,特别是IIS的
HttpURLConnection httpCon = null;
InputStream is = null;
BufferedInputStream bis = null;
String temp = "";
// System.out.println(httpConnProp.getCookies().toString());
try {
URL url = new URL(strUrl);
httpCon = (HttpURLConnection) url.openConnection();
// 设置相关属性
httpCon.setReadTimeout(httpConnProp.getTimeOut());
httpCon.setConnectTimeout(httpConnProp.getTimeOut());
httpCon.setUseCaches(httpConnProp.getIsUseCaches());// 设置缓存
if (httpConnProp.getIsKeepAlive())
httpCon.setRequestProperty("connection", "Keep-Alive");
httpCon.setInstanceFollowRedirects(httpConnProp
.getIsInstanceFollowRedirects());// 设置跳转跟随
httpCon.setRequestProperty("Referer", httpConnProp.getReferer());
httpCon.setRequestProperty("Content-Type",
httpConnProp.getContentType());
httpCon.setRequestProperty("Accept", httpConnProp.getAccept());
httpCon.setRequestProperty("User-Agent",
httpConnProp.getUserAgent());
httpCon.setRequestProperty("Cookie", httpConnProp.getCookies()
.toString());
httpCon.setRequestProperty("Accept-Language",
"zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
if (isPost) {// 如果是post 设置post信息
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
httpCon.setUseCaches(false);// POST请求不能使用缓存
httpCon.setRequestProperty("Context-Length",
String.valueOf(strPost.getBytes(encoding).length));
httpCon.setRequestMethod("POST");
httpCon.connect();
OutputStream os = null;// 输出post信息的流
try {
os = httpCon.getOutputStream();
os.write(strPost.getBytes(encoding));
os.flush();
} finally {
if (os != null)
os.close();
}
}
// 获取数据
is = httpCon.getInputStream();
bis = new BufferedInputStream(is);
byte[] buffer = new byte[512];
int count = 0;
while ((count = bis.read(buffer)) != -1) {
temp += (new String(buffer, 0, count, encoding));
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
} finally {
try {
if (bis != null)
bis.close();
if (is != null)
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
HttpConnProp updtedHttpConnProp = HttpConnProp.copy(httpConnProp);
if (httpCon != null) {
updtedHttpConnProp.getCookies().putCookies(
httpCon.getHeaderField("Set-Cookie"));
// 更新 referer
updtedHttpConnProp.setReferer(strUrl);
// System.out.println("输出号:--" + httpCon.getResponseCode());
httpCon.disconnect();
httpCon = null;
}
return new ReturnData(temp, updtedHttpConnProp, encoding);
}
/**
* 同步方法:
* 从网络上下载文件 缓存4kb
* @param strUrl
* 文件URL地址
* @param fileURL
* 保存地址 如g://1.rar (注意是覆蓋的)
*/
public static void downLoadFile(final String strUrl, final String fileURL) {
downLoadFile(strUrl, fileURL,4096);
}
/**
* 同步方法: 从网络上下载文件
*
* @param strUrl
*文件URL地址
* @param fileURL
*保存地址 如g://1.rar (注意是覆蓋的)
* @bufferLength
* 下载缓存的大小,byte单位 ,建议4096 (4KB)
*/
public static void downLoadFile(final String strUrl, final String fileURL,final int bufferLength) {
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(strUrl).openStream());
File img = new File(fileURL);
out = new BufferedOutputStream(new FileOutputStream(img));
byte[] buf = new byte[bufferLength];
int count = in.read(buf);
while (count != -1) {
out.write(buf, 0, count);
count = in.read(buf);
}
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* 文件异步下载的接口
*
*/
interface asynDownLoadCallBack {
public void beforeDownLoad();// 下载文件之前
/**
* 如果服务器不指定文件的长度,则fileLength = 0 要用到这几个参数的话要自己在回调接口处判断
* @param hasDownedByte
* 已经下载的字节数
* @param FileLength
* 文件总字节数 若服务器无此信息即为0
*/
public void duringDownLoad(long hasDownedByte, long FileLength);// 下载文件之中
public void downLoadFinished();// 下载文件之后
public void downLoadErrorOccured(Exception e);// 出错后
}
/**
* 异步方法:
* 以4KB缓存从网上下载文件
* @param strUrl
* 文件URL地址
* @param fileURL
* 保存的地址 如g://1.rar
* @param callback
* 回调接口
*/
public static void AsynDownLoadFile(final String strUrl,
final String fileURL, final asynDownLoadCallBack callback) {
AsynDownLoadFile(strUrl, fileURL, callback,4096);
}
/**
* 异步方法:
* 从网络上异步下载文件
* @param strUrl
* 文件URL地址
* @param fileURL
* @param callback
* @param bufferLength
*/
public static void AsynDownLoadFile(final String strUrl,
final String fileURL, final asynDownLoadCallBack callback,final int bufferLength) {
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
URLConnection urlConnection = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
long fileLength = 0;
long hasDowned = 0;
try {
urlConnection = new URL(strUrl).openConnection();
fileLength = urlConnection.getContentLengthLong();// 获取报文里给的数据长度
bis = new BufferedInputStream(urlConnection
.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream(
new File(fileURL)));
callback.beforeDownLoad();// 执行回调函数
byte[] buffer = new byte[bufferLength];
int count = bis.read(buffer);
while (count != -1) {
bos.write(buffer, 0, count);
hasDowned += count;
// 如果服务器不指定文件的长度,则fileLength = 0 要用到这几个参数的话要自己在回调接口处判断
callback.duringDownLoad(hasDowned, fileLength);
count = bis.read(buffer);
}
callback.downLoadFinished();
} catch (Exception e) {
e.printStackTrace();
callback.downLoadErrorOccured(e);
}
finally{
try {
bis.close();
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
}
花了一天时间弄的,累死了。 但还不是很完全,还可以添加更多的方法。如果用于android的话还可以继承一下httpHelper个类,使用android类库再写几个android专用方法,比如load图片
目前有好多android的网络编程框架