package com.lonely.utils; import com.ztkj.common.log.interceptors.HttpLogInterceptor; import okhttp3.*; import org.apache.http.client.utils.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.*; import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @author lonely * @Date 2019/9/2 14:05 * @Description 基於okhttp的工具類 */ public class OkHttpUtil { private static final Logger logger = LoggerFactory.getLogger(OkHttpUtil.class); public final static int READ_TIMEOUT = 100; public final static int CONNECT_TIMEOUT = 60; public final static int WRITE_TIMEOUT = 60; public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static final String CONTENT_TYPE = "Content-Type"; private static final byte[] LOCKER = new byte[0]; private static OkHttpUtil mInstance; private OkHttpClient mOkHttpClient; private OkHttpUtil() { //todo 由於是靜態工具類,只會創建client一次,如果以后需要不同請求不同超時時間,不能這樣使用 okhttp3.OkHttpClient.Builder clientBuilder = new okhttp3.OkHttpClient.Builder(); //設置讀取超市時間 clientBuilder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS); //設置超時連接時間 clientBuilder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS); //設置寫入超時時間 clientBuilder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS); //支持HTTPS請求,跳過證書驗證 clientBuilder.sslSocketFactory(createSSLSocketFactory()); clientBuilder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); //添加攔截器 clientBuilder.addInterceptor(new HttpLogInterceptor()); mOkHttpClient = clientBuilder.build(); } /** * 單例模式獲取NetUtils * * @return */ public static OkHttpUtil getInstance() { if (mInstance == null) { synchronized (LOCKER) { if (mInstance == null) { mInstance = new OkHttpUtil(); } } } return mInstance; } /** * get請求,同步方式,獲取網絡數據,是在主線程中執行的,需要新起線程,將其放到子線程中執行 * * @param url * @return */ public Response getData(String url) { return getData(url, null); } /** * get請求,同步方式,獲取網絡數據,是在主線程中執行的,需要新起線程,將其放到子線程中執行 * * @param url * @return */ public Response getData(String url, Map<String, String> headerMap) { //1 構造Request Request.Builder builder = new Request.Builder().get().url(url); //Request request = builder.get().url(url).build(); //builder = builder.get().url(url); /*if (headerMap != null && headerMap.isEmpty()) { for (Map.Entry<String, String> headerEntry : headerMap.entrySet()) { builder.addHeader(headerEntry.getKey(), headerEntry.getValue()); } }*/ addHeaders(headerMap,builder); Request request = builder.build(); //2 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //3 執行Call,得到response Response response = null; try { response = call.execute(); } catch (IOException e) { e.printStackTrace(); } return response; } /** * post form表單 請求,同步方式,提交數據,是在主線程中執行的,需要新起線程,將其放到子線程中執行 * * @param url * @param bodyParams * @return */ /*public Response postFormData(String url, Map<String, String> bodyParams) { //1構造RequestBody RequestBody body = setRequestBody(bodyParams); //2 構造Request Request.Builder requestBuilder = new Request.Builder(); Request request = requestBuilder.post(body).addHeader(CONTENT_TYPE, HttpContentTypeEnum.FORM.contentTypeValue).url(url).build(); //3 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //4 執行Call,得到response Response response = null; try { response = call.execute(); } catch (IOException e) { e.printStackTrace(); } return response; }*/ /** * post方式 * * @param url 請求url * @param bodyParams requestbody * @param headerMap 請求頭信息 * @return * @throws IOException */ public Response postData(String url, Map<String, Object> bodyParams, Map<String, String> headerMap) throws Exception { //1構造RequestBody RequestBody body = setRequestBody(bodyParams, headerMap); //2 構造Request Request.Builder requestBuilder = new Request.Builder().post(body).url(url); //requestBuilder = requestBuilder.post(body).url(url); addHeaders(headerMap, requestBuilder); Request request = requestBuilder.build(); //Request request = requestBuilder.post(body).addHeader(CONTENT_TYPE, HttpContentTypeEnum.JSON.contentTypeValue).url(url).build(); //3 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //4 執行Call,得到response Response response = null; try { response = call.execute(); } catch (IOException e) { e.printStackTrace(); } return response; } /** * put請求方式 * * @param url * @param bodyParams * @return */ public Response putData(String url, Map<String, Object> bodyParams, Map<String, String> headerMap) throws Exception { //1構造RequestBody RequestBody body = setRequestBody(bodyParams, headerMap); //2 構造Request Request.Builder requestBuilder = new Request.Builder().put(body).url(url); addHeaders(headerMap, requestBuilder); Request request = requestBuilder.build(); //3 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //4 執行Call,得到response Response response = null; try { response = call.execute(); } catch (IOException e) { e.printStackTrace(); } return response; } /** * @param url * @param bodyParams * @return */ public Response delData(String url, Map<String, Object> bodyParams, Map<String, String> headerMap) throws Exception { //1構造RequestBody RequestBody body = setRequestBody(bodyParams, headerMap); //2 構造Request Request.Builder requestBuilder = new Request.Builder().delete(body).url(url); addHeaders(headerMap, requestBuilder); Request request = requestBuilder.build(); //3 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //4 執行Call,得到response Response response = null; try { response = call.execute(); } catch (IOException e) { e.printStackTrace(); } return response; } /** * post的請求參數,構造RequestBody * * @param bodyParams * @return */ private RequestBody setRequestBody(Map<String, Object> bodyParams, Map<String, String> headerMap) throws Exception { //判斷請求頭中是否存在 content-type字段 if (headerMap == null || !headerMap.containsKey(CONTENT_TYPE)) { throw new Exception("請求頭信息配置中無 Content-Type配置,請先配置"); } String contentType = headerMap.get(CONTENT_TYPE); if ("application/x-www-form-urlencoded".equals(contentType)) { //表單提交 就是key-value 都是字符串型 //轉換 Map<String, String> strBodyParamMap = new HashMap<>(); if (bodyParams != null && !bodyParams.isEmpty()) { bodyParams.forEach((key, value) -> { if (value != null) { strBodyParamMap.put(key, (String) value); } }); } return buildRequestBodyByMap(strBodyParamMap); } else { //json return buildRequestBodyByJson(com.alibaba.fastjson.JSON.toJSONString(bodyParams)); } } /** * 表單方式提交構建 * * @param bodyParams * @return */ private RequestBody buildRequestBodyByMap(Map<String, String> bodyParams) { RequestBody body = null; okhttp3.FormBody.Builder formEncodingBuilder = new okhttp3.FormBody.Builder(); if (bodyParams != null) { Iterator<String> iterator = bodyParams.keySet().iterator(); String key = ""; while (iterator.hasNext()) { key = iterator.next().toString(); formEncodingBuilder.add(key, bodyParams.get(key)); logger.info(" 請求參數:{},請求值:{} ", key, bodyParams.get(key)); } } body = formEncodingBuilder.build(); return body; } /** * json方式提交構建 * * @param jsonStr * @return */ private RequestBody buildRequestBodyByJson(String jsonStr) { return RequestBody.create(JSON, jsonStr); } /** * 生成安全套接字工廠,用於https請求的證書跳過 * * @return */ public SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory ssfFactory = null; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom()); ssfFactory = sc.getSocketFactory(); } catch (Exception e) { } return ssfFactory; } /** * 針對json post處理 * * @param url * @param json * @return * @throws IOException */ public String postJson(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = mOkHttpClient.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } public void postJsonAsyn(String url, String json, final MyNetCall myNetCall) throws IOException { RequestBody body = RequestBody.create(JSON, json); //2 構造Request Request.Builder requestBuilder = new Request.Builder(); Request request = requestBuilder.post(body).url(url).build(); //3 將Request封裝為Call Call call = mOkHttpClient.newCall(request); //4 執行Call call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { myNetCall.failed(call, e); } @Override public void onResponse(Call call, Response response) throws IOException { myNetCall.success(call, response); } }); } /** * 自定義網絡回調接口 */ public interface MyNetCall { void success(Call call, Response response) throws IOException; void failed(Call call, IOException e); } /** * 構建http get請求,將參數拼接到url后面 * * @param url * @param para * @return * @throws URISyntaxException * @throws MalformedURLException */ public static String buildHttpGet(String url, Map<String, Object> para) throws URISyntaxException, MalformedURLException { URIBuilder builder = new URIBuilder(url); Set<String> set = para.keySet(); for (String key : set) { builder.setParameter(key, String.valueOf(para.get(key))); } return builder.build().toURL().toString(); } /** * 添加header信息 * * @param headerMap * @param builder * @return */ private static Request.Builder addHeaders(Map<String, String> headerMap, Request.Builder builder) { if (headerMap != null && !headerMap.isEmpty()) { headerMap.forEach((key, value) -> builder.addHeader(key, value)); } return builder; } /** * 用於信任所有證書 */ class TrustAllCerts implements 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[0]; } } }