• HttpClient 基于连接池的使用


    场景:调用外部系统接口的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之间没有差异。

  • 相关阅读:
    webpack4从0开始构建前端单页项目(8)处理css的loader
    webpack4从0开始构建前端单页项目(7)用babel-loader处理js㈣transform-runtime
    webpack4从0开始构建前端单页项目(6)用babel-loader处理js㈢babel-polyfill
    webpack4从0开始构建前端单页项目(5)用babel-loader处理js㈡.babelrc文件
    webpack4从0开始构建前端单页项目(4)用babel-loader处理js㈠配置
    webpack4从0开始构建前端单页项目(3)用webpack-dev-server搭建热加载开发环境
    webpack4从0开始构建前端单页项目(2)用html-webpack-plugin生成html文件
    webpack4从0开始构建前端单页项目(1)整理目录
    webpack二刷笔记(4)webpack的核心概念-插件(plugin)
    webpack二刷笔记(3)webpack的核心概念-loader
  • 原文地址:https://www.cnblogs.com/lodor/p/6775112.html
Copyright © 2020-2023  润新知