话说写的多线程上传下载很没有重用性,就想着写一个重用性高一点的出来。
初步想法是,将请求信息封装在一个DataForNet类中,然后一个实现自Runnable接口只负责调用,不负责具体的逻辑。
调用分为两步,一个是在请求之前,之后的处理,一个是真正的请求。那么做了两个接口
package com.whut.handlers; import java.io.InputStream; /* * 在请求之前之后的拦截处理 */ public interface IHandler { public void doBefore(); public void doAfter(InputStream is); } package com.whut.network; import java.io.InputStream; import com.whut.data.DataForNet; /* * 负责真正的http请求,返回InputStream */ public abstract class INet { protected DataForNet params; //你妹的!这里 doGet doPost没有return一直抱null,折腾人啦! public final InputStream doNet()throws Exception{ if(params.getMethod().equals("GET")) return doGet(); else if(params.getMethod().equals("POST")) return doPost(); else throw new Exception("位置http方法。无法进行http请求"); } public abstract InputStream doGet(); public abstract InputStream doPost(); }
线程类
package com.whut.netthread; import java.io.InputStream; import com.whut.handlers.IHandler; import com.whut.network.INet; public class HttpAyns implements Runnable { private INet net; private IHandler handler; public HttpAyns(INet net,IHandler handler){ this.net=net; this.handler=handler; } @Override public void run() { try { InputStream is=this.net.doNet(); handler.doAfter(is); } catch (Exception e) { e.printStackTrace(); } } }
因为有JDK 带的http请求类和apache的httpclient所以这里抽象出来的话就可以使用不同的请求方式而不用改变线程代码
下面分别是jdk和httpclient
package com.whut.network; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import com.whut.data.DataForNet; public class JDKHttp extends INet { public JDKHttp(DataForNet param) { this.params=param; } @Override public InputStream doGet() { InputStream is = null; try { URL uri = new URL(params.appParamUrl()); if (uri != null) { HttpURLConnection huc = (HttpURLConnection) uri .openConnection(); huc.setConnectTimeout(params.getTimeOut());// 设置连接网络的超时时间 huc.setDoInput(true);// 打开输入流 huc.setRequestMethod(params.getMethod());// GET请求 int statusCode = huc.getResponseCode(); if (statusCode == 200) { is = huc.getInputStream(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { return is; } } /* * 发送post请求 */ @Override public InputStream doPost() { InputStream is = null; String tmp = ""; try { URL url = new URL(params.getUrl()); HttpURLConnection huc = (HttpURLConnection) url.openConnection(); huc.setConnectTimeout(params.getTimeOut()); huc.setDoInput(true);// 从服务器获取数据 huc.setRequestMethod(params.getMethod()); huc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); if ((tmp = params.getParamUrl()) != "") { huc.setDoOutput(true);// 表示向服务器写 byte[] mybyte = tmp.getBytes(); huc.setRequestProperty("Content-Length", String.valueOf(mybyte.length)); OutputStream ops = huc.getOutputStream(); // 向服务器输出 ops.write(mybyte); } int statusCode = huc.getResponseCode(); if (200 == statusCode) { is = huc.getInputStream(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return is; } }
package com.whut.network; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import com.whut.data.DataForNet; public class ApacheHttp extends INet { public ApacheHttp(DataForNet param) { this.params = param; } @Override public InputStream doGet() { DefaultHttpClient httpclient = new DefaultHttpClient(); InputStream body = null; HttpGet get = new HttpGet(this.params.appParamUrl()); body = invoke(httpclient, get); // httpclient.getConnectionManager().shutdown(); //这里如果关了InputStream也会被关掉比较... return body; } @Override public InputStream doPost() { DefaultHttpClient httpclient = new DefaultHttpClient(); InputStream body = null; HttpPost post = postForm(this.params.getUrl(), this.params.getParams()); body = invoke(httpclient, post); return body; } private HttpResponse sendRequest(DefaultHttpClient httpclient, HttpUriRequest httpost) { HttpResponse response = null; try { response = httpclient.execute(httpost); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return response; } private InputStream invoke(DefaultHttpClient httpclient, HttpUriRequest httpost) { InputStream body=null; HttpResponse response = sendRequest(httpclient, httpost); if(response!=null){ if(response.getStatusLine().getStatusCode()==200) body = paseResponse(response); } return body; } private String paseResponseString(HttpResponse response) { HttpEntity entity = response.getEntity(); String charset = EntityUtils.getContentCharSet(entity); String body = null; try { body = EntityUtils.toString(entity); } catch (IOException e) { e.printStackTrace(); } return body; } private InputStream paseResponse(HttpResponse response) { InputStream entity=null; try { entity = response.getEntity().getContent(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return entity; } private HttpPost postForm(String url, Map<String, String> params){ HttpPost httpost = new HttpPost(url); List<NameValuePair> nvps = new ArrayList <NameValuePair>(); Set<String> keySet = params.keySet(); for(String key : keySet) { nvps.add(new BasicNameValuePair(key, params.get(key))); } try { httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return httpost; } }
还尝试写了一个线程池的调度很简单,只是作为练习吧
package com.whut.netthread; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* * 线程池 */ public class HttpThreadPool { private final static int cpus = Runtime.getRuntime().availableProcessors(); //cpu数量 public static void batchExecute(List<Runnable> tasks) { int len = tasks.size(); if (len <= 0) return; ExecutorService threadPool; if (len > cpus * 2) { // 任务太多时,最多使用cpu*2 个线程,这种情况效率最好 threadPool = Executors.newFixedThreadPool(cpus * 2); } else if (len < 3) { threadPool = Executors.newSingleThreadExecutor(); } else threadPool = Executors.newFixedThreadPool(len / 2); for (Runnable task : tasks) threadPool.execute(task); threadPool.shutdown(); } }
最后奉上请求封装的简单类
package com.whut.data; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Map; /* * 一次发送的所有信息 */ public class DataForNet { private String url; private String method; private int timeOut; private String encode; private Map<String, String> params; public DataForNet(String url) { this.url = url; this.method = "GET"; this.timeOut = 5000; this.encode = "utf-8"; params = null; } public DataForNet(String url, String method) { this.url = url; this.method = method.toUpperCase(); this.timeOut = 5000; this.encode = "utf-8"; this.params = null; } public DataForNet(String url, String method, Map<String, String> param) { this.url = url; this.method = method.toUpperCase(); this.timeOut = 5000; this.encode = "utf-8"; this.params = param; } public DataForNet(String url, String method, int timeOut, Map<String, String> param) { this.url = url; this.method = method.toUpperCase(); this.timeOut = timeOut; this.encode = "utf-8"; this.params = param; } public DataForNet(String url, String method, int timeOut, String encode, Map<String, String> param) { this.url = url; this.method = method.toUpperCase(); this.timeOut = timeOut; this.encode = encode; this.params = param; } public int getTimeOut() { return timeOut; } public void setTimeOut(int timeOut) { this.timeOut = timeOut; } // 根据参数Map构建请求,encode是参数的编码方式如"utf-8" ,主要用于jdk中的get请求 public String appParamUrl() { return this.url + getParamUrl(); } public String getEncode() { return encode; } public void setEncode(String encode) { this.encode = encode; } // 用于jdk中的post请求 public String getParamUrl() { StringBuffer sb = new StringBuffer(this.url); if (params != null && !params.isEmpty()) { try { for (Map.Entry<String, String> entry : params.entrySet()) { sb.append(entry.getKey()) .append("=") .append(URLEncoder.encode(entry.getValue(), encode)) .append("&"); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } sb.deleteCharAt(sb.length() - 1); return sb.toString(); } return ""; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public Map<String, String> getParams() { return params; } public void setParams(Map<String, String> params) { this.params = params; } @Override public String toString() { return this.url+":"+this.method+":"+this.timeOut; } }