Retrofit封裝Okhttp3網(wǎng)絡(luò)請求客戶端

package com.major.com.api;

import android.util.Log;

import com.google.gson.Gson;

import com.google.gson.GsonBuilder;

import java.io.File;

import java.io.IOException;

import java.net.InetAddress;

import java.net.Socket;

import java.net.UnknownHostException;

import java.nio.charset.Charset;

import java.security.KeyManagementException;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSession;

import javax.net.ssl.SSLSocket;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

import okhttp3.ConnectionSpec;

import okhttp3.Interceptor;

import okhttp3.OkHttpClient;

import okhttp3.Request;

import okhttp3.Response;

import okhttp3.ResponseBody;

import okhttp3.TlsVersion;

import okio.Buffer;

import okio.BufferedSource;

import retrofit2.Retrofit;

import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import retrofit2.converter.gson.GsonConverterFactory;

/**

* Created by QuietLake on 2017/11/3.

*/

public class LocalClient {

? ? private static String BASE_URL= "";

? ? private static Retrofit retrofit= null;

? ? private static OkHttpClient okHttpClient= null;

? ? private static LocalClient localCilent= null;

? ? private LocalClient() {

}

? ? // 單例獲取

? ? public static LocalClient getInstance(){

? ? ? ? if (localCilent== null){

? ? ? ? ? ? synchronized (LocalClient.class){

? ? ? ? ? ? ? ? if (localCilent==null){

? ? ? ? ? ? ? ? ? ? localCilent= new LocalClient();

? ? ? ? ? ? ? ? }

}

}

? ? ? ? return localCilent;

? ? }

? ? /**

? ? * 重新設(shè)置baseUrl

? ? * @parambaseUrl 需要在調(diào)用create之前調(diào)用

? ? * @return當(dāng)前對象

? ? */

? ? public LocalClient setBaseUrl(String baseUrl) {

? ? ? ? if (baseUrl.endsWith(File.separator)) {

? ? ? ? ? ? BASE_URL= baseUrl;

? ? ? ? } else {

? ? ? ? ? ? BASE_URL= baseUrl + File.separator;

? ? ? ? }

? ? ? ? return localCilent;

? ? }

? ? //創(chuàng)建服務(wù)接口,不綁定生命周期

? ? public T create(Class cla){

? ? ? ? retrofit= getRetrofit();

? ? ? ? return retrofit.create(cla);

? ? }

? ? private static final int READ_TIMEOUT = 60;

? ? private static final int WRITE_TIMEOUT = 60;

? ? private static final int CONNECT_TIMEOUT = 20;

? ? //設(shè)置okhttpclient

? ? private OkHttpClient initOkHttpClient(){

? ? ? ? OkHttpClient.Builder builder= new OkHttpClient.Builder();

? ? ? ? builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);? ? ? //全局的讀取超時時間

? ? ? ? builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);? ? //全局的寫入超時時間

? ? ? ? builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);? //全局的連接超時時間

? ? ? ? OkSSLSocketFactory okSSLSocketFactory= null;

? ? ? ? try {

? ? ? ? ? ? okSSLSocketFactory= new OkSSLSocketFactory();

? ? ? ? } catch (KeyManagementException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (NoSuchAlgorithmException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? ? ? builder.followSslRedirects(true)

? ? ? ? ? ? ? ? .retryOnConnectionFailure(true);

? ? ? ? builder.sslSocketFactory(new Tls12SocketFactory(okSSLSocketFactory), okSSLSocketFactory.trustManager);

? ? ? ? //配置https的域名匹配規(guī)則,詳細看demo的初始化介紹雷则,不需要就不要加入,使用不當(dāng)會導(dǎo)致https握手失敗

? ? ? ? builder.hostnameVerifier(new SafeHostnameVerifier());

? ? ? ? ConnectionSpec cs= new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)

? ? ? ? ? ? ? ? .tlsVersions(TlsVersion.TLS_1_2)

? ? ? ? ? ? ? ? .build();

? ? ? ? List specList= new ArrayList<>();

? ? ? ? specList.add(cs);

? ? ? ? specList.add(ConnectionSpec.COMPATIBLE_TLS);

? ? ? ? specList.add(ConnectionSpec.CLEARTEXT);

? ? ? ? Interceptor loggingIntercept= new Interceptor() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public Response intercept(Interceptor.Chain chain) throws IOException {

? ? ? ? ? ? ? ? Request request= chain.request();

? ? ? ? ? ? ? ? Response response= chain.proceed(request);

? ? ? ? ? ? ? ? ResponseBody responseBody= response.body();

? ? ? ? ? ? ? ? BufferedSource source= responseBody.source();

? ? ? ? ? ? ? ? source.request(Long.MAX_VALUE); // Buffer the entire body.

? ? ? ? ? ? ? ? Buffer buffer= source.buffer();

? ? ? ? ? ? ? ? Charset UTF8= Charset.forName("UTF-8");

? ? ? ? ? ? ? ? Log.w("日志", "intercept: "+buffer.clone().readString(UTF8));

? ? ? ? ? ? ? ? Log.w("日志", "intercept: "+request.toString());

? ? ? ? ? ? ? ? return response;

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? builder.addInterceptor(loggingIntercept);

? ? ? ? OkHttpClient httpClient= builder.connectionSpecs(specList)

? ? ? ? ? ? ? ? .addInterceptor(new Interceptor() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public Response intercept(Chain chain) throws IOException {

? ? ? ? ? ? ? ? ? ? ? ? Request request= chain.request()//獲取請求

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .newBuilder()

//? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Encoding", "gzip") //header不支持中文裸影,不允許有特殊字符

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Language", "zh-CN,zh;q=0.8")

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3")

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .addHeader("Connection", "close")

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .build();

? ? ? ? ? ? ? ? ? ? ? ? Log.d("request",request.toString());

? ? ? ? ? ? ? ? ? ? ? ? return chain.proceed(request);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }).build();

? ? ? ? return httpClient;

? ? }

? ? //設(shè)置Retrofit,不帶生命周期綁定的

? ? private Retrofit getRetrofit(){

? ? ? ? if (retrofit== null){

? ? ? ? ? ? if (okHttpClient== null){

? ? ? ? ? ? ? ? okHttpClient= getOkHttpCilent();

? ? ? ? ? ? }

? ? ? ? ? ? Gson gson= new GsonBuilder()

? ? ? ? ? ? ? ? ? ? .setLenient()

? ? ? ? ? ? ? ? ? ? .create();

? ? ? ? ? ? retrofit= new Retrofit.Builder()

? ? ? ? ? ? ? ? ? ? .baseUrl(BASE_URL)

? ? ? ? ? ? ? ? ? ? .client(okHttpClient)

? ? ? ? ? ? ? ? ? ? .addConverterFactory(GsonConverterFactory.create(gson))//json轉(zhuǎn)換器支持

? ? ? ? ? ? ? ? ? ? .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

? ? ? ? ? ? ? ? ? ? .build();

? ? ? ? }

? ? ? ? return retrofit;

? ? }

? ? /**

? ? * 提供方法單獨獲取okhttpCilent

? ? * @returnokhttpCilent

*/

? ? public OkHttpClient getOkHttpCilent(){

? ? ? ? if(okHttpClient== null){

? ? ? ? ? ? okHttpClient= initOkHttpClient();

? ? ? ? }

? ? ? ? return okHttpClient;

? ? }

? ? // 主機校驗

? ? private class SafeHostnameVerifier implements HostnameVerifier {

? ? ? ? @Override

? ? ? ? public boolean verify(String hostname, SSLSession session) {

? ? ? ? ? ? //驗證主機名是否匹配

? ? ? ? ? ? return true;

? ? ? ? }

}

? ? // 信任證書

? ? private class OkSSLSocketFactory extends SSLSocketFactory {

? ? ? ? SSLContext sslContext= SSLContext.getInstance("TLSv1.2");

? ? ? ? public X509TrustManager trustManager;

? ? ? ? public OkSSLSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, IOException {

? ? ? ? ? ? super();

? ? ? ? ? ? // 使用預(yù)埋證書,校驗服務(wù)端證書(自簽名證書)

//? ? ? ? ? ? TrustManager[] trustManagers = prepareTrustManager(MtsApp.getCtx().getAssets().open("www.major.com.cer"));

//? ? ? ? ? ? trustManager = chooseTrustManager(trustManagers);

? ? ? ? ? ? // 信任所有證書

? ? ? ? ? ? trustManager= 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 new X509Certificate[0];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? };

? ? ? ? ? ? sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());

? ? ? ? }

? ? ? ? @Override

? ? ? ? public String[] getDefaultCipherSuites() {

? ? ? ? ? ? return new String[0];

? ? ? ? }

? ? ? ? @Override

? ? ? ? public String[] getSupportedCipherSuites() {

? ? ? ? ? ? return new String[0];

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {

? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(s, host, port, autoClose);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(String host, int port) throws IOException {

? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {

? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port, localHost, localPort);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(InetAddress host, int port) throws IOException {

? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {

? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(address, port, localAddress, localPort);

? ? ? ? }

}

? ? // 支持TLSv1.2 ON Android4.x設(shè)備的https請求

? ? public class Tls12SocketFactory extends SSLSocketFactory {

? ? ? ? private final String[] TLS_V12_ONLY= {"TLSv1.2"};

? ? ? ? final SSLSocketFactory delegate;

? ? ? ? public Tls12SocketFactory(SSLSocketFactory base) {

? ? ? ? ? ? this.delegate= base;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public String[] getDefaultCipherSuites() {

? ? ? ? ? ? return delegate.getDefaultCipherSuites();

? ? ? ? }

? ? ? ? @Override

? ? ? ? public String[] getSupportedCipherSuites() {

? ? ? ? ? ? return delegate.getSupportedCipherSuites();

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {

? ? ? ? ? ? return patch(delegate.createSocket(s, host, port, autoClose));

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(String host, int port) throws IOException, UnknownHostException {

? ? ? ? ? ? return patch(delegate.createSocket(host, port));

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {

? ? ? ? ? ? return patch(delegate.createSocket(host, port, localHost, localPort));

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(InetAddress host, int port) throws IOException {

? ? ? ? ? ? return patch(delegate.createSocket(host, port));

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {

? ? ? ? ? ? return patch(delegate.createSocket(address, port, localAddress, localPort));

? ? ? ? }

? ? ? ? private Socket patch(Socket s) {

? ? ? ? ? ? if (s instanceof SSLSocket) {

? ? ? ? ? ? ? ? ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY);

? ? ? ? ? ? }

? ? ? ? ? ? return s;

? ? ? ? }

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子耕腾,更是在濱河造成了極大的恐慌,老刑警劉巖杀糯,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異苍苞,居然都是意外死亡固翰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門羹呵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骂际,“玉大人,你說我怎么就攤上這事冈欢∏嘎粒” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵凑耻,是天一觀的道長太示。 經(jīng)常有香客問我,道長香浩,這世上最難降的妖魔是什么类缤? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮邻吭,結(jié)果婚禮上餐弱,老公的妹妹穿的比我還像新娘。我一直安慰自己囱晴,他們只是感情好膏蚓,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著畸写,像睡著了一般驮瞧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枯芬,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天剧董,我揣著相機與錄音幢尚,去河邊找鬼。 笑死翅楼,一個胖子當(dāng)著我的面吹牛尉剩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毅臊,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼理茎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了管嬉?” 一聲冷哼從身側(cè)響起皂林,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚯撩,沒想到半個月后础倍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡胎挎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年沟启,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片犹菇。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡德迹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出揭芍,到底是詐尸還是另有隱情胳搞,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布称杨,位于F島的核電站肌毅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏姑原。R本人自食惡果不足惜芽腾,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望页衙。 院中可真熱鬧摊滔,春花似錦、人聲如沸店乐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眨八。三九已至腺兴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間廉侧,已是汗流浹背页响。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工篓足, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闰蚕。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓栈拖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親没陡。 傳聞我的和親對象是個殘疾皇子涩哟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容