• Httpclient 支持https(转)


    参考:https://jingyan.baidu.com/article/154b46317353d228ca8f4112.html

    参考:https://www.jianshu.com/p/a44407f48321

           (一) 自httpclient-4.4开始,官方对代码进行了很多调整,4.4以前的很多class和method都过时了,而国内之前很多关于httpclient的分享都是4.4之前的。

            个人感觉使用Httpclient比较重要的是看它的代码,和官方的一些例子,可能是网络知识比较短板的原因,官方的tutorial其实看起来挺不清晰的,感觉主线不明确,不能引导你很好的学习,建议初学的人同时结合官网源码官方例子、tutorial进行学习。

            HttpClient-4.5.jar  

    @Test
    public void firstHttpClientDemo(){
    try {
                String url = "http://www.baidu.com";
                // 使用默认配置创建httpclient的实例
                CloseableHttpClient client = HttpClients.createDefault();
                
                HttpPost post = new HttpPost(url);
    //          HttpGet get = new HttpGet(url);
                
                CloseableHttpResponse response = client.execute(post);
    //          CloseableHttpResponse response = client.execute(get);
                
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println("status_code = " + status_code);
                
                // 服务器返回内容,请求到的是一个页面
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }

    这个demo主要是完成基本的交互过程,发送请求,接收消息,如果只是做小程序或者不是特别大并发量的系统,基本已经够用了。

    进行一些说明:

    1.需要向服务器发送请求,我们需要一个org.apache.http.client.HttpClient的实例对象,一般使用的都是org.apache.http.impl.client.CloseableHttpClient,创建该对象的最简单方法是CloseableHttpClient client = HttpClients.createDefault();,HttpClients是负责创建CloseableHttpClient的工厂,现在我们用最简单的方法就是使用默认配置去创建实例,后面我们再讨论有参数定制需求的实例创建方法。我们可以通过打断点的方式看到这个默认的实例对象的连接管理器 : org.apache.http.conn.HttpClientConnectionManager、请求配置 : org.apache.http.client.config.RequestConfig等配置的默认参数,这些都是后面需要了解的。

    2.构造请求方法HttpPost post = new HttpPost(url);表示我们希望用那种交互方法与服务器交互,HttpClient为每种交互方法都提供了一个类:HttpGet,
    HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, 还有 HttpOptions。

    3.向服务器提交请求CloseableHttpResponse response = client.execute(post);,很明显`CloseableHttpResponse就是用了处理返回数据的实体,通过它我们可以拿到返回的状态码、返回实体等等我们需要的东西。

    4.EntityUtils是官方提供一个处理返回实体的工具类,toString方法负责将返回实体装换为字符串,官方是不太建议使用这个类的,除非返回数据的服务器绝对可信和返回的内容长度是有限的。官方建议是自己使用HttpEntity#getContent()或者HttpEntity#writeTo(OutputStream),需要提醒的是记得关闭底层资源。

    5.EntityUtils.consume(entity);负责释放资源,通过源码可知,是需要把底层的流关闭:

    1.  
      InputStream instream = entity.getContent();
    2.  
      if (instream != null) {
    3.  
      instream.close();
    4.  
      }
    5.  
       

    好了,到此已经完成了httpclient的第一个demo。
    jar包地址:Apache HttpClient 4.5.2Apache HttpCore 4.4

    (二)跟服务器交互,更多的是发送数据,然后接收到服务器返回的数据,一般我们利用http-client中的实体(Entity),具体在org.apache.http.entity包下面的类来封装我们的请求,从服务器上接收的也是实体,这个在上一篇response.getEntity()可知。

    HttpClient根据内容的出处来区分3种实体:

    • 流式(Stream):内容从流(Stream)中接收,或者在运行中产生(generated on the fly)。

    • 自我包含(self-contained):内容在内存中或通过独立的连接或其他实体中获得。

    • 包装(wrapping):内容是从其他实体(Entity)中获得的。

    只有自我包含的实体是可以重复的,重复意味着可以被多次读取,如多次调用EntityUtils.toString(entity)。具体来讲有如:StringEntity、ByteArrayEntity……

    废话不多说,上代码,看看如何向服务器发送请求。

    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;

    @Test
    public void requestParaDemo(){
    try {
                String url = "http://localhost:9090";
                // 使用默认配置创建httpclient的实例
                CloseableHttpClient client = HttpClients.createDefault();
                
                HttpPost post = new HttpPost(url);
                
                /**
                 * 设置参数,常用的有StringEntity,UrlEncodedFormEntity,MultipartEntity
                 * 具体看org.apache.http.entity包
                 */
                List<NameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("username", "张三"));
                params.add(new BasicNameValuePair("password", "123456"));
                UrlEncodedFormEntity e = new UrlEncodedFormEntity(params, "UTF-8");
                post.setEntity(e);
                
                CloseableHttpResponse response = client.execute(post);
                
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println(status_code);
                
                // 服务器返回内容
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }

    }
     

    代码模拟了客户端向服务器发送一个表单数据,最常用的场景就是发送报文数据/登陆动作了。

    这段代码应该不需要过多的解释。

    来欣赏一下官方代码是如何完成一个登陆动作的:

    public void ClientFormLogin()throws Exception{
    BasicCookieStore cookieStore = new BasicCookieStore();
            CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
            try {
                HttpGet httpget = new HttpGet("https://someportal/");
                CloseableHttpResponse response1 = httpclient.execute(httpget);
                try {
                    HttpEntity entity = response1.getEntity();

                    System.out.println("Login form get: " + response1.getStatusLine());
                    EntityUtils.consume(entity);

                    System.out.println("Initial set of cookies:");
                    List<Cookie> cookies = cookieStore.getCookies();
                    if (cookies.isEmpty()) {
                        System.out.println("None");
                    } else {
                        for (int i = 0; i < cookies.size(); i++) {
                            System.out.println("- " + cookies.get(i).toString());
                        }
                    }
                } finally {
                    response1.close();
                }

                HttpUriRequest login = RequestBuilder.post().setUri(new URI("https://someportal/"))
                        .addParameter("IDToken1", "username").addParameter("IDToken2", "password").build();
                CloseableHttpResponse response2 = httpclient.execute(login);
                try {
                    HttpEntity entity = response2.getEntity();

                    System.out.println("Login form get: " + response2.getStatusLine());
                    EntityUtils.consume(entity);

                    System.out.println("Post logon cookies:");
                    List<Cookie> cookies = cookieStore.getCookies();
                    if (cookies.isEmpty()) {
                        System.out.println("None");
                    } else {
                        for (int i = 0; i < cookies.size(); i++) {
                            System.out.println("- " + cookies.get(i).toString());
                        }
                    }
                } finally {
                    response2.close();
                }
            } finally {
                httpclient.close();
            }

    }

    (三)我们在使用HttpClient的时候更多的是需要自己根据业务特点创建自己定制化的HttpClient实例,而不是像上面那样使用
     
    1.  
      // 使用默认配置创建httpclient的实例
    2.  
      CloseableHttpClient client = HttpClients.createDefault();
    废话不多说,直接上代码(Talk is cheap, show me the code!):
    1.  
      /**
    2.  
      * 使用httpclient-4.5.2发送请求,配置请求定制化参数
    3.  
      * @author chmod400
    4.  
      * 2016.3.28
    5.  
      */

    @Test
    public void requestConfigDemo(){
    try {
                String url = "http://www.baidu.com";
                /**
                 *  请求参数配置
                 *  connectionRequestTimeout:
                 *    从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
                 *    会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                 *  connectTimeout:
                 *    连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
                 *  socketTimeout:
                 *    服务器返回数据(response)的时间,超过该时间抛出read timeout
                 */
                CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectionRequestTimeout(2000).setConnectTimeout(2000).setSocketTimeout(2000).build()).build();
                
                HttpPost post = new HttpPost(url);
    //          HttpGet get = new HttpGet(url);
                
                CloseableHttpResponse response = client.execute(post);
    //          CloseableHttpResponse response = client.execute(get);
              
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println("status_code = " + status_code);
                
                // 服务器返回内容
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }

     

    需要说明的是,需要自己定制HttpClient客户端的话,我们使用HttpClients.custom(),然后调用各种set方法即可,一般建议使用HttpClients.custom().setDefaultRequestConfig()org.apache.http.client.config.RequestConfig类提供了很多可定制的参数,我们可以根据自己的配置来使用相关配置。有几个参数我们自己必须设置一下

    1.  
      connectionRequestTimeout:从连接池中获取连接的超时时间,超过该时间未拿到可用连接,        会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
    2.  
       
    connectTimeout:连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
    
    socketTimeout:服务器返回数据(response)的时间,超过该时间抛出read timeout
    

    通过打断点的方式我们知道,HttpClients在我们没有指定连接工厂的时候默认使用的是连接池工厂org.apache.http.impl.conn.PoolingHttpClientConnectionManager.PoolingHttpClientConnectionManager(Registry<ConnectionSocketFactory>),所以我们需要配置一下从连接池获取连接池的超时时间。

    以上3个超时相关的参数如果未配置,默认为-1,意味着无限大,就是一直阻塞等待!

    官方提供了一个demo,里面有一些最常用的配置代码,仅供参考:

     

    /*
     * ====================================================================
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     * ====================================================================
     *
     * This software consists of voluntary contributions made by many
     * individuals on behalf of the Apache Software Foundation.  For more
     * information on the Apache Software Foundation, please see
     * <http://www.apache.org/>.
     *
     */


    package org.apache.http.examples.client;


    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.nio.charset.CodingErrorAction;
    import java.util.Arrays;


    import javax.net.ssl.SSLContext;


    import org.apache.http.Consts;
    import org.apache.http.Header;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpRequest;
    import org.apache.http.HttpResponse;
    import org.apache.http.ParseException;
    import org.apache.http.client.CookieStore;
    import org.apache.http.client.CredentialsProvider;
    import org.apache.http.client.config.AuthSchemes;
    import org.apache.http.client.config.CookieSpecs;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.protocol.HttpClientContext;
    import org.apache.http.config.ConnectionConfig;
    import org.apache.http.config.MessageConstraints;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.config.SocketConfig;
    import org.apache.http.conn.DnsResolver;
    import org.apache.http.conn.HttpConnectionFactory;
    import org.apache.http.conn.ManagedHttpClientConnection;
    import org.apache.http.conn.routing.HttpRoute;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.DefaultHttpResponseFactory;
    import org.apache.http.impl.client.BasicCookieStore;
    import org.apache.http.impl.client.BasicCredentialsProvider;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.DefaultHttpResponseParser;
    import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
    import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.impl.conn.SystemDefaultDnsResolver;
    import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
    import org.apache.http.io.HttpMessageParser;
    import org.apache.http.io.HttpMessageParserFactory;
    import org.apache.http.io.HttpMessageWriterFactory;
    import org.apache.http.io.SessionInputBuffer;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.message.BasicLineParser;
    import org.apache.http.message.LineParser;
    import org.apache.http.ssl.SSLContexts;
    import org.apache.http.util.CharArrayBuffer;
    import org.apache.http.util.EntityUtils;


    /**
     * This example demonstrates how to customize and configure the most common aspects
     * of HTTP request execution and connection management.
     */
    public class ClientConfiguration {


        public final static void main(String[] args) throws Exception {


            // Use custom message parser / writer to customize the way HTTP
            // messages are parsed from and written out to the data stream.
            HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {


                @Override
                public HttpMessageParser<HttpResponse> create(
                    SessionInputBuffer buffer, MessageConstraints constraints) {
                    LineParser lineParser = new BasicLineParser() {


                        @Override
                        public Header parseHeader(final CharArrayBuffer buffer) {
                            try {
                                return super.parseHeader(buffer);
                            } catch (ParseException ex) {
                                return new BasicHeader(buffer.toString(), null);
                            }
                        }


                    };
                    return new DefaultHttpResponseParser(
                        buffer, lineParser, DefaultHttpResponseFactory.INSTANCE, constraints) {


                        @Override
                        protected boolean reject(final CharArrayBuffer line, int count) {
                            // try to ignore all garbage preceding a status line infinitely
                            return false;
                        }


                    };
                }


            };
            HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();


            // Use a custom connection factory to customize the process of
            // initialization of outgoing HTTP connections. Beside standard connection
            // configuration parameters HTTP connection factory can define message
            // parser / writer routines to be employed by individual connections.
            HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
                    requestWriterFactory, responseParserFactory);


            // Client HTTP connection objects when fully initialized can be bound to
            // an arbitrary network socket. The process of network socket initialization,
            // its connection to a remote address and binding to a local one is controlled
            // by a connection socket factory.


            // SSL context for secure connections can be created either based on
            // system or application specific properties.
            SSLContext sslcontext = SSLContexts.createSystemDefault();


            // Create a registry of custom connection socket factories for supported
            // protocol schemes.
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslcontext))
                .build();


            // Use custom DNS resolver to override the system DNS resolution.
            DnsResolver dnsResolver = new SystemDefaultDnsResolver() {


                @Override
                public InetAddress[] resolve(final String host) throws UnknownHostException {
                    if (host.equalsIgnoreCase("myhost")) {
                        return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
                    } else {
                        return super.resolve(host);
                    }
                }


            };


            // Create a connection manager with custom configuration.
            PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry, connFactory, dnsResolver);


            // Create socket configuration
            SocketConfig socketConfig = SocketConfig.custom()
                .setTcpNoDelay(true)
                .build();
            // Configure the connection manager to use socket configuration either
            // by default or for a specific host.
            connManager.setDefaultSocketConfig(socketConfig);
            connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);
            // Validate connections after 1 sec of inactivity
            connManager.setValidateAfterInactivity(1000);


            // Create message constraints
            MessageConstraints messageConstraints = MessageConstraints.custom()
                .setMaxHeaderCount(200)
                .setMaxLineLength(2000)
                .build();
            // Create connection configuration
            ConnectionConfig connectionConfig = ConnectionConfig.custom()
                .setMalformedInputAction(CodingErrorAction.IGNORE)
                .setUnmappableInputAction(CodingErrorAction.IGNORE)
                .setCharset(Consts.UTF_8)
                .setMessageConstraints(messageConstraints)
                .build();
            // Configure the connection manager to use connection configuration either
            // by default or for a specific host.
            connManager.setDefaultConnectionConfig(connectionConfig);
            connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);


            // Configure total max or per route limits for persistent connections
            // that can be kept in the pool or leased by the connection manager.
            connManager.setMaxTotal(100);
            connManager.setDefaultMaxPerRoute(10);
            connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);


            // Use custom cookie store if necessary.
            CookieStore cookieStore = new BasicCookieStore();
            // Use custom credentials provider if necessary.
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            // Create global request configuration
            RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setCookieSpec(CookieSpecs.DEFAULT)
                .setExpectContinueEnabled(true)
                .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
                .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
                .build();


            // Create an HttpClient with the given custom dependencies and configuration.
            CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setDefaultCookieStore(cookieStore)
                .setDefaultCredentialsProvider(credentialsProvider)
                .setProxy(new HttpHost("myproxy", 8080))
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();


            try {
                HttpGet httpget = new HttpGet("http://httpbin.org/get");
                // Request configuration can be overridden at the request level.
                // They will take precedence over the one set at the client level.
                RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .setProxy(new HttpHost("myotherproxy", 8080))
                    .build();
                httpget.setConfig(requestConfig);


                // Execution context can be customized locally.
                HttpClientContext context = HttpClientContext.create();
                // Contextual attributes set the local context level will take
                // precedence over those set at the client level.
                context.setCookieStore(cookieStore);
                context.setCredentialsProvider(credentialsProvider);


                System.out.println("executing request " + httpget.getURI());
                CloseableHttpResponse response = httpclient.execute(httpget, context);
                try {
                    System.out.println("----------------------------------------");
                    System.out.println(response.getStatusLine());
                    System.out.println(EntityUtils.toString(response.getEntity()));
                    System.out.println("----------------------------------------");


                    // Once the request has been executed the local context can
                    // be used to examine updated state and various objects affected
                    // by the request execution.


                    // Last executed request
                    context.getRequest();
                    // Execution route
                    context.getHttpRoute();
                    // Target auth state
                    context.getTargetAuthState();
                    // Proxy auth state
                    context.getTargetAuthState();
                    // Cookie origin
                    context.getCookieOrigin();
                    // Cookie spec used
                    context.getCookieSpec();
                    // User security token
                    context.getUserToken();


                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
        }


    }

    (四) 

    总结一下HttpClient发送https请求相关的内容。
    先简单介绍连接工厂(interface org.apache.http.conn.socket.ConnectionSocketFactory),连接工厂主要用于创建、初始化、连接socket。org.apache.http.conn.socket.PlainConnectionSocketFactory是默认的socket工厂,用于创建无加密(unencrypted)socket对象。创建https需要使用org.apache.http.conn.ssl.SSLConnectionSocketFactoryPlainConnectionSocketFactorySSLConnectionSocketFactory都实现了ConnectionSocketFactory
    好了,直接上代码,代码实现的功能是,组装一个发往银联的查询报文(查询交易结果)。

    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;


    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;


    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;


    /**
     * This example demonstrates how to create secure connections with a custom SSL
     * context.
     */
    public class ClientCustomSSL {
        private static String reqStr = "txnType=00&signMethod=01&certId=68759663125&encoding=UTF-8&merId=777290058110048&bizType=000201&txnSubType=00&signature=k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D&orderId=20160309145206&version=5.0.0&txnTime=20160309145206&accessType=0";
        private static String url = "https://101.231.204.80:5000/gateway/api/queryTrans.do";


        // 信任管理器
        private static X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        
        public final static void main(String[] args) throws Exception {
            long starttime = System.currentTimeMillis();
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSL上下文
            sslContext.init(null, new TrustManager[] { tm }, null);
            // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
            /**
             * 通过setSSLSocketFactory(sslsf)保证httpclient实例能发送Https请求
             */
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setMaxConnTotal(50)
                    .setMaxConnPerRoute(50).setDefaultRequestConfig(RequestConfig.custom()
                            .setConnectionRequestTimeout(60000).setConnectTimeout(60000).setSocketTimeout(60000).build())
                    .build();
            try {

                HttpPost httppost = new HttpPost(url);
                
                // 设置参数,参数含义不需要理解
                Map<String, String> map = new HashMap<String, String>();
                map.put("txnType","00");
                map.put("signMethod","01");
                map.put("certId","68759663125");
                map.put("encoding","UTF-8");
                map.put("merId","777290058110048");
                map.put("bizType","000201");
                map.put("txnSubType","00");
                map.put("signature","k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D");
                map.put("orderId","20160309145206");
                map.put("version","5.0.0");
                map.put("txnTime","20160309145206");
                map.put("accessType","0");
                
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Entry<String, String> elem = (Entry<String, String>) iterator.next();
                    list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
                }
                if (list.size() > 0) {
                    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
                    httppost.setEntity(entity);
                }
                
                System.out.println("executing request " + httppost.getRequestLine());

                CloseableHttpResponse response = httpclient.execute(httppost);
                try {
                    HttpEntity entity = response.getEntity();

                    System.out.println("----------------------------------------");
                    System.out.println(response.getStatusLine());
                    if (entity != null) {
                        System.out.println("Response content length: " + entity.getContentLength());
                    }
                    String s = EntityUtils.toString(entity,"UTF-8");
                    System.out.println("应答内容:" + s);
                    
                    EntityUtils.consume(entity);
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
            
            long endtime = System.currentTimeMillis();
            System.out.println("耗时:" + (endtime-starttime) + "ms");
        }

    }

    使用注册器可以保证既能发送http请求也能发送httpsclient请求,代码块如下:

    int httpReqTimeOut = 60000;//60秒


    SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSL上下文
            sslContext.init(null, new TrustManager[] { tm }, null);
            // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
            // 注册http套接字工厂和https套接字工厂
            Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", sslsf)
                    .build();
            // 连接池管理器
            PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);
            pcm.setMaxTotal(maxConnTotal);//连接池最大连接数
            pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数
            /**
             *  请求参数配置
             *  connectionRequestTimeout:
             *                          从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
             *                          会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
             *  connectTimeout:
             *                  连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
             *  socketTimeout:
             *                  服务器返回数据(response)的时间,超过该时间抛出read timeout
             */
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(httpReqTimeOut)
                    .setConnectTimeout(httpReqTimeOut)
                    .setSocketTimeout(httpReqTimeOut)
                    .build();
            /**
             * 构造closeableHttpClient对象
             */
            closeableHttpClient = HttpClients.custom()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(pcm)
                    .setRetryHandler(retryHandler)
                    .build();

     
    关键代码为:
            // 注册http套接字工厂和https套接字工厂
            Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", sslsf)
                    .build();
  • 相关阅读:
    java线程池源码阅读
    websocketcometd源码阅读基于注解初始化(三)
    websocketcometd源码阅读与spring整合初始化(四)
    cometd源码阅读初始化(二)
    cometd源码阅读WebSocketTransport普通消息处理过程(八)
    websocketcometd源码阅读transport(五)
    一.安装软件
    GitHub一篇文章系列
    JavaJVM调优jstack找出最耗cpu的线程&定位问题代码
    Git总目录
  • 原文地址:https://www.cnblogs.com/wq920/p/9932027.html
Copyright © 2020-2023  润新知