轻松把玩HttpClient之封装HttpClient工具类(六),封装输入参数,简化工具类
最后更新于:2022-04-01 23:00:06
版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载请声明:【转自 http://blog.csdn.net/xiaoxian8023 】
在写这个工具类的时候发现传入的参数太多,以至于方法泛滥,只一个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 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 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 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 nvps = new ArrayList();
//检测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 。
';