场景:调用外部系统接口的http请求

要求:

1:可能是http请求,也可能是https请求

2:需要加入连接池的概念,不能每次发起请求都新建一个连接(每次连接握手三次,效率太低)

准备使用httpclient 4.5的版本

HTTPClient的特性

1. 基于标准、纯净的Java语言。实现了Http1.0和Http1.1

2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。

3. 支持HTTPS协议。

4. 通过Http代理建立透明的连接。

5. 利用CONNECT方法通过Http代理建立隧道的https连接。

6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。

7. 插件式的自定义认证方案。

8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。

9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。

10. 自动处理Set-Cookie中的Cookie。

11. 插件式的自定义Cookie策略。

12. Request的输出流可以避免流中内容直接缓冲到socket服务器。

13. Response的输入流可以有效的从socket服务器直接读取相应内容。

14. 在http1.0和http1.1中利用KeepAlive保持持久连接。

15. 直接获取服务器发送的response code和 headers。

16. 设置连接超时的能力。

17. 实验性的支持http1.1 response caching。

18. 源代码基于Apache License 可免费获取。

在HttpClient 4.x版本中引入了大量的构造器设计模式,很多的配置都不建议直接new出来,而且相关的API也有所改动,例如连接参数,以前是直接new出HttpConnectionParams对象后通过set方法逐一设置属性,现在有了构造器,可以通过如下方式进行构造:

  1. ConnectionConfig.custom().setCharset(Charsets.toCharset(defaultEncoding)).build();
  2. SocketConfig.custom().setSoTimeout(100000).build();

实现访问自签名https的要点就是建立一个自定义的SSLContext对象,该对象要有可以存储信任密钥的容器,还要有判断当前连接是否受信任的策略,以及在SSL连接工厂中取消对所有主机名的验证。他的代码将会在本文最后贴出来,以下代码均针对新HttpClient

首先建立一个信任任何密钥的策略。代码很简单,不去考虑证书链和授权类型,均认为是受信任的

  1. class AnyTrustStrategy implements TrustStrategy{  
    
        @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    return true;
    }
    }

HttpClient既能处理常规http协议,又能支持https,根源在于在连接管理器中注册了不同的连接创建工厂。当访问url的schema为http时,调用明文连接套节工厂来建立连接;当访问url的schema为https时,调用SSL连接套接字工厂来建立连接。对于http的连接我们不做修改,只针对使用SSL的https连接来进行自定义:

RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();  
ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
//指定信任密钥存储对象和连接套接字工厂
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, new AnyTrustStrategy()).build();
LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
registryBuilder.register("https", sslSF);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
Registry<ConnectionSocketFactory> registry = registryBuilder.build();

在上述代码中可以看到,首先建立了一个密钥存储容器,随后让SSLContext开启TLS,并将密钥存储容器和信任任何主机的策略加载到该上下文中。构造SSL连接工厂时,将自定义的上下文和允许任何主机名通过校验的指令一并传入。最后将这样一个自定义的SSL连接工厂注册到https协议上。

前期准备已经完成,接下来我们要获得HttpClient对象:

//设置连接管理器
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
connManager.setDefaultConnectionConfig(connConfig);
connManager.setDefaultSocketConfig(socketConfig);
//构建客户端
HttpClient client= HttpClientBuilder.create().setConnectionManager(connManager).build();

为了让我们的HttpClient具有多线程处理的能力,连接管理器选用了PoolingHttpClientConnectionManager,将协议注册信息传入连接管理器,最后再次利用构造器的模式创建出我们需要的HttpClient。随后的GET/POST请求发起方法http和https之间没有差异。

HttpClient 基于连接池的使用的更多相关文章

  1. httpclient httpclient使用连接池

    httpclient使用连接池 http协议是无状态的,但毕竟是基于tcp的,底层还是需要和服务器连接的, 对于需要从同一个站点抓取大量网页的程序,应该使用连接池,否则每次抓取都和web站点建立连接, ...

  2. httpclient: 设置连接池及超时配置,请求数据:PoolingHttpClientConnectionManager

    public static void main(String[] args) throws Exception{ //httpclient连接池 //创建连接池 PoolingHttpClientCo ...

  3. Http持久连接与HttpClient连接池

    一.背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的.因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接. HTTP协议是全双工的协议, ...

  4. HttpClient实战二:单线程和多线程连接池实例

    为什么使用HTTP连接池? 随着系统架构风格逐渐向前后端分离架构,微服务架构转变,RestFul风格API的开发与设计,同时SpringMVC也很好的支持了REST风格接口.各个系统之间服务的调用大多 ...

  5. Http 持久连接与 HttpClient 连接池

    一.背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的.因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接. HTTP协议是全双工的协议, ...

  6. HttpClient连接池的一些思考

    前言 使用apache的httpclient进行http的交互处理已经很长时间了,而httpclient实例则使用了http连接池,想必大家也没有关心过连接池的管理.事实上,通过分析httpclien ...

  7. 基于HiKariCP组件,分析连接池原理

    HiKariCP作为SpringBoot2框架的默认连接池,号称是跑的最快的连接池,数据库连接池与之前两篇提到的线程池和对象池,从设计的原理上都是基于池化思想,只是在实现方式上有各自的特点:

  8. 带有连接池的Http客户端工具类HttpClientUtil

    一.背景 业务开发中,经常会遇到通过http/https向下游服务发送请求.每次都要重复造轮子写HttpClient的逻辑,而且性能.功能参差不齐.这里分享一个高性能的.带连接池的通用Http客户端工 ...

  9. 走进JavaWeb技术世界3:JDBC的进化与连接池技术

    走进JavaWeb技术世界3:JDBC的进化与连接池技术 转载公众号[码农翻身] 网络访问 随着 Oracle, Sybase, SQL Server ,DB2,  Mysql 等人陆陆续续住进数据库 ...

随机推荐

  1. MySQL: [Err] 1093 - You can't specify target table 'bk' for update in FROM clause

    错误的意思说,不能先select出同一表中的某些值,再update这个表(在同一语句中). 例如下面这个sql: delete from tbl where id in (        select ...

  2. HDU ACM Fibonacci

    Problem Description Fibonacci numbers are well-known as follow: Now given an integer N, please find ...

  3. 【287】◀▶ arcpy 常用类说明

    ArcPy 类列表(按字母顺序) 01   Raster 创建一个可在 Python 脚本或地图代数表达式中使用的栅格对象. 02   Cursor Cursor 是一种数据访问对象,可用于在表中迭代 ...

  4. 什么是HUD

    [什么是HUD] 游戏HUD的意思: 说直白点就是在屏幕上显示你的游戏相关信息,让玩家可以随时了解那些最重要最直接相关的内容.就是说,像我们玩游戏的时候,显示您的武器耐久度不够了,您的血量不足了等等. ...

  5. GIT常用命令以及作用【备忘】

    git commit  提交一个修改 git branch branchName  新建一个branchName的分支 git merge branchName 将当前分支与branchName分支合 ...

  6. 使用百度翻译的API接口

    http://api.fanyi.baidu.com/api/trans/product/desktop 这是申请的接口地址,会得到一个APPID和一个钥密 然后下载PHP的对应的代码 有一个PHP文 ...

  7. Lambda03 方法引用、类型判断、变量引用

    1 方法引用 1.1 方法引用的好处 方法引用结合 Lambda 可以引用已存在的方法,省略很多编码,而且可读性更强,它可以自动装配参数与返回值. 在编写lambda表达式的时候可以通过方法引用的方式 ...

  8. SpringBoot17 FastJson配置、Druid配置

    1 FastJson配置 1.1 FastJson基础知识 点击前往 1.2 SpringBoot整合FastJson 点击前往 1.2.1 导入FastJson依赖 <!--fastjson- ...

  9. 使用RVM更新Ruby 版本

    http://rvm.io/rvm/install Install RVM (development version): \curl -sSL https://get.rvm.io | bash Wi ...

  10. Part10-C语言环境初始化-C与汇编混合编程lesson4

    1.为什么要混合编程 汇编语言:执行效率高:编写繁琐: 执行效率高:能够更直接地控制处理器. c语言:可读性强,移植性好,调试方便. 1.汇编调用c函数 2.c调用汇编函数 汇编语言定义的函数(标号) ...