美文网首页网络图片
Retrofit实现cookie自动化管理

Retrofit实现cookie自动化管理

作者: 打酱油的日光灯 | 来源:发表于2018-10-12 09:20 被阅读84次

    打造终极MVP+Retrofit2+okhttp3+Rxjava2网络请求,开发实用,简约,由于篇幅字数原因 本章只讲cookie自动化管理实现

    抓住人生中的一分一秒,胜过虚度中的一月一年!

    前言

    目前最火的网络请求就是Retrofit+okhttp+Rxjava,于是我也加入了使用行列,在网上找了许多案例,实际代码开发中解决了一些所谓的坑,打造出一个使用简约的框架封装,mvp实现模式,实现逻辑如下。

    利用了以下技术点
    1.Retrofit2 Retrofit2官网
    2.okhttp3 okhttp3官网
    3.RxJava2 RxJava2官网
    4.MVP

    下面看下代码结构

    mmm.png
    1.导包
     //网络请求
        compile 'com.squareup.okhttp3:okhttp:3.9.1'
        compile 'com.squareup.retrofit2:retrofit:2.3.0'
        //ConverterFactory的Gson依赖包
        compile 'com.squareup.retrofit2:converter-gson:2.3.0'
        //CallAdapterFactory的Rx依赖包
        compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    
        compile 'io.reactivex.rxjava2:rxandroid:2.0.2'
    

    2.retrofit代码实现

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.lp.mvp_network.App;
    import com.lp.mvp_network.base.BaseContent;
    import com.lp.mvp_network.base.convert.MyGsonConverterFactory;
    import com.lp.mvp_network.base.cookie.CookieManger;
    import com.lp.mvp_network.base.gson.DoubleDefault0Adapter;
    import com.lp.mvp_network.base.gson.IntegerDefault0Adapter;
    import com.lp.mvp_network.base.gson.LongDefault0Adapter;
    import com.orhanobut.logger.Logger;
    
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    
    import okhttp3.Interceptor;
    import okhttp3.MediaType;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.Response;
    import okhttp3.ResponseBody;
    import retrofit2.Retrofit;
    import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
    import retrofit2.converter.gson.GsonConverterFactory;
    
    /**
     * File descripition:  创建Retrofit
     *
     * @author lp
     * @date 2018/6/19
     */
    
    public class ApiRetrofit {
        public final String BASE_SERVER_URL = BaseContent.baseUrl;
        private String TAG = "ApiRetrofit %s";
        private static ApiRetrofit apiRetrofit;
        private Retrofit retrofit;
        private ApiServer apiServer;
        private static Gson gson;
        private static final int DEFAULT_TIMEOUT = 15;
    
    
        public ApiRetrofit() {
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            httpClientBuilder
                    .cookieJar(new CookieManger(App.getContext())) //这块是添加的管理cookie方法
                    .addInterceptor(interceptor)//日志拦截
    //                .addInterceptor(new HeadUrlInterceptor())
                    .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true);//错误重联
    
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_SERVER_URL)
                    .addConverterFactory(GsonConverterFactory.create())//添加json转换框架
                    //支持RxJava2
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(httpClientBuilder.build())
                    .build();
            apiServer = retrofit.create(ApiServer.class);
        }
    
        public static ApiRetrofit getInstance() {
            if (apiRetrofit == null) {
                synchronized (Object.class) {
                    if (apiRetrofit == null) {
                        apiRetrofit = new ApiRetrofit();
                    }
                }
            }
            return apiRetrofit;
        }
    
        public ApiServer getApiService() {
            return apiServer;
        }
    
        /**
         * 请求访问quest
         * response拦截器  打印日志
         */
        private Interceptor interceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                long startTime = System.currentTimeMillis();
                Response response = chain.proceed(chain.request());
                long endTime = System.currentTimeMillis();
                long duration = endTime - startTime;
                MediaType mediaType = response.body().contentType();
                String content = response.body().string();
    
                Logger.wtf(TAG, "----------Request Start----------------");
                Logger.e(TAG, "| " + request.toString() + "===========" + request.headers().toString());
                Logger.json(content);
                Logger.e(content);
                Logger.wtf(TAG, "----------Request End:" + duration + "毫秒----------");
    
                return response.newBuilder()
                        .body(ResponseBody.create(mediaType, content))
                        .build();
            }
        };
    }
    

    3.新建ApiServer类,注释的都是请求案例

    public interface ApiServer {
        //示例    多种类型请求方式
    
    //    @POST("api/Activity/get_activities?")
    //    Observable<BaseModel<List<>>> getApi1(@Query("time") String requestType);
    
    //    @GET("api/Activity/get_activities?")
    //    Observable<BaseModel<List<>>> getApi1(@Query("time") String requestType);
    
    //    @FormUrlEncoded
    //    @POST("api/Activity/get_activities?")
    //    Observable<BaseModel<List<>>> getApi1(@Field("time") String requestType);
    
    //    @FormUrlEncoded
    //    @POST("api/Activity/get_activities?")
    //    Observable<BaseModel<List<>>> getApi1(@FieldMap HashMap<String, String> params);
    
    //    @Multipart
    //    @POST("api/Activity/get_activities?")
    //    Observable<BaseModel<List<>>> getApi1(@PartMap Map<String, RequestBody> map);
    
        @POST("api/Activity/get_activities?")
        Observable<BaseModel<List<MainBean>>> getMain(@Query("time") String requestType);
    }
    

    4.cookie自动化管理代码如下(以下内容复制粘贴即可使用)
    1.新建CookieManger类

    import android.content.Context;
    import android.text.TextUtils;
    import android.util.Log;
    
    
    import java.util.List;
    
    import okhttp3.Cookie;
    import okhttp3.CookieJar;
    import okhttp3.HttpUrl;
    
    /**
     * File descripition: cookie 处理
     *
     * @author lp
     * @date 2018/7/2
     */
    
    public class CookieManger implements CookieJar {
        private static Context mContext;
    
        private static PersistentCookieStore cookieStore;
    
        public CookieManger(Context context) {
            mContext = context;
            if (cookieStore == null) {
                cookieStore = new PersistentCookieStore(mContext);
            }
        }
    
        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            if (cookies != null && cookies.size() > 0) {
                for (Cookie item : cookies) {
                    cookieStore.add(url, item);
                    if (item.name() != null && !TextUtils.isEmpty(item.name()) &&
                            item.value() != null && !TextUtils.isEmpty(item.value())) {
                        /*保存cookie到sp地方  可能会用到 */
    //                    PrefUtils.setString(mContext, "cookie_name", item.name());
    //                    PrefUtils.setString(mContext, "cookie_value", item.value());
                    }
                }
            }
        }
    
        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            List<Cookie> cookies = cookieStore.get(url);
            for (int i = 0; i < cookies.size(); i++) {
                Log.e("", "拿出来的cookies name()==" + cookies.get(i).name());
                Log.e("", "拿出来的cookies value()==" + cookies.get(i).value());
            }
            return cookies;
        }
    
    }
    

    2.新建OkHttpCookies类(以下内容复制粘贴即可使用)

    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    import okhttp3.Cookie;
    
    /**
     * File descripition:   cookie 处理
     *
     * @author lp
     * @date 2018/7/2
     */
    
    public class OkHttpCookies  implements Serializable {
        private transient final Cookie cookies;
        private transient Cookie clientCookies;
    
        public OkHttpCookies(Cookie cookies) {
            this.cookies = cookies;
        }
    
        public Cookie getCookies() {
            Cookie bestCookies = cookies;
            if (clientCookies != null) {
                bestCookies = clientCookies;
            }
            return bestCookies;
        }
    
        private void writeObject(ObjectOutputStream out) throws IOException {
            out.writeObject(cookies.name());
            out.writeObject(cookies.value());
            out.writeLong(cookies.expiresAt());
            out.writeObject(cookies.domain());
            out.writeObject(cookies.path());
            out.writeBoolean(cookies.secure());
            out.writeBoolean(cookies.httpOnly());
            out.writeBoolean(cookies.hostOnly());
            out.writeBoolean(cookies.persistent());
        }
    
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            String name = (String) in.readObject();
            String value = (String) in.readObject();
            long expiresAt = in.readLong();
            String domain = (String) in.readObject();
            String path = (String) in.readObject();
            boolean secure = in.readBoolean();
            boolean httpOnly = in.readBoolean();
            boolean hostOnly = in.readBoolean();
            boolean persistent = in.readBoolean();
            Cookie.Builder builder = new Cookie.Builder();
            builder = builder.name(name);
            builder = builder.value(value);
            builder = builder.expiresAt(expiresAt);
            builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain);
            builder = builder.path(path);
            builder = secure ? builder.secure() : builder;
            builder = httpOnly ? builder.httpOnly() : builder;
            clientCookies =builder.build();
        }
    }
    

    3.新建PersistentCookieStore类(以下内容复制粘贴即可使用)

    import android.content.Context;
    import android.content.SharedPreferences;
    import android.text.TextUtils;
    import android.util.Log;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    import okhttp3.Cookie;
    import okhttp3.HttpUrl;
    
    /**
     * File descripition:   cookie 处理
     *
     * @author lp
     * @date 2018/7/2
     */
    
    public class PersistentCookieStore {
        private static final String LOG_TAG = "PersistentCookieStore";
        private static final String COOKIE_PREFS = "Cookies_Prefs";
    
        private final Map<String, ConcurrentHashMap<String, Cookie>> cookies;
        private final SharedPreferences cookiePrefs;
    
    
        public PersistentCookieStore(Context context) {
            cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);
            cookies = new HashMap<>();
    
            //将持久化的cookies缓存到内存中 即map cookies
            Map<String, ?> prefsMap = cookiePrefs.getAll();
            for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
                String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
                for (String name : cookieNames) {
                    String encodedCookie = cookiePrefs.getString(name, null);
                    if (encodedCookie != null) {
                        Cookie decodedCookie = decodeCookie(encodedCookie);
                        if (decodedCookie != null) {
                            if (!cookies.containsKey(entry.getKey())) {
                                cookies.put(entry.getKey(), new ConcurrentHashMap<String, Cookie>());
                            }
                            cookies.get(entry.getKey()).put(name, decodedCookie);
                        }
                    }
                }
            }
        }
    
        protected String getCookieToken(Cookie cookie) {
            return cookie.name() + "@" + cookie.domain();
        }
    
        public void add(HttpUrl url, Cookie cookie) {
            String name = getCookieToken(cookie);
    
            //将cookies缓存到内存中 如果缓存过期 就重置此cookie
            if (!cookie.persistent()) {
                if (!cookies.containsKey(url.host())) {
                    cookies.put(url.host(), new ConcurrentHashMap<String, Cookie>());
                }
                cookies.get(url.host()).put(name, cookie);
            } else {
                if (cookies.containsKey(url.host())) {
                    cookies.get(url.host()).remove(name);
                }
            }
    
            //讲cookies持久化到本地
            SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
            prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));
            prefsWriter.putString(name, encodeCookie(new OkHttpCookies(cookie)));
            prefsWriter.apply();
        }
    
        public List<Cookie> get(HttpUrl url) {
            ArrayList<Cookie> ret = new ArrayList<>();
            if (cookies.containsKey(url.host())) {
                ret.addAll(cookies.get(url.host()).values());
            }
            return ret;
        }
    
        public boolean removeAll() {
            SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
            prefsWriter.clear();
            prefsWriter.apply();
            cookies.clear();
            return true;
        }
    
        public boolean remove(HttpUrl url, Cookie cookie) {
            String name = getCookieToken(cookie);
    
            if (cookies.containsKey(url.host()) && cookies.get(url.host()).containsKey(name)) {
                cookies.get(url.host()).remove(name);
    
                SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
                if (cookiePrefs.contains(name)) {
                    prefsWriter.remove(name);
                }
                prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));
                prefsWriter.apply();
    
                return true;
            } else {
                return false;
            }
        }
    
        public List<Cookie> getCookies() {
            ArrayList<Cookie> ret = new ArrayList<>();
            for (String key : cookies.keySet()) {
                ret.addAll(cookies.get(key).values());
            }
    
            return ret;
        }
    
        /**
         * cookies 序列化成 string
         *
         * @param cookie 要序列化的cookie
         * @return 序列化之后的string
         */
        protected String encodeCookie(OkHttpCookies cookie) {
            if (cookie == null) {
                return null;
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            try {
                ObjectOutputStream outputStream = new ObjectOutputStream(os);
                outputStream.writeObject(cookie);
            } catch (IOException e) {
                Log.d(LOG_TAG, "IOException in encodeCookie", e);
                return null;
            }
    
            return byteArrayToHexString(os.toByteArray());
        }
    
        /**
         * 将字符串反序列化成cookies
         *
         * @param cookieString cookies string
         * @return cookie object
         */
        protected Cookie decodeCookie(String cookieString) {
            byte[] bytes = hexStringToByteArray(cookieString);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            Cookie cookie = null;
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
                cookie = ((OkHttpCookies) objectInputStream.readObject()).getCookies();
            } catch (IOException e) {
                Log.d(LOG_TAG, "IOException in decodeCookie", e);
            } catch (ClassNotFoundException e) {
                Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e);
            }
    
            return cookie;
        }
    
        /**
         * 二进制数组转十六进制字符串
         *
         * @param bytes byte array to be converted
         * @return string containing hex values
         */
        protected String byteArrayToHexString(byte[] bytes) {
            StringBuilder sb = new StringBuilder(bytes.length * 2);
            for (byte element : bytes) {
                int v = element & 0xff;
                if (v < 16) {
                    sb.append('0');
                }
                sb.append(Integer.toHexString(v));
            }
            return sb.toString().toUpperCase(Locale.US);
        }
    
        /**
         * 十六进制字符串转二进制数组
         *
         * @param hexString string of hex-encoded values
         * @return decoded byte array
         */
        protected byte[] hexStringToByteArray(String hexString) {
            int len = hexString.length();
            byte[] data = new byte[len / 2];
            for (int i = 0; i < len; i += 2) {
                data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
            }
            return data;
        }
    }
    

    至此 上边是实现cookie自动化管理所需代码
    本文章最终实现终极MVP+Retrofit2+okhttp3+Rxjava2网络请求,开发实用,简约,具体实现方式请查看下篇文章

    相关文章

      网友评论

        本文标题:Retrofit实现cookie自动化管理

        本文链接:https://www.haomeiwen.com/subject/dozbaftx.html