|
@@ -0,0 +1,499 @@
|
|
|
+package com.emato.common.utils.oms;
|
|
|
+
|
|
|
+import okhttp3.*;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import javax.net.ssl.*;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.security.KeyStore;
|
|
|
+import java.security.SecureRandom;
|
|
|
+import java.security.cert.CertificateException;
|
|
|
+import java.security.cert.CertificateFactory;
|
|
|
+import java.security.cert.X509Certificate;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author Scott Chen
|
|
|
+ * @date 2017/3/13
|
|
|
+ */
|
|
|
+public class OkHttpUtils {
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(OkHttpUtils.class);
|
|
|
+
|
|
|
+ public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=UTF-8");
|
|
|
+ public static final MediaType MEDIA_TYPE_XML = MediaType.parse("application/xml;charset=UTF-8");
|
|
|
+ public static final MediaType MEDIA_TYPE_TEXT_HTML = MediaType.parse("text/html;charset=UTF-8");
|
|
|
+ private static final MediaType MEDIA_TYPE_FORM= MediaType.parse("application/x-www-form-urlencoded");
|
|
|
+
|
|
|
+ private static final String SSL = "SSL";
|
|
|
+
|
|
|
+
|
|
|
+ public static final int CONNECT_TIME_OUT = 20;
|
|
|
+ public static final int READ_TIME = 30;
|
|
|
+ public static final int WRITE_TIME = 30;
|
|
|
+
|
|
|
+ private static final ThreadLocal<OkHttpClient> okHttpClientThreadLocal = new ThreadLocal<>();
|
|
|
+ private static final ThreadLocal<OkHttpClient> okHttpClientSslThreadLocal = new ThreadLocal<>();
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 禁止调用无参构造
|
|
|
+ */
|
|
|
+ private OkHttpUtils() {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认http
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpClient(){
|
|
|
+ return okHttpClient(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * https 和 http
|
|
|
+ * @param ssl 如果需要SSL认证https, ssl值为SSL, 如果ssl为空, 则为http
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpClient(String ssl){
|
|
|
+ return StringUtils.isNotBlank(ssl) && SSL.equals(ssl) ? okHttpInstanceSsl() : okHttpInstance();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * https 和 http
|
|
|
+ * 如果要信息所有证书,
|
|
|
+ * <code>ssl</code>必须为SSL,
|
|
|
+ * <code>ignoreHostnameVerifier</code>为true,
|
|
|
+ * <code>InputStream... certificates</code>为null
|
|
|
+ *
|
|
|
+ * @param ssl
|
|
|
+ * @param ignoreHostnameVerifier 是否忽略Hostname验证
|
|
|
+ * @param certificates 证书流
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpClient(String ssl, boolean ignoreHostnameVerifier, InputStream... certificates){
|
|
|
+ return StringUtils.isNotBlank(ssl) && SSL.equals(ssl)
|
|
|
+ ? okHttpInstanceSsl(ignoreHostnameVerifier, certificates)
|
|
|
+ : okHttpInstance();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OkHttpClient 实例
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpInstance() {
|
|
|
+ OkHttpClient client = okHttpClientThreadLocal.get();
|
|
|
+ if (client == null) {
|
|
|
+ synchronized (OkHttpUtils.class) {
|
|
|
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
|
|
+ builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(READ_TIME, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(WRITE_TIME, TimeUnit.SECONDS)
|
|
|
+ .retryOnConnectionFailure(true);
|
|
|
+ client = builder.build();
|
|
|
+ okHttpClientThreadLocal.set(client);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return client;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OkHttpClient ssl 实例
|
|
|
+ * 忽略Hostname验证, 并信息所有证书
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpInstanceSsl() {
|
|
|
+ return okHttpInstanceSsl(true, new InputStream[]{});
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OkHttpClient ssl 实例
|
|
|
+ * 如果要信息所有证书, <code>InputStream... certificates</code>为null
|
|
|
+ * @param ignoreHostnameVerifier 是否忽略Hostname验证
|
|
|
+ * @param certificates 证书流
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static OkHttpClient okHttpInstanceSsl(boolean ignoreHostnameVerifier, InputStream... certificates) {
|
|
|
+ OkHttpClient client = okHttpClientSslThreadLocal.get();
|
|
|
+ if (client == null) {
|
|
|
+ synchronized (OkHttpUtils.class) {
|
|
|
+ X509TrustManager[] trustManager = buildX509TrustManager(certificates);
|
|
|
+ SSLSocketFactory sslSocketFactory = buildSSLSocketFactory(trustManager);
|
|
|
+
|
|
|
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
|
|
+ builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(READ_TIME, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(WRITE_TIME, TimeUnit.SECONDS)
|
|
|
+ .retryOnConnectionFailure(true);
|
|
|
+
|
|
|
+ //是否忽略host验证
|
|
|
+ if (ignoreHostnameVerifier) {
|
|
|
+ builder.hostnameVerifier(getHostnameVerifier());
|
|
|
+ }
|
|
|
+ builder.sslSocketFactory(sslSocketFactory, trustManager[0])
|
|
|
+ .retryOnConnectionFailure(true);
|
|
|
+
|
|
|
+ client = builder.build();
|
|
|
+ okHttpClientSslThreadLocal.set(client);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return client;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //------------------------------ build RequestBody ------------------------------
|
|
|
+
|
|
|
+
|
|
|
+ public static RequestBody buildRequestBody(MediaType mediaType, String json) {
|
|
|
+ return RequestBody.create(mediaType,json );
|
|
|
+ }
|
|
|
+
|
|
|
+ public static RequestBody buildRequestBody(String key, Object value) {
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isBlank(key)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Map<String, Object> param = new HashMap<>();
|
|
|
+ param.put(key, value);
|
|
|
+ return buildRequestBody(param);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static RequestBody buildMapStringRequestBody(Map<String, String> params) {
|
|
|
+ FormBody.Builder builder = new FormBody.Builder();
|
|
|
+ Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
|
|
|
+ while (iterator.hasNext()) {
|
|
|
+ Map.Entry<String, String> entry = iterator.next();
|
|
|
+ builder.add(entry.getKey(), entry.getValue());
|
|
|
+ }
|
|
|
+ return builder.build();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造RequestBody
|
|
|
+ *
|
|
|
+ * @param params
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static RequestBody buildRequestBody(Map<String, Object> params) {
|
|
|
+ FormBody.Builder builder = new FormBody.Builder();
|
|
|
+ Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
|
|
|
+ while (iterator.hasNext()) {
|
|
|
+ Map.Entry<String, Object> entry = iterator.next();
|
|
|
+ builder.add(entry.getKey(), JacksonUtils.toJsonStr(entry.getValue()));
|
|
|
+ }
|
|
|
+ return builder.build();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //------------------------------ build Request ------------------------------
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 以字符串数据构建
|
|
|
+ * @param json
|
|
|
+ * @param url
|
|
|
+ * @param type
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Request buildRequest(String json, String url, String type) {
|
|
|
+ //默认JSON
|
|
|
+ MediaType mediaType = MEDIA_TYPE_JSON;
|
|
|
+
|
|
|
+ type = StringUtils.isBlank(type) ? "" : type;
|
|
|
+ json = StringUtils.isBlank(json) ? "" : json;
|
|
|
+
|
|
|
+ if (type.equalsIgnoreCase("text_html")) {
|
|
|
+ mediaType = MEDIA_TYPE_TEXT_HTML;
|
|
|
+ }else if (type.equalsIgnoreCase("form")) {
|
|
|
+ mediaType = MEDIA_TYPE_FORM;
|
|
|
+ }else if (type.equalsIgnoreCase("xml")) {
|
|
|
+ mediaType = MEDIA_TYPE_XML;
|
|
|
+ }
|
|
|
+
|
|
|
+ RequestBody body = buildRequestBody(mediaType, json);
|
|
|
+ return buildRequest(body, url);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static Request buildStringRequest(Map<String, String> param, String url) {
|
|
|
+ return buildRequest(buildMapStringRequestBody(param), url);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建Request
|
|
|
+ * @param param
|
|
|
+ * @param url
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Request buildRequest(Map<String, Object> param, String url) {
|
|
|
+ return buildRequest(buildRequestBody(param), url);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建Request
|
|
|
+ * @param key
|
|
|
+ * @param value
|
|
|
+ * @param url
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Request buildRequest(String key, Object value, String url) {
|
|
|
+ return buildRequest(buildRequestBody(key, value), url);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建Request
|
|
|
+ * @param body
|
|
|
+ * @param url
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Request buildRequest(RequestBody body, String url) {
|
|
|
+ return new Request.Builder()
|
|
|
+ .url(url)
|
|
|
+ .post(body)
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //------------------------------ post ------------------------------
|
|
|
+
|
|
|
+ public static String post(String json, String url, String type, String ssl) {
|
|
|
+ return post(buildRequest(json, url, type), ssl);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String post(String key, Object value, String url, String ssl) {
|
|
|
+ return post(buildRequest(key, value, url), ssl);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String postString(Map<String, String> param, String url, String ssl) {
|
|
|
+ return post(buildStringRequest(param, url), ssl);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String post(Map<String, Object> param, String url, String ssl) {
|
|
|
+ return post(buildRequest(param, url), ssl);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步访问,返回结果字符串
|
|
|
+ * 可能超时
|
|
|
+ *
|
|
|
+ * @param request
|
|
|
+ * @param ssl
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static String post(Request request, String ssl) {
|
|
|
+ String result = "";
|
|
|
+ try {
|
|
|
+ Response response = okHttpClient(ssl).newCall(request).execute();
|
|
|
+
|
|
|
+ if (response.isSuccessful()) {
|
|
|
+ result = response.body().string();
|
|
|
+ } else {
|
|
|
+ logger.error("okhttp3 post failed.");
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("okhttp3 post throw IOException, {}", e.getMessage());
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步访问,返回Response
|
|
|
+ * 可能超时
|
|
|
+ *
|
|
|
+ * @param request
|
|
|
+ * @param ssl
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static String postReturnResponse(Request request, String ssl) {
|
|
|
+ try {
|
|
|
+ return okHttpClient(ssl).newCall(request).execute().body().string();
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("okhttp3 post throw IOException, {}", e.getMessage());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 异步访问,回调结果
|
|
|
+ * @param request
|
|
|
+ * @param ssl
|
|
|
+ * @param responseCallback
|
|
|
+ */
|
|
|
+ public static void asyncPostCallback(Request request, String ssl, Callback responseCallback) {
|
|
|
+ okHttpClient(ssl).newCall(request).enqueue(responseCallback);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 异步访问,无结果返回
|
|
|
+ * @param request
|
|
|
+ * @param ssl
|
|
|
+ */
|
|
|
+ public static void asyncPost(Request request, String ssl) {
|
|
|
+ okHttpClient(ssl).newCall(request).enqueue(new Callback() {
|
|
|
+ @Override
|
|
|
+ public void onFailure(Call call, IOException e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onResponse(Call call, Response response) throws IOException {
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //------------------------------ ssl ------------------------------
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取主机验证 HostnameVerifier
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static HostnameVerifier getHostnameVerifier() {
|
|
|
+ return new HostnameVerifier() {
|
|
|
+ @Override
|
|
|
+ public boolean verify(String s, SSLSession sslSession) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 自定义证书
|
|
|
+ *
|
|
|
+ * @param certificates
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static KeyStore generateKeyStore(InputStream... certificates) {
|
|
|
+ try {
|
|
|
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
|
|
+
|
|
|
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
|
+ keyStore.load(null);
|
|
|
+
|
|
|
+ int index = 0;
|
|
|
+ if (certificates !=null && certificates.length > 0) {
|
|
|
+ for (InputStream certificate : certificates) {
|
|
|
+ String certificateAlias = Integer.toString(index++);
|
|
|
+ keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (certificate != null) {
|
|
|
+ certificate.close();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return keyStore;
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 证书管理
|
|
|
+ * 信任所有证书
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static X509TrustManager[] buildX509TrustManager(){
|
|
|
+ return buildX509TrustManager(new InputStream[]{});
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 证书管理
|
|
|
+ * 如果要信任所有证书,<code>InputStream... certificates</code>为null
|
|
|
+ * @param certificates 证书文件流
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static X509TrustManager[] buildX509TrustManager(InputStream... certificates) {
|
|
|
+ try {
|
|
|
+ if (certificates == null) {
|
|
|
+ // 信任所有证书
|
|
|
+ return new X509TrustManager[]{
|
|
|
+ new X509TrustManager() {
|
|
|
+ @Override
|
|
|
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public X509Certificate[] getAcceptedIssuers() {
|
|
|
+ return new X509Certificate[]{};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 信任自定义证书
|
|
|
+ KeyStore keyStore = generateKeyStore(certificates);
|
|
|
+
|
|
|
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
|
|
+ TrustManagerFactory.getDefaultAlgorithm());
|
|
|
+
|
|
|
+ trustManagerFactory.init(keyStore);
|
|
|
+
|
|
|
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
|
|
+ if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
|
|
+ throw new IllegalStateException("Unexpected default trust managers:"
|
|
|
+ + Arrays.toString(trustManagers));
|
|
|
+ }
|
|
|
+
|
|
|
+ return (X509TrustManager[]) trustManagers;
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private static SSLSocketFactory buildSSLSocketFactory() {
|
|
|
+ return buildSSLSocketFactory((InputStream)null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static SSLSocketFactory buildSSLSocketFactory(InputStream... certificates) {
|
|
|
+ try {
|
|
|
+ TrustManager[] trustManager = buildX509TrustManager(certificates);
|
|
|
+ return buildSSLSocketFactory(trustManager);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static SSLSocketFactory buildSSLSocketFactory(TrustManager[] trustManager) {
|
|
|
+ try {
|
|
|
+ if (trustManager == null) {
|
|
|
+ throw new IllegalStateException("TrustManager is null");
|
|
|
+ }
|
|
|
+
|
|
|
+ SSLContext sslContext = SSLContext.getInstance(SSL);
|
|
|
+ sslContext.init(null, trustManager, new SecureRandom());
|
|
|
+
|
|
|
+ return sslContext.getSocketFactory();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|