使用单例模式实现自己的HttpClient工具类
使用单例模式实现自己的HttpClient工具类
引子
在Android开发中我们经常会用到网络连接功能与服务器进行数据的交互,为此Android的SDK提供了Apache的HttpClient来方便我们使用各种Http服务。你可以把HttpClient想象成一个浏览器,通过它的API我们可以很方便的发出GET,POST请求(当然它的功能远不止这些)。
比如你只需以下几行代码就能发出一个简单的GET请求并打印响应结果:
try {// 创建一个默认的HttpClient HttpClient httpclient =new DefaultHttpClient();// 创建一个GET请求 HttpGet request =new HttpGet("www.google.com");// 发送GET请求,并将响应内容转换成字符串 String response = httpclient.execute(request, new BasicResponseHandler()); Log.v("response text", response); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
为什么要使用单例HttpClient?
这只是一段演示代码,实际的项目中的请求与响应处理会复杂一些,并且还要考虑到代码的容错性,但是这并不是本篇的重点。注意代码的第三行:
HttpClient httpclient =new DefaultHttpClient();
在发出HTTP请求前,我们先创建了一个HttpClient对象。那么,在实际项目中,我们很可能在多处需要进行HTTP通信,这时候我们不需要为每个请求都创建一个新的HttpClient。因为之前已经提到,HttpClient就像一个小型的浏览器,对于整个应用,我们只需要一个HttpClient就够了。看到这里,一定有人心里想,这有什么难的,用单例啊!!就像这样:
publicclass CustomerHttpClient {privatestatic HttpClient customerHttpClient; private CustomerHttpClient() { } publicstatic HttpClient getHttpClient() {if(null== customerHttpClient) { customerHttpClient =new DefaultHttpClient(); }return customerHttpClient; }}
那么,哪里不对劲呢?或者说做的还不够完善呢?
多线程!试想,现在我们的应用程序使用同一个HttpClient来管理所有的Http请求,一旦出现并发请求,那么一定会出现多线程的问题。这就好像我们的浏览器只有一个标签页却有多个用户,A要上google,B要上baidu,这时浏览器就会忙不过来了。幸运的是,HttpClient提供了创建线程安全对象的API,帮助我们能很快地得到线程安全的“浏览器”。
解决多线程问题
package edu.cdut.robin; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; public class CustomerHttpClient { private static final String CHARSET = HTTP.UTF_8; private static HttpClient customerHttpClient; private CustomerHttpClient() { } public static synchronized HttpClient getHttpClient() { if (null == customerHttpClient) { HttpParams params = new BasicHttpParams(); /* 设置一些基本参数 */ HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); HttpProtocolParams .setUserAgent( params, "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) " + "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1"); /* 超时设置 */ /* 从连接池中取连接的超时时间 */ ConnManagerParams.setTimeout(params, 1000); /* 连接超时 */ HttpConnectionParams.setConnectionTimeout(params, 2000); /* 请求超时 */ HttpConnectionParams.setSoTimeout(params, 4000); /* 设置我们的HttpClient支持HTTP和HTTPS两种模式 */ SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory .getSocketFactory(), 443)); /* 使用线程安全的连接管理来创建HttpClient */ ClientConnectionManager conMgr = new ThreadSafeClientConnManager( params, schReg); customerHttpClient = new DefaultHttpClient(conMgr, params); } return customerHttpClient; } }
在上面的getHttpClient()方法中,我们为HttpClient配置了一些基本参数和超时设置,然后使用ThreadSafeClientConnManager来创建线程安全的HttpClient。上面的代码提到了3种超时设置,比较容易搞混,故在此特作辨析。
HttpClient的3种超时说明
关于此请参考《Android中HttpClient的3种超时》
封装简单的POST请求
有了单例的HttpClient对象,我们就可以把一些常用的发出GET和POST请求的代码也封装起来,写进我们的工具类中了。目前我仅仅实现发出POST请求并返回响应字符串的方法以供大家参考。将以下代码加入我们的CustomerHttpClient类中:
privatestaticfinal String TAG ="CustomerHttpClient"; publicstatic String post(String url, NameValuePair... params) {try {// 编码参数 List<NameValuePair> formparams =new ArrayList<NameValuePair>(); // 请求参数for (NameValuePair p : params) { formparams.add(p); } UrlEncodedFormEntity entity =new UrlEncodedFormEntity(formparams, CHARSET);// 创建POST请求 HttpPost request =new HttpPost(url); request.setEntity(entity);// 发送请求 HttpClient client = getHttpClient(); HttpResponse response = client.execute(request);if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {thrownew RuntimeException("请求失败"); } HttpEntity resEntity = response.getEntity();return (resEntity ==null) ?null : EntityUtils.toString(resEntity, CHARSET); } catch (UnsupportedEncodingException e) { Log.w(TAG, e.getMessage());returnnull; } catch (ClientProtocolException e) { Log.w(TAG, e.getMessage());returnnull; } catch (IOException e) {thrownew RuntimeException("连接失败", e); } }
使用我们的CustomerHttpClient工具类
现在,在整个项目中我们都能很方便的使用该工具类来进行网络通信的业务代码编写了。下面的代码演示了如何使用username和password注册一个账户并得到新账户ID。
final String url ="http://yourdomain/context/adduser";//准备数据 NameValuePair param1 =new BasicNameValuePair("username", "张三"); NameValuePair param2 =new BasicNameValuePair("password", "123456");int resultId =-1;try {// 使用工具类直接发出POST请求,服务器返回json数据,比如"{userid:12}" String response = CustomerHttpClient.post(url, param1, param2); JSONObject root =new JSONObject(response); resultId = Integer.parseInt(root.getString("userid")); Log.i(TAG, "新用户ID:"+ resultId); } catch (RuntimeException e) {// 请求失败或者连接失败 Log.w(TAG, e.getMessage()); Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT); } catch (Exception e) {// JSon解析出错 Log.w(TAG, e.getMessage()); }
结语
可以看到,使用工具类能大大提高在项目中编写网络通信代码的效率。不过该工具类还有待完善,欢迎各位补充和矫正错误,希望最后能完成一个工具类作为使用HttpClient的最佳实践。(完)
<wbr></wbr>
使用单例模式实现自己的HttpClient工具类相关推荐
- Java开发小技巧(五):HttpClient工具类
前言 大多数Java应用程序都会通过HTTP协议来调用接口访问各种网络资源,JDK也提供了相应的HTTP工具包,但是使用起来不够方便灵活,所以我们可以利用Apache的HttpClient来封装一个具 ...
- HttpClient工具类
HttpClient工具类 package cn.sh.steven.httpclient;import com.alibaba.fastjson.JSON; import com.alibaba.f ...
- apache httpclient 工具类_HttpClient
HttpClient 简介 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 ...
- apache httpclient 工具类_HttpClient 和Mycat 主从节点和读写分离
第175次(HttpClient) 学习主题:HttpClient 学习目标: 1 掌握HttpClient自定义工具以及HttpClient具体的使用 对应视频: http://www.itbaiz ...
- apache httpclient 工具类_使用HttpClient进行服务的远程调用
目标:使用apache公司的产品http httpcomponents 完成服务调用. HTTPClient调用服务 4:导入httpclient的依赖配置 org.apache.httpcompon ...
- 14、阿里云短信Demo演示、Http的Get请求和Post请求演示、httpClient工具类演示、发送短信模块搭建、搭建用户中心模块、完成user注册基本功能、验证码存入redis、短信验证码注册
阿里云短信Demo演示 一.前端部分 无前端. 二.后端部分 1.创建发送短信测试模块SmsSendDemo,不用使用骨架. 2.在pom文件中引入依赖坐标 <dependency>< ...
- 工具类-httpClient工具类
httpClient工具类 1.httpClient工具类(http/https.重发.超时.连接数的设置) package com.xxxxxxx.xxxx.xxxx.payutil;import ...
- HttpClient工具类封装
HttpClient是Apache Jakarta Common下的子项目,用来提供高效的.最新的.功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议.HttpCli ...
- HttpClient工具类及应用
Content-Type类型: 常见的媒体格式类型如下: text/html : HTML格式 text/plain :纯文本格式 text/xml : XML格式 image/gif :gif图片格 ...
最新文章
- 【opencv】(1) 基础操作:图像视频读取、图像截取、颜色通道
- Unix/Linux中Cron的用法
- 5种ASP.NET页面间传递参数实例代码
- Eclipse将引用了第三方jar包的Java项目打包成jar文件
- CCIE-LAB-SDN-第六篇-SDWAN-Branch2-vEdge-51-vEdge-52
- Win7系统打开网页特别慢的解决方法
- Core Graphics 定制UIVIew 处理图片
- Centos7安装完毕后无法联网的解决方法(转)
- Office 2016中修改正文默认字体
- 风云2号卫星云图_世界气象日话说54所与风云气象卫星的“不解之缘”
- 写一个加密程序对文件加密
- 前端面试之----跨域解决方案之一(CORS)
- 数据挖掘与机器学习:机器学习 --- 决策树
- Windows10 笔记本电脑移动硬盘设备未就绪
- 修改文件扩展名(只需四步)
- hadoop与spark的异同
- 2022IYPT/CUPT第十一题 旋风球(橡皮筋上的球)
- 生物大分子的计算机模拟就业,生物大分子体系结合自由能及构象变化的计算机模拟...
- 基于Spring boot的个人理财系统
- linux新建用户并赋予权限
热门文章
- 自己动手实现arm函数栈帧回溯【转】
- 【.NET】使用HtmlAgilityPack抓取网页数据
- PL/SQL Developer 登录 Oracle 12c和Win10下安装Oracle 11g
- 【C#】【MySQL】C# 查询数据库语句@Row:=@Row+1以及执行存储过程失败解决方案
- 单元测试注意事项总结(一)
- 【简易教程】人体时钟 ホネホネ・クロック [時計・ブログパーツ]
- 解决Eclipse Pydev中import时报错:Unresolved import
- Spring boot如何打war包发布到tomcat
- 四则运算2扩展---c++
- mysql : 常用管理命令