zoukankan      html  css  js  c++  java
  • 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();
  • 相关阅读:
    平衡二叉树之RB树
    平衡二叉树之AVL树
    实现哈希表
    LeetCode Median of Two Sorted Arrays
    LeetCode Minimum Window Substring
    LeetCode Interleaving String
    LeetCode Regular Expression Matching
    PAT 1087 All Roads Lead to Rome
    PAT 1086 Tree Traversals Again
    LeetCode Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/wq920/p/9932027.html
Copyright © 2011-2022 走看看