【fastweixin框架教程3】JAVA进行HTTPS网站访问,PKIX path building failed解决方法

上几篇文章我们谈到fastweixin使用问题和修改。

今天的问题就是使用JAVA访问HTTPS网站时候经常出现javax.net.ssl.SSLHandshakeException

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)

at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)

at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)

at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)

at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)

at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)

at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)

at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)

at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)

at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)

对于这个问题,一般采用两种方法:1、导入疼讯网站证书 2、修改代码

考虑到很多人的服务器并不是自主控制,无法进行第一种方法,导入证书,下面决定修改原框架代码以便适应HTTPS。

package com.fastwixinextend;

import com.github.sd4324530.fastweixin.util.NetWorkCenter;

import java.io.File;
import java.io.IOException;

import java.net.URL;

import java.nio.charset.Charset;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
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.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * com.github.sd4324530.fastweixin.util.NetWorkCenter 修改版本
 * http://blog.csdn.net/xiaoxian8023/article/details/49865335
 *
 * 将 com.github.sd4324530.fastweixin.util修改 public final class NetWorkCenter
 * extends MyNetWorkCenter {
 *
 * 采用https的访问协议获取新的AccessToken时,总是出现异常: javax.net.ssl.SSLHandshakeException:
 * sun.security.validator.ValidatorException: PKIX path building failed:
 * sun.security.provider.certpath.SunCertPathBuilderException: unable to find
 * valid certification path to requested target 之后在网上找了很多例子,最后摘了一个不需要证书的例子:
 */
public class MyNetWorkCenter {

    /**
     * 默认连接超时时间(毫秒) 由于目前的设计原因,该变量定义为静态的,超时时间不能针对每一次的请求做定制 备选优化方案:
     * 1.考虑是否重新设计这个工具类,每次请求都需要创建一个实例; 2.请求方法里加入超时时间参数
     * 或者说是否没必要定制,10秒是一个比较适中的选择,但有些请求可能就是需要快速给出结果T_T
     */
    public static final int CONNECT_TIMEOUT = 10 * 1000;
    private static final Logger LOG
            = LoggerFactory.getLogger(NetWorkCenter.class);
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    public MyNetWorkCenter() {
        super();
    }

    /**
     * 自定义HTTP响应回调接口,用于兼容jdk6
     *
     * @author peiyu
     * @since 1.1
     */
    //  @FunctionalInterface
    public interface ResponseCallback {

        /**
         * 响应后回调方法
         *
         * @param resultCode 响应结果码,比如200成功,404不存在,500服务器异常等
         * @param resultJson 响应内容,目前支持JSON字符串
         */
        void onResponse(int resultCode, String resultJson);
    }

    /**
     * 标识HTTP请求类型枚举
     *
     * @author peiyu
     * @since 1.0
     */
    public enum RequestMethod {
        /**
         * HTTP GET请求 一般对应的是查询业务接口
         */
        GET,
        /**
         * HTTP POST请求 一般对应的是新增业务接口 只是一般都通用这个请求方式来处理一切接口了T_T
         */
        POST,
        /**
         * HTTP PUT请求,用的太少,暂不支持 一般对应的是更新业务接口
         */
        PUT,
        /**
         * HTTP DELETE请求,用的太少,暂不支持 一般对应的是删除业务接口
         */
        DELETE;
        private static final long serialVersionUID = 1L;
    }

    /**
     * 处理HTTP请求 基于org.apache.http.client包做了简单的二次封装 对于子函数,修改doRequest() String
     * ishttp=url.toLowerCase(); if(ishttp.startsWith("https") ||
     * ishttp.startsWith("HTTPS")) { doRequestSSH(method, url, paramData,
     * fileList, callback); return; }
     *
     * @param method HTTP请求类型
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void doRequestSSH(final RequestMethod method, final String url,
            final String paramData,
            final List<File> fileList,
            final ResponseCallback callback) {
        //如果url没有传入,则直接返回
        if (null == url || url.isEmpty()) {
            LOG.warn("The url is null or empty!!You must give it to me!OK?");
            return;
        }

        //默认期望调用者传入callback函数
        boolean haveCallback = true;
        /*
         * 支持不传回调函数,只输出一个警告,并改变haveCallback标识
                 * 用于一些不需要后续处理的请求,比如只是发送一个心跳包等等
         */
        if (null == callback) {
            LOG.warn("--------------no callback block!--------------");
            haveCallback = false;
        }

        LOG.debug("-----------------请求地址:{}-----------------", url);
        //配置请求参数
        RequestConfig config
                = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(CONNECT_TIMEOUT).build();

        SSLContext sslcontext = null;

        // 设置协议http和https对应的处理socket链接工厂的对象
        try {
            sslcontext = SslUtils.createIgnoreVerifySSL();
        } catch (KeyManagementException e) {
        } catch (NoSuchAlgorithmException e) {
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry
                = RegistryBuilder.<ConnectionSocketFactory>create().register("http",
                        PlainConnectionSocketFactory.INSTANCE).register("https",
                        new SSLConnectionSocketFactory(sslcontext)).build();
        PoolingHttpClientConnectionManager connManager
                = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);

        //创建自定义的httpclient对象
        HttpClientBuilder HttpClientbuilder = HttpClients.custom().setConnectionManager(connManager);
        HttpClientbuilder.setDefaultRequestConfig(config);
        CloseableHttpClient client = HttpClientbuilder.build();
        //CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpUriRequest request = null;
        switch (method) {
            case GET:
                String getUrl = url;
                if (null != paramData) {
                    getUrl += "?" + paramData;
                }
                request = new HttpGet(getUrl);
                break;
            case POST:
                LOG.debug("请求入参:");
                LOG.debug(paramData);
                request = new HttpPost(url);
                //上传文件
                if (null != fileList && !fileList.isEmpty()) {
                    LOG.debug("上传文件...");
                    MultipartEntityBuilder builder
                            = MultipartEntityBuilder.create();
                    for (File file : fileList) {
                        //只能上传文件哦 ^_^
                        if (file.isFile()) {
                            FileBody fb = new FileBody(file);
                            builder.addPart("media", fb);
                        } else { //如果上传内容有不是文件的,则不发起本次请求
                            LOG.warn("The target '{}' not a file,please check and try again!",
                                    file.getPath());
                            return;
                        }
                    }
                    if (null != paramData) {
                        builder.addPart("description",
                                new StringBody(paramData, ContentType.APPLICATION_JSON));
                    }
                    ((HttpPost) request).setEntity(builder.build());
                } else //不上传文件的普通请求
                {
                    if (null != paramData) {
                        // 目前支持JSON格式的数据
                        StringEntity jsonEntity
                                = new StringEntity(paramData, ContentType.APPLICATION_JSON);
                        ((HttpPost) request).setEntity(jsonEntity);
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                LOG.warn("-----------------请求类型:{} 暂不支持-----------------",
                        method.toString());
                break;
        }
        CloseableHttpResponse response = null;
        try {
            URL u = new URL(url);
            if ("https".equalsIgnoreCase(u.getProtocol())) {
                SslUtils.ignoreSsl();
            }
            long start = System.currentTimeMillis();
            //发起请求
            response = client.execute(request);
            long time = System.currentTimeMillis() - start;
            LOG.debug("本次请求'{}'耗时:{}ms",
                    url.substring(url.lastIndexOf("/") + 1, url.length()),
                    time);
            int resultCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            //此流不是操作系统资源,不用关闭,ByteArrayOutputStream源码里close也是个空方法-0_0-
            //            OutputStream os = new ByteArrayOutputStream();
            //            entity.writeTo(os);
            //            String resultJson = os.toString();
            String resultJson = EntityUtils.toString(entity, UTF_8);
            //返回码200,请求成功;其他情况都为请求出现错误
            if (HttpStatus.SC_OK == resultCode) {
                LOG.debug("-----------------请求成功-----------------");
                LOG.debug("响应结果:");
                LOG.debug(resultJson);
                if (haveCallback) {
                    callback.onResponse(resultCode, resultJson);
                }
            } else if (haveCallback) {
                LOG.warn("-----------------请求出现错误,错误码:{}-----------------",
                        resultCode);
                callback.onResponse(resultCode, resultJson);
            }
        } catch (ClientProtocolException e) {
            LOG.error("ClientProtocolException:", e);
            LOG.warn("-----------------请求出现异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } catch (IOException e) {
            LOG.error("IOException:", e);
            LOG.warn("-----------------请求出现IO异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } catch (Exception e) {
            LOG.error("Exception:", e);
            LOG.warn("-----------------请求出现其他异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }
    }
}

原文件NetWorkCenter 修改如下:

package com.github.sd4324530.fastweixin.util;

import com.fastwixinextend.MyNetWorkCenter.RequestMethod;
import com.fastwixinextend.MyNetWorkCenter.ResponseCallback;

import com.github.sd4324530.fastweixin.api.response.BaseResponse;

import com.fastwixinextend.MyNetWorkCenter;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
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.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * HTTP请求客户端操作类,基于org.apache.http.client包4.4.x版本实现
 */
public final class NetWorkCenter extends MyNetWorkCenter {

    /**
     * 默认连接超时时间(毫秒) 由于目前的设计原因,该变量定义为静态的,超时时间不能针对每一次的请求做定制 备选优化方案:
     * 1.考虑是否重新设计这个工具类,每次请求都需要创建一个实例; 2.请求方法里加入超时时间参数
     * 或者说是否没必要定制,10秒是一个比较适中的选择,但有些请求可能就是需要快速给出结果T_T
     */
    public static final int CONNECT_TIMEOUT = 10 * 1000;
    /**
     * 日志输出组件
     */
    private static final Logger LOG = LoggerFactory.getLogger(NetWorkCenter.class);
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    /**
     * 私有化构造器 不允许外界创建实例
     */
    private NetWorkCenter() {
        LOG.warn("Oh,my god!!!How do you call this method?!");
        LOG.warn("You shouldn't create me!!!");
        LOG.warn("Look my doc again!!!");
    }

    /**
     * 发起HTTP POST同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void post(String url, String paramData,
            ResponseCallback callback) {
        post(url, paramData, null, callback);
    }

    public static BaseResponse post(String url, String paramData) {
        final BaseResponse[] response = new BaseResponse[]{null};
        post(url, paramData, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 发起HTTP POST同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void post(String url, String paramData, List<File> fileList,
            ResponseCallback callback) {
        doRequest(MyNetWorkCenter.RequestMethod.POST, url, paramData, fileList, callback);
    }

    public static BaseResponse post(String url, String paramData, List<File> fileList) {
        final BaseResponse[] response = new BaseResponse[]{null};
        post(url, paramData, fileList, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    if (StrUtil.isBlank(r.getErrcode())) {
                        r.setErrcode("0");
                    }
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 发起HTTP GET同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramMap GET请求所带参数Map,即URL地址问号后面所带的键值对,很蛋疼的实现方式,后续得改进,还没什么好的方案
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void get(String url, Map<String, String> paramMap, ResponseCallback callback) {
        String paramData = null;
        if (null != paramMap && !paramMap.isEmpty()) {
            StringBuilder buffer = new StringBuilder();
            //根据传进来的参数拼url后缀- -!
            for (Map.Entry<String, String> param : paramMap.entrySet()) {
                buffer.append(param.getKey()).append("=").append(param.getValue()).append("&");
            }
            //去掉最后一个&符号
            paramData = buffer.substring(0, buffer.length() - 1);
        }
        doRequest(MyNetWorkCenter.RequestMethod.GET, url, paramData, null, callback);
    }

    public static BaseResponse get(String url) {
        final BaseResponse[] response = new BaseResponse[]{null};
        doRequest(MyNetWorkCenter.RequestMethod.GET, url, null, null, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    if (StrUtil.isBlank(r.getErrcode())) {
                        r.setErrcode("0");
                    }
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 处理HTTP请求 基于org.apache.http.client包做了简单的二次封装
     *
     * @param method HTTP请求类型
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    private static void doRequest(final RequestMethod method, final String url,
            final String paramData, final List<File> fileList, final ResponseCallback callback) {
        //如果url没有传入,则直接返回
        if (null == url || url.isEmpty()) {
            LOG.warn("The url is null or empty!!You must give it to me!OK?");
            return;
        }
        String ishttp = url.toLowerCase();
        if (ishttp.startsWith("https") || ishttp.startsWith("HTTPS")) {
            doRequestSSH(method, url, paramData, fileList, callback);
            return;
        }
        //默认期望调用者传入callback函数
        boolean haveCallback = true;
        /*
         * 支持不传回调函数,只输出一个警告,并改变haveCallback标识
		 * 用于一些不需要后续处理的请求,比如只是发送一个心跳包等等
         */
        if (null == callback) {
            LOG.warn("--------------no callback block!--------------");
            haveCallback = false;
        }

        LOG.debug("-----------------请求地址:{}-----------------", url);
        //配置请求参数
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(CONNECT_TIMEOUT).build();
        CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpUriRequest request = null;
        switch (method) {
            case GET:
                String getUrl = url;
                if (null != paramData) {
                    getUrl += "?" + paramData;
                }
                request = new HttpGet(getUrl);
                break;
            case POST:
                LOG.debug("请求入参:");
                LOG.debug(paramData);
                request = new HttpPost(url);
                //上传文件
                if (null != fileList && !fileList.isEmpty()) {
                    LOG.debug("上传文件...");
                    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
                    for (File file : fileList) {
                        //只能上传文件哦 ^_^
                        if (file.isFile()) {
                            FileBody fb = new FileBody(file);
                            builder.addPart("media", fb);
                        } else {//如果上传内容有不是文件的,则不发起本次请求
                            LOG.warn("The target '{}' not a file,please check and try again!", file.getPath());
                            return;
                        }
                    }
                    if (null != paramData) {
                        builder.addPart("description", new StringBody(paramData, ContentType.APPLICATION_JSON));
                    }
                    ((HttpPost) request).setEntity(builder.build());
                } else//不上传文件的普通请求
                {
                    if (null != paramData) {
                        // 目前支持JSON格式的数据
                        StringEntity jsonEntity = new StringEntity(paramData, ContentType.APPLICATION_JSON);
                        ((HttpPost) request).setEntity(jsonEntity);
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                LOG.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }
        CloseableHttpResponse response = null;
        try {
            long start = System.currentTimeMillis();
            //发起请求
            response = client.execute(request);
            long time = System.currentTimeMillis() - start;
            LOG.debug("本次请求'{}'耗时:{}ms", url.substring(url.lastIndexOf("/") + 1, url.length()), time);
            int resultCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            //此流不是操作系统资源,不用关闭,ByteArrayOutputStream源码里close也是个空方法-0_0-
//            OutputStream os = new ByteArrayOutputStream();
//            entity.writeTo(os);
//            String resultJson = os.toString();
            String resultJson = EntityUtils.toString(entity, UTF_8);
            //返回码200,请求成功;其他情况都为请求出现错误
            if (HttpStatus.SC_OK == resultCode) {
                LOG.debug("-----------------请求成功-----------------");
                LOG.debug("响应结果:");
                LOG.debug(resultJson);
                if (haveCallback) {
                    callback.onResponse(resultCode, resultJson);
                }
            } else if (haveCallback) {
                LOG.warn("-----------------请求出现错误,错误码:{}-----------------", resultCode);
                callback.onResponse(resultCode, resultJson);
            }
        } catch (ClientProtocolException e) {
            LOG.error("ClientProtocolException:", e);
            LOG.warn("-----------------请求出现异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } catch (IOException e) {
            LOG.error("IOException:", e);
            LOG.warn("-----------------请求出现IO异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } catch (Exception e) {
            LOG.error("Exception:", e);
            LOG.warn("-----------------请求出现其他异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }
    }

}
时间: 2024-08-05 02:15:27

【fastweixin框架教程3】JAVA进行HTTPS网站访问,PKIX path building failed解决方法的相关文章

Java生成证书工具类 InstallCert.java解决httpClient访问https出错:PKIX path building failed

编译:javac InstallCert.java运行:java InstallCert 要访问的网址 最后面会输出: Enter certificate to add to trusted keystore or 'q' to quit: [1] 输入1,然后直接回车,会在相应的目录下产生一个名为'jssecacerts'的证书.将证书copy到$JAVA_HOME/jre/lib/security目录下 InstallCert.java /* * Copyright 2006 Sun Mic

Windows Server 2008 网站访问PHP响应慢的解决方法

公司新上了一个网站,但是在配置完PHP环境之后却发现了问题,访问HTML速度飞快,而访问PHP网页时就要卡顿1秒,响应很慢的样子,排除了带宽的因素之后,在百度上搜了一圈竟然解决了,现在将方法转载给大家,其实解决方法很简单哦. IIS7.5网站访问PHP响应慢的原因 原因是PHP5.3以上支持IPv6协议,但是大家的服务器未使用IPv6,我们配置数据库信息时都类似这样的“$dbhost=‘localhost' ”,这本身是没有问题的,只是当访问PHP的时候会连接MySQL的地址为localhost

HTTPS连接时出现PKIX path building failed问题

第一种方法:进行安全证书的下载及导入-----------传统办法,优点是安全性高,缺点是网站若更换证书,还得重新下载和导入,不够灵活 sudo keytool -import -noprompt -trustcacerts -alias CTSite -file /Users/zhanghao/Desktop/sslvpn.cer -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre/lib

https开头的URL接口无法获取数据并报错: PKIX path building failed

大概介绍:php语言写的接口,通过get或post方式获取里面的数据.但是是以https开头的URL 原因:https网址向客户的要证书 解决方案:跳过证书验证部分 package com.scheduler; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import java.io.BufferedReader;

https网站访问第三方https网站时候报错: The request was aborted:Could not create SSL/TLS secure channel.

https网站访问第三方https网站时候报错: The request was aborted:Could not create SSL/TLS secure channel. 解决办法: if(Url.StartsWith("https",StringComparison.OrdinalIgnoreCase))//https请求 { ServicePointManager.Expect100Continue = true; //如果是4.5以上版本可以直接使用 //ServiceP

java compiler 与 facet doesn&#39;t match 错误的解决方法

java compiler 与 facet doesn't match 错误的解决方法 原文地址:https://www.cnblogs.com/CrisZjie180228/p/9319772.html

mac下https方式连接svn连接不上解决方法

以前一个人开发没有考虑代码服务器的问题,现在需要提交代码到服务器,服务器安装了cvs以及svn,一般的Mac OS X都已经安装了subversion客户端,自然是选择svn了,不过碰到了连接不上的问题. 由于客户端使用https访问服务器,是需要进行安全认证的. 为此,在终端输入 svn list  https://192.168.1.103/svn/IOS 出现 Error validating server certificate for 'https://192.168.2.126:44

java中两double相加精度丢失问题及解决方法

在讨论两位double数0.1和0.2相加时,毫无疑问他们相加的结果是0.2.但是问题总是如此吗? 下面我们让下面两个doubles数相加,然后看看输出结果: @Test public void testBig(){ System.out.println(0.11+2001299.32); } 控制台输出2001299.4300000002 我们吃惊的发现,结果并不是我们预想的那样,这是为什么呢?又如何解决呢? 现贴出BigDecimal的一个构造函数的文档供大家参考 BigDecimal pu

从根本分析网站降权的原因与解决方法

网站降权了该怎么办?这个是做seo优化人员的经常面临与遇到的问题,不知道该从何分析与着手,下面小编就带着大家来分析原因并解决网站降权:        网站优化从两方面着手,站内优化与站外优化,首先我们先从站内优化开始分析: 1.锚文本过分 许多站长喜好做锚文本和全站毗邻,每更新一篇文章,见关键词就做锚文本,见主页关键词就做全站毗邻,至使蜘蛛在抓取日志的时分,有区分优化过速,刻意搜刮引擎优化的猜忌,被罚降权. 解决方法: 淘汰锚文本的数目,通常1000字的文章,放10个没关系.尚有,放关键词超毗邻