最近,业务需要在java服务端发起http请求,需要实现"GET","POST","PUT"等基本方法。于是想以 "HttpClient" 为基础,封装基本实现方法。在github上面看到一个项目cn-umbrella/httpclientDemo,里面实现简单的 "GET","POST"。一方面,demo中实现的逻辑不能满足业务需要,同时实现过程中,存在使用过期的类,代码封装不足等问题。也是我就重新封装了httpclient-util,抱着大家相互学习的心态,将代码上传到github上面,相关链接,错误的地方欢迎大家指正。

回归正题,下面讲讲工具类实现的基本思路。

1.主要依赖

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency> <!--httpmime主要用于构建multi-part/form-data 请求-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.2</version>
</dependency>

2.HttpClientUtil 主要方法

/**
* Do http request
* @param request request object
* @return response object
*/
public static Response doRequest(Request request)

其中,Request 封装了请求参数,Response 封装了返回内容。

3.Request 说明

支持方法:"GET","OPTIONS","HEAD","POST","PUT","PATCH"。支持请求体: "application/x-www-form-urlencoded","json字符串","multipart/form-data"。

Request的继承关系

Request (没有请求body的请求,支持方法:"GET", "OPTIONS", "HEAD")
|---BaseEntityRequest (抽象类,定义有请求body的请求, 支持方法:"POST", "PUT", "PATCH")
|--- UrlEncodedFormRequest (application/x-www-form-urlencoded)
|--- JsonRequest (请求body为json字符串)
|--- MultiPartFormRequest (multipart/form-data)

同时,Request 支持使用 ssl/tls,使用request.setUseSSL(true);设置即可。

HttpEntity就是对应请求body相关实体对象。

3.BaseEntityRequest 介绍

任何实现具有请求body的请求,需要实现 BaseEntityRequest 以下方法

/**
* Get HttpEntity about request body
* @return HttpEntity
*/
public abstract HttpEntity getEntity();

3.1 UrlEncodedFormRequest 核心代码

这个实现比较简单,"K-V" 的形式,返回 UrlEncodedFormEntity,注意参数编码。

@Override
public HttpEntity getEntity() {
List<NameValuePair> pairList = new ArrayList<>(params.size());
for (Map.Entry<String, Object> entry : params.entrySet()) {
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry
.getValue().toString());
pairList.add(pair);
} return new UrlEncodedFormEntity(pairList, Charset.forName(getRequestCharset())); //参数编码
}

3.2 JsonRequest 核心代码

请求body就是一个 "json字符串",返回一个StringEntity 实体即可。

@Override
public HttpEntity getEntity() {
StringEntity stringEntity = new StringEntity(jsonObject.toString(), getRequestCharset()); //解决中文乱码问题,需要注意编码,如使用"utf-8"
stringEntity.setContentEncoding(getResponseDefaultCharset());
stringEntity.setContentType(JSON_CONTENT_TYPE);
return stringEntity;
}

3.3 MultiPartFormRequest 核心代码

httpclient 类库中不直接支持构造 "multi-part/form-data" ,需要引入 httpmime,并使用 MultipartEntityBuilder 构造请求body。如果是文件类型的参数对象,使用 FileBody 构建 part,否则,使用 StringBody,注意编码。

@Override
public HttpEntity getEntity() {
try {
Charset charset = CharsetUtils.get(getRequestCharset());
//使用浏览器兼容模式,并且设置编码,防止文件名乱码问题
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.setCharset(charset); //编码
parts.forEach((key, value) -> {
if (null != value && value instanceof File) { //for file
FileBody fileBody = new FileBody((File) value);
builder.addPart(key, fileBody);
} else {
StringBody stringBody = new StringBody(null == value ? "" : value.toString()
, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset)); //编码
builder.addPart(key, stringBody);
}
});
return builder.build();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Charset '" + getRequestCharset() + "' is unsupported!");
}
}

4.注意地方

使用 https 过程中,如果出现下述异常:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)

可以参考我的上篇博文解决 java 使用ssl过程中出现"PKIX path building failed:...,当然在包 com.xiaobenma020.http.cert 下面可以找到类 InstallCert

关键步骤

% java InstallCert _web_site_hostname_

显示相关的证书信息

此时输入'q' 则为'退出', '1' 则将添加CA证书。

将新生成的 "jssecacerts" 移到"$JAVA_HOME/jre/lib/security"

5.使用demo

@Test
public void doResponse() throws Exception {
UrlEncodedFormRequest request = new UrlEncodedFormRequest("https://xxx.com/login", RequestMethod.POST); //url form param
request.addParam("loginId", "loginId");
request.addParam("password", "password"); //query string param
request.addUrlParam("version", "v1"); //ssl
request.setUseSSL(true); Response response = HttpClientUtil.doRequest(request);
System.out.println(response.getResponseText()); //response text
System.out.println(response.getCode()); //response code
System.out.println(response.getHeader("Set-Cookie"));
}

HttpClient 4.5.x 工具类设计与实现的更多相关文章

  1. JFreeChart绘制XY折线图(工具类设计)

    准备用Java写通信的仿真平台作为毕业设计,相比matlab绘图,Java绘图需要自己去写很多工具类,博主在这采用了JFreeChart的开源解决方案,摸索着自己写了一个XY折线图工具类,话不多说贴源 ...

  2. httpclient 实现的http工具类

    HttpClient实现的工具类 就是簡單的用http 協議請求請求地址並返回數據,廢話少數直接上代碼 http請求返回的封裝類 package com.nnk.upstream.util; impo ...

  3. 使用RedisTemplate进行Redis存取的工具类设计

    通常在访问量大数据更新频率不高的系统中会使用第三方的缓存组件来降低数据库服务的负载,鉴于模块独立分工独立的考虑,针对缓存组件操作的工作全部应该统一接口对其他业务提供服务,这样业务操作只需要关注业务实现 ...

  4. 基于Java反射的map自动装配JavaBean工具类设计

    我们平时在用Myabtis时不是常常需要用map来传递参数,大体是如下的步骤: public List<Role> findRoles(Map<String,Object> p ...

  5. 使用HttpClient访问url的工具类

    maven依赖jar包配置: <dependency> <groupId>org.apache.httpcomponents</groupId> <artif ...

  6. Httpclient 工具类(get,put)

    package com.googosoft.until; import java.io.IOException; import org.apache.http.HttpEntity; import o ...

  7. HttpUtil工具类,发送Get/Post请求,支持Http和Https协议

    HttpUtil工具类,发送Get/Post请求,支持Http和Https协议 使用用Httpclient封装的HttpUtil工具类,发送Get/Post请求 1. maven引入httpclien ...

  8. Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案

    要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...

  9. 170314、工具:apache httpClient多线程并发情况下安全实用及工具类分享

    简单用法介绍:介绍来源网络 建立连接:在HttpClient中使用多线程的一个主要原因是可以一次执行多个方法.在执行期间,每一个方法都使用一个HttpConnection实例.由于在同一时间多个连接只 ...

随机推荐

  1. 为什么Pojo类没有注解也没有spring中配置<bean>也能够被加载到容器中。

    Spring的注入机制其实就是代替了new的这个过程(称为解耦). 写了一个Thread类,没有加注解@Component,但是可以正常运行,开始为了自圆其说,打通逻辑,猜测是StartThread中 ...

  2. MySQL的下载与安装 和 navicat for mysql 安装使用

    新手上路-MySQL安装 目录结构 Windows平台 MySQL安装 示例数据导入 Linux平台 CentOS系统 Ubuntu系统 FAQ 密码生成工具-keepass 修改提示符 图形工具 删 ...

  3. 使用Docker构建redis集群--最靠谱的版本

    1集群结构说明 集群中有三个主节点,三个从节点,一共六个结点.因此要构建六个redis的docker容器.在宿主机中将这六个独立的redis结点关联成一个redis集群.需要用到官方提供的ruby脚本 ...

  4. Java多线程开发系列之四:玩转多线程(线程的控制2)

    在上节的线程控制(详情点击这里)中,我们讲解了线程的等待join().守护线程.本节我们将会把剩下的线程控制内容一并讲完,主要内容有线程的睡眠.让步.优先级.挂起和恢复.停止等. 废话不多说,我们直接 ...

  5. git 学习笔记

    1.创建git仓库 git init 2.添加文件 git add readme.txt 3.修改文件 git add readme.txt 4.提交修改 git commit -m "提交 ...

  6. CentOS7安装MariaDB10.1.14

    1.下载MariaDB 下载地址:https://downloads.mariadb.org/mariadb/10.1.14/ 这里选择mariadb-10.1.14-linux-x86_64.tar ...

  7. infoq - neo4j graph db

    My name is Charles Humble and I am here at QCon New York 2014 with Ian Robinson. Ian, can you introd ...

  8. C++ new和delete具体操作符是怎样的

    在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数.如下所示: int *p = (int*) malloc( sizeof(int) * 10 ); //分配10个i ...

  9. SQLite的优化总结

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下. 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2 ...

  10. CSS 盒子

    转载自:http://www.zblog.us/programing/web/css/cssbox-introduce-2.html 盒子模型定义 如果CSS对HTML文档元素生成了一个描述该元素在H ...