轻松把玩HttpClient之封装HttpClient工具类(六),封装输入参数,简化工具类

在写这个工具类的时候发现传入的参数太多,以至于方法泛滥,只一个send方法就有30多个,所以对工具类进行了优化,把输入参数封装在一个对象里,这样以后再扩展输入参数,直接修改这个类就ok了。

不多说了,先上代码:

/**
 * 请求配置类
 *
 * @author arron
 * @date 2016年2月2日 下午3:14:32
 * @version 1.0
 */
public class HttpConfig {

	private HttpConfig(){};

	/**
	 * 获取实例
	 * @return
	 */
	public static HttpConfig custom(){
		return new HttpConfig();
	}

	/**
	 * HttpClient对象
	 */
	private HttpClient client;

	/**
	 * CloseableHttpAsyncClient对象
	 */
	private CloseableHttpAsyncClient asynclient;

	/**
	 * 资源url
	 */
	private String url;

	/**
	 * Header头信息
	 */
	private Header[] headers;

	/**
	 * 请求方法
	 */
	private HttpMethods method=HttpMethods.GET;

	/**
	 * 请求方法名称
	 */
	private String methodName;

	/**
	 * 用于cookie操作
	 */
	private HttpContext context;

	/**
	 * 传递参数
	 */
	private Map<String, Object> map;

	/**
	 * 输入输出编码
	 */
	private String encoding=Charset.defaultCharset().displayName();

	/**
	 * 输入编码
	 */
	private String inenc;

	/**
	 * 输出编码
	 */
	private String outenc;

	/**
	 * 输出流对象
	 */
	private OutputStream out;

	/**
	 * 异步操作回调执行器
	 */
	private IHandler handler;

	/**
	 * HttpClient对象
	 */
	public HttpConfig client(HttpClient client) {
		this.client = client;
		return this;
	}

	/**
	 * CloseableHttpAsyncClient对象
	 */
	public HttpConfig asynclient(CloseableHttpAsyncClient asynclient) {
		this.asynclient = asynclient;
		return this;
	}

	/**
	 * 资源url
	 */
	public HttpConfig url(String url) {
		this.url = url;
		return this;
	}

	/**
	 * Header头信息
	 */
	public HttpConfig headers(Header[] headers) {
		this.headers = headers;
		return this;
	}

	/**
	 * 请求方法
	 */
	public HttpConfig method(HttpMethods method) {
		this.method = method;
		return this;
	}

	/**
	 * 请求方法
	 */
	public HttpConfig methodName(String methodName) {
		this.methodName = methodName;
		return this;
	}

	/**
	 * cookie操作相关
	 */
	public HttpConfig context(HttpContext context) {
		this.context = context;
		return this;
	}

	/**
	 * 传递参数
	 */
	public HttpConfig map(Map<String, Object> map) {
		this.map = map;
		return this;
	}

	/**
	 * 输入输出编码
	 */
	public HttpConfig encoding(String encoding) {
		//设置输入输出
		inenc(encoding);
		outenc(encoding);
		this.encoding = encoding;
		return this;
	}

	/**
	 * 输入编码
	 */
	public HttpConfig inenc(String inenc) {
		this.inenc = inenc;
		return this;
	}

	/**
	 * 输出编码
	 */
	public HttpConfig outenc(String outenc) {
		this.outenc = outenc;
		return this;
	}

	/**
	 * 输出流对象
	 */
	public HttpConfig out(OutputStream out) {
		this.out = out;
		return this;
	}

	/**
	 * 异步操作回调执行器
	 */
	public HttpConfig handler(IHandler handler) {
		this.handler = handler;
		return this;
	}

	public HttpClient client() {
		return client;
	}

	public CloseableHttpAsyncClient asynclient() {
		return asynclient;
	}

	public Header[] headers() {
		return headers;
	}

	public String url() {
		return url;
	}

	public HttpMethods method() {
		return method;
	}

	public String methodName() {
		return methodName;
	}

	public HttpContext context() {
		return context;
	}

	public Map<String, Object> map() {
		return map;
	}

	public String encoding() {
		return encoding;
	}

	public String inenc() {
		return inenc == null ? encoding : inenc;
	}

	public String outenc() {
		return outenc == null ? encoding : outenc;
	}

	public OutputStream out() {
		return out;
	}

	public IHandler handler() {
		return handler;
	}
}

将构造方法设置为private,然后提供一个custom()方法来获取新的实例,所有的set方法,都是返回HttpConfig,这样就支持链式调用(创建者模式)了。

工具类的核心方法如下:

	/**
	 * 请求资源或服务
	 *
	 * @param config
	 * @return
	 * @throws HttpProcessException
	 */
	public static String send(HttpConfig config) throws HttpProcessException {
		return fmt2String(execute(config), config.outenc());
	}

	/**
	 * 请求资源或服务
	 *
	 * @param client				client对象
	 * @param url					资源地址
	 * @param httpMethod	请求方法
	 * @param parasMap		请求参数
	 * @param headers			请求头信息
	 * @param encoding		编码
	 * @return						返回处理结果
	 * @throws HttpProcessException
	 */
	private static HttpResponse execute(HttpConfig config) throws HttpProcessException {
		if(config.client()==null){//检测是否设置了client
			config.client(create(config.url()));
		}
		HttpResponse resp = null;
		try {
			//创建请求对象
			HttpRequestBase request = getRequest(config.url(), config.method());

			//设置header信息
			request.setHeaders(config.headers());

			//判断是否支持设置entity(仅HttpPost、HttpPut、HttpPatch支持)
			if(HttpEntityEnclosingRequestBase.class.isAssignableFrom(request.getClass())){
				List<NameValuePair> nvps = new ArrayList<NameValuePair>();

				//检测url中是否存在参数
				config.url(Utils.checkHasParas(config.url(), nvps, config.inenc()));

				//装填参数
				HttpEntity entity = Utils.map2List(nvps, config.map(), config.inenc());

				//设置参数到请求对象中
				((HttpEntityEnclosingRequestBase)request).setEntity(entity);

				logger.info("请求地址:"+config.url());
				if(nvps.size()>0){
					logger.info("请求参数:"+nvps.toString());
				}
			}else{
				int idx = config.url().indexOf("?");
				logger.info("请求地址:"+config.url().substring(0, (idx>0 ? idx : config.url().length())));
				if(idx>0){
					logger.info("请求参数:"+config.url().substring(idx+1));
				}
			}
			//执行请求操作,并拿到结果(同步阻塞)
			resp = (config.context()==null)?config.client().execute(request) : config.client().execute(request, config.context()) ;

			//获取结果实体
			return resp;

		} catch (IOException e) {
			throw new HttpProcessException(e);
		}
	}

	//-----------华----丽----分----割----线--------------
	//-----------华----丽----分----割----线--------------
	//-----------华----丽----分----割----线--------------

	/**
	 * 转化为字符串
	 *
	 * @param entity			实体
	 * @param encoding	编码
	 * @return
	 * @throws HttpProcessException
	 */
	public static String fmt2String(HttpResponse resp, String encoding) throws HttpProcessException {
		String body = "";
		try {
			if (resp.getEntity() != null) {
				// 按指定编码转换结果实体为String类型
				body = EntityUtils.toString(resp.getEntity(), encoding);
				logger.debug(body);
			}
			EntityUtils.consume(resp.getEntity());
		} catch (ParseException | IOException e) {
			throw new HttpProcessException(e);
		}finally{
			close(resp);
		}
		return body;
	}

	/**
	 * 转化为流
	 *
	 * @param entity			实体
	 * @param out				输出流
	 * @return
	 * @throws HttpProcessException
	 */
	public static OutputStream fmt2Stream(HttpResponse resp, OutputStream out) throws HttpProcessException {
		try {
			resp.getEntity().writeTo(out);
			EntityUtils.consume(resp.getEntity());
		} catch (ParseException | IOException e) {
			throw new HttpProcessException(e);
		}finally{
			close(resp);
		}
		return out;
	}

再附上测试代码:

	public static void testOne() throws HttpProcessException{

		System.out.println("--------简单方式调用(默认post)--------");
		String url = "http://tool.oschina.net/";
		HttpConfig  config = HttpConfig.custom();
		//简单调用
		String resp = HttpClientUtil.get(config.url(url));

		System.out.println("请求结果内容长度:"+ resp.length());

		System.out.println("\n#################################\n");

		System.out.println("--------加入header设置--------");
		url="http://blog.csdn.net/xiaoxian8023";
		//设置header信息
		Header[] headers=HttpHeader.custom().userAgent("Mozilla/5.0").build();
		//执行请求
		resp = HttpClientUtil.get(config.headers(headers));
		System.out.println("请求结果内容长度:"+ resp.length());

		System.out.println("\n#################################\n");

		System.out.println("--------代理设置(绕过证书验证)-------");
		url="https://www.facebook.com/";
		HttpClient client= HCB.custom().timeout(10000).proxy("127.0.0.1", 8087).ssl().build();//采用默认方式(绕过证书验证)
		//执行请求
		resp = HttpClientUtil.get(config.client(client));
		System.out.println("请求结果内容长度:"+ resp.length());

		System.out.println("\n#################################\n");

//		System.out.println("--------代理设置(自签名证书验证)+header+get方式-------");
//		url = "https://sso.tgb.com:8443/cas/login";
//		client= HCB.custom().timeout(10000).ssl("D:\\keys\\wsriakey","tomcat").build();
//		headers=HttpHeader.custom().keepAlive("false").connection("close").contentType(Headers.APP_FORM_URLENCODED).build();
//		//执行请求
//		resp = CopyOfHttpClientUtil.get(config.method(HttpMethods.GET));
//		System.out.println("请求结果内容长度:"+ resp.length());
		try {
			System.out.println("--------下载测试-------");
			url="http://ss.bdimg.com/static/superman/img/logo/logo_white_fe6da1ec.png";
			FileOutputStream out = new FileOutputStream(new File("d://aaa//000.png"));
			HttpClientUtil.down(HttpConfig.custom().url(url).out(out));
			out.flush();
			out.close();
			System.out.println("--------下载测试+代理-------");

			out = new FileOutputStream(new File("d://aaa//001.png"));
			HttpClientUtil.down(HttpConfig.custom().client(client).url(url).out(out));
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println("\n#################################\n");
	}

可以看到这样调用会更显得清晰明了。以后再添加功能时,改起来也会比较方便了。工具类也提供了输出流的功能,可以用于下载文件或者加载验证码图片,非常方便。

最新的完整代码请到GitHub上进行下载:https://github.com/Arronlong/httpclientUtil 。

时间: 2024-10-27 18:55:56

轻松把玩HttpClient之封装HttpClient工具类(六),封装输入参数,简化工具类的相关文章

轻松把玩HttpClient之封装HttpClient工具类(二),插件式配置HttpClient对象

上一篇文章中,简单分享一下封装HttpClient工具类的思路及部分代码,本文将分享如何实现插件式配置HttpClient对象. 如果你看过我前面的几篇关于HttpClient的文章或者官网示例,应该都知道HttpClient对象在创建时,都可以设置各种参数,但是却没有简单的进行封装,比如对我来说比较重要的3个:代理.ssl(包含绕过证书验证和自定义证书验证).超时.还需要自己写.所以这里我就简单封装了一下,顺便还封装了一个连接池的配置. 其实说是插件式配置,那是高大上的说法,说白了,就是采用了

封装HttpClient进行http请求与https请求

一.https忽略证书 /** * 用于进行Https请求的HttpClient * * @author joey * */ public class SSLClient { public static CloseableHttpClient createSSLClientDefault(){ try { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { //

iOS开发--QQ音乐练习,旋转动画的实现,音乐工具类的封装,定时器的使用技巧,SliderBar的事件处理

一.旋转动画的实现 二.音乐工具类的封装 -- 返回所有歌曲,返回当前播放歌曲,设置当前播放歌曲,返回下一首歌曲,返回上一首歌曲方法的实现 头文件 .m文件 1 #import "ChaosMusicTool.h" 2 #import "MJExtension.h" 3 #import "ChaosMusic.h" 4 5 static NSArray *_musics; 6 static ChaosMusic *_playingMusic; 7

验证码确保php无输出、sql语句的封装性、文件上传的工具类【这三个重点工具类实现】

1.php代码在引入中不会进行结束或者确保结束之后没有空格,来保证php在被包含中没有被输出[防止header和session_start()对输出的控制]实质上,需要注意的就是,要不就进行输出缓存控制以及php开始标签前没有空格 验证码这个功能需要header和session两个功能[尤其需要注意输出的问题] [总结:防止php代码中带着一些输出的问题](1)在php标签中开始<?php 前顶格(2)php结束符要不不写,写了就不要在结束之后还有换行[防止该文件被包含之后提前出线输出](3)或

C++使用libcurl做HttpClient(业务观摩,用C++封装过程式代码,post和get的数据,最好url编码,否则+会变成空格)good

当使用C++做HTTP客户端时,目前通用的做法就是使用libcurl.其官方网站的地址是http://curl.haxx.se/,该网站主要提供了Curl和libcurl.Curl是命令行工具,用于完成FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP的命令的请求及接收回馈.libcurl提供给开发者,用于使用C++跨平台的开发各种网络协议的请求及响应.里面的文档非常齐全,不过都是英文的. 本文提供最简单的demo使用libcur

封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil

封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,代码比较简单,主要是把MongoTarget的配置.FileTarget的配置集成到类中,同时利用缓存依赖来判断是否需要重新创建Logger类,完整代码如下: using NLog; using NLog.Config; using NLog.Mongo; using NLog.Targets; using System; using System.Collections.Generic; using System.IO;

javascript 总结(常用工具类的封装,转)

javascript 总结(常用工具类的封装) 前言 因为工作中经常用到这些方法,所有便把这些方法进行了总结. JavaScript 1. type 类型判断 isString (o) { //是否字符串 return Object.prototype.toString.call(o).slice(8, -1) === 'String' } isNumber (o) { //是否数字 return Object.prototype.toString.call(o).slice(8, -1) ==

轻松把玩HttpAsyncClient之模拟post请求示例

如果看到过我前些天写过的<轻松把玩HttpClient之模拟post请求示例>这篇文章,你再看本文就是小菜一碟了,如果你顺便懂一些NIO,基本上是毫无压力了.因为HttpAsyncClient相对于HttpClient,就多了一个NIO,这也是为什么支持异步的原因. 不过我有一个疑问,虽说NIO是同步非阻塞IO,但是HttpAsyncClient提供了回调的机制,这点儿跟netty很像,所以可以模拟类似于AIO的效果.但是官网上的例子却基本上都是使用Future<HttpResponse

LruCache缓存处理及异步加载图片类的封装

Android中的缓存处理及异步加载图片类的封装 一.缓存介绍: (一).Android中缓存的必要性: 智能手机的缓存管理应用非常的普遍和需要,是提高用户体验的有效手段之一. 1.没有缓存的弊端: 流量开销:对于客户端——服务器端应用,从远程获取图片算是经常要用的一个功能,而图片资源往往会消耗比较大的流量. 加载速度:如果应用中图片加载速度很慢的话,那么用户体验会非常糟糕. 那么如何处理好图片资源的获取和管理呢?异步下载+本地缓存 2.缓存带来的好处: 1. 服务器的压力大大减小: 2. 客户