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

原创 2016年02月29日 21:55:00

       在写这个工具类的时候发现传入的参数太多,以至于方法泛滥,只一个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 。


       httpclientUtil (QQ交流群:548452686 httpclientUtil交流

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载请声明:【转自 http://blog.csdn.net/xiaoxian8023 】

HttpClient中头部Header的使用

今天看了几个使用HttpClient设置头部信息的帖子,发现使用的Header都是commons-httpclient包中的: import org.apache.commons.httpcli...
  • blue_jjw
  • blue_jjw
  • 2013年04月07日 17:16
  • 75444

HttpClient设置HTTP请求头Header

用Firebug对POST的数据进行监控 请求 HTTP头 信息,得到如下内容: Java代码   Accept  application/json, text/javascr...
  • z69183787
  • z69183787
  • 2015年01月21日 11:00
  • 73333

HttpGet &&HttpPost方法发送header,params, Content

public static JSONObject post(String url,JSONObject json,Map headers){ HttpClient client = ...
  • fhlkm
  • fhlkm
  • 2012年08月08日 17:51
  • 57763

http_config.h

#ifndef APACHE_HTTP_CONFIG_H#define APACHE_HTTP_CONFIG_H#ifdef __cplusplusextern "C" {#endif/* * The...
  • ruixj
  • ruixj
  • 2006年06月20日 22:14
  • 2885

C# HttpWebRequest网络常用方法封装

C# 使用HttpWebRequest实现网络常用方法(GET, POST)的简单封装, 参数定制也很方便. 虽然.NET框架原生提供了类似的包装WebClient, 功能全面但是控制起来远不如Htt...
  • rrrfff
  • rrrfff
  • 2012年01月19日 20:04
  • 162960

基于HttpClient4.5.1实现Http访问工具类

本工具类基于httpclient4.5.1实现,点击此处查看官方版HttpClient4.5.1手册。
  • wangnan537
  • wangnan537
  • 2015年12月21日 20:02
  • 28748

C# HTTP工具类

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net...
  • qq183518918
  • qq183518918
  • 2013年12月20日 10:25
  • 1651

HttpClient 发送 HTTP、HTTPS 请求的简单封装

序 最近这几周,一直在忙同一个项目,刚开始是了解需求,需求有一定了解之后,就开始调第三方的接口。由于第三方给提供的文档很模糊,在调接口的时候,出了很多问题,一直在沟通协调,具体的无奈就不说了,由于...
  • happylee6688
  • happylee6688
  • 2015年07月30日 12:38
  • 63824

轻松把玩HttpClient之封装HttpClient工具类(一)(现有网上分享中的最强大的工具类)

搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用。调用关系不清楚,结构有点混乱。所以也就萌生了自己封装HttpClient工具类的想法。要做就...
  • xiaoxian8023
  • xiaoxian8023
  • 2015年11月19日 11:20
  • 27142

轻松把玩HttpClient之封装HttpClient工具类(三),插件式配置Header

上篇文章介绍了插件式配置HttpClient,本文将介绍插件式配置Header。为什么要配置header在前面已经提到了,还里再简单说一下,要使用HttpClient模拟请求,去访问各种接口或者网站资...
  • xiaoxian8023
  • xiaoxian8023
  • 2015年11月19日 11:20
  • 16429
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:轻松把玩HttpClient之封装HttpClient工具类(六),封装输入参数,简化工具类
举报原因:
原因补充:

(最多只允许输入30个字)