参考: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();

Httpclient 支持https(转)的更多相关文章

  1. android httpClient 支持HTTPS的2种处理方式

    摘自: http://www.kankanews.com/ICkengine/archives/9634.shtml 项目中Android https或http请求地址重定向为HTTPS的地址,相信很 ...

  2. android httpClient 支持HTTPS的访问方式

    项目中Android https请求地址遇到了这个异常,javax.net.ssl.SSLPeerUnverifiedException: No peer certificate,是SSL协议中没有终 ...

  3. Android进阶(三)android httpClient 支持HTTPS的访问方式

    项目中Android https请求地址遇到了这个异常(无终端认证): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 是S ...

  4. 在 IIS 6 和 IIS 7中配置Https,设置WCF同时支持HTTP和HTPPS,以及使用HttpWebRequest和HttpClient调用HttpS

    IIS 7 ,给IIS添加CA证书以支持https IIS 6 架设证书服务器 及 让IIS启用HTTPS服务 WCF IIS 7中配置HTTPS C#利用HttpWebRequest进行post请求 ...

  5. 使用HttpClient发送HTTPS请求以及配置Tomcat支持SSL

    这里使用的是HttpComponents-Client-4.1.2 package com.jadyer.util; import java.io.File; import java.io.FileI ...

  6. httpclient调用https

    httpclient调用https报错: Exception in thread "main" java.lang.Exception: sun.security.validato ...

  7. 【转】让 cocos2d-x 的 CCHttpRequest 支持https

    肖锐(Cooki)个人原创,欢迎转载,转载请注明地址,肖锐(Cooki)的技术博客 http://blog.csdn.net/xiao0026  由于游戏用到了网络头像, 今天发现换成facebook ...

  8. Retrofit 2.0 超能实践(一),okHttp完美支持Https传输

    http: //blog.csdn.net/sk719887916/article/details/51597816 Tamic首发 前阵子看到圈子里Retrofit 2.0,RxJava(Andro ...

  9. Retrofit 2.0 超能实践,完美支持Https传输

    http://blog.csdn.NET/sk719887916/article/details/51597816 前阵子看到圈子里Retrofit 2.0,RxJava(Android), OkHt ...

随机推荐

  1. 面试官问:JS的this指向

    前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...

  2. Javaworkers团队最终项目总结

    Javaworkers团队最终项目总结 小组成员 20145205武钰 20145222黄亚奇 20145235李涛 20145103冯文华 团队项目总结 案例提出及工程用时 本次项目由十一到十六周共 ...

  3. 在JAVA可移植性的来源的三方面

    软件可移植性的概念是与软件从某一环境转移到另一环境下的难易程度.为获得较高的可移植性,在设计过程中常采用通用的程序设计语言和运行支撑环境.尽量不用与系统的底层相关性强的语言.下面介绍JAVA的可移植性 ...

  4. root权限和sudo得到权限的区别

    参考: 知乎 命令前加sudo执行和用真正的root用户执行有什么区别?pansz的回答 root用户和sudo使用root权限的区别 变换用户身份为root的方法su 与 sudo root权限和s ...

  5. 原生DOM操作vs框架虚拟DOM比较

    1. 原生 DOM 操作 vs. 通过框架封装操作. 这是一个性能 vs. 可维护性的取舍.框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护.没 ...

  6. [BZOJ1257][CQOI2007]余数之和

    题目大意 给你 \(n, k\),计算 $ \sum_{i=1}^n k \bmod i$ 解析 注意到 $ k\bmod i=k-[k/i] \times i$ 则上式等于 $ n \times k ...

  7. Sublime编辑器上的Linux Vim插件常用快捷键

    Sublime编辑器上的 Vim 插件常用快捷键 vim 的设置: 在Reference-> User Settings(首选项--> 设置用户) 选项,点击进入配置文件编辑状态,默认的用 ...

  8. Linux删除(清空)正在运行的应用日志文件内容 及 查看服务器剩余空间

    在测试环境定位问题时,如果发现日志文件内容太多或太大,有时需要删除该日志,如Tomcat,Nginx日志.以前每次都是先rm -rf ***.log,然后重启应用.直到后来发现了以下命令,原来可以不用 ...

  9. 雷林鹏分享:Ruby CGI Cookies

    Ruby CGI Cookies HTTP协议是无状态协议.但对于一个商业网站,它需要保持不同的页面间的会话信息. 如用户在网站注册过程中需要跳转页面,但又要保证之前填写的信息部丢失. 这种情况下 C ...

  10. sql语句中处理金额,把分换算成元

    问题,sql语句中直接将金额/100返回的结果会有多个小数位. as value from account as acc left join conCategory as cate on acc.ca ...