Retrofit+Rxjava+OKHttp3之Session過期處理

前言
在app實(shí)際請求服務(wù)器接口的過程中,經(jīng)常會(huì)遇到session過期的情況,這時(shí)候需要我們重新登錄刷新session。
期初實(shí)現(xiàn)的方案是,發(fā)現(xiàn)session過期需要登錄時(shí),直接跳轉(zhuǎn)到登錄界面,登陸后跳轉(zhuǎn)首頁。
但更合理的情形是一旦發(fā)現(xiàn)session過期,直接調(diào)用登錄接口刷新session,之后繼續(xù)原來的業(yè)務(wù),即在此請求原來的業(yè)務(wù)接口。
本文就將針對(duì)使用OKHttp3的底層網(wǎng)路框架的情形,說一下如何實(shí)現(xiàn)session過期的統(tǒng)一處理。
有興趣的同學(xué)可以加入學(xué)習(xí)小組QQ群: 193765960做進(jìn)一步的討論。

版權(quán)歸作者所有,轉(zhuǎn)發(fā)請注明出處:http://www.itdecent.cn/u/d43d948bef39

1. 總體方案:攔截器

1)在網(wǎng)絡(luò)請求的底層OKhttp層設(shè)置攔截器,攔截網(wǎng)絡(luò)請求和響應(yīng)數(shù)據(jù)。
2)分析響應(yīng)數(shù)據(jù),根據(jù)響應(yīng)的狀態(tài)判斷是否發(fā)生session過期。
3)如果沒有過期,則正常返回響應(yīng)數(shù)據(jù)。
4)如果發(fā)生session過期,則取消當(dāng)前響應(yīng)數(shù)據(jù),生成刷新session的請求(一般是登錄請求)。
5)如果session刷新成功,根據(jù)原來業(yè)務(wù)的請求數(shù)據(jù)從新發(fā)起請求。
6)如果session刷新失敗,則返回session過期的異常響應(yīng),在上層解析該響應(yīng)后跳轉(zhuǎn)登錄界面。
7)從登錄界面重新登陸后,跳轉(zhuǎn)到首頁。

2. 攔截器的實(shí)現(xiàn)

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class SessionKeyInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request old_request = chain.request();
        Response old_response = chain.proceed(old_request);
        //下面這行代碼注意下,不要使用Gson等工具對(duì)old_response.body等直接轉(zhuǎn)化,會(huì)出問題的。
        //RequestHelper: 工具類小伙伴們可以加群,單獨(dú)找我索要
        JSONObject obj = RequestHelper.response2Object(old_response);
        //如果session過期,則重新登錄獲取sessionkey
        if (obj != null && TextUtils.equals(obj .optString("error_code"), MyConfig.getSessionKeyErrorNumber())) {

            //上層注入的請求MyRequest 
            MyRequest loginp = LoginUtils.getRequest();
            if(null == loginp || loginp.size()==0){
                return old_response;
            }

            if(null == LoginUtil.getLoginApi()){
                return originalResponse;
            }

            Request login_request = RequestHelper.buildGetRequest(loginparam, LoginUtils.getLoginApi());
            Response login_response = chain.proceed(login_request);
            if (login_response.isSuccessful()) {
                JSONObject obj2 = RequestHelper.response2Object(login_response);
                if(obj2!= null && (TextUtils.equals(obj2.optString("error_code"), "http://api請求成功的狀態(tài)碼"))){
                    //登錄成功,執(zhí)行原始request
                    String sessionKey = "";
                    try {
                        sessionKey = obj2.getJSONObject("jsondata").getString("session_key");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    login_response.body().close();
                    Map<String, Object> param = RequestHelper.parseParams(old_request);
                    //更新old_request的session_key等可變參數(shù)
                    param.put("sessionKey",sessionKey);
                    MyRequest request = new MyRequest ();
                    request.put(param);
                    originalRequest = RequestHelper.handler(request, old_request);
                    originalResponse.body().close();
                    return chain.proceed(old_request);
                }
            }
        }
        return old_response;
    }

基于項(xiàng)目代碼安全的需要,對(duì)以上代碼做了處理,不過大體的思路都是可用的

3. 登錄請求的上層注入

為了更好地適用于不同的項(xiàng)目,和后期代碼的維護(hù),判斷session是否過期的判斷依據(jù)采用上層配置并注入的方式。
當(dāng)然,您也可以直接在Okhttp層寫死,開發(fā)難度會(huì)簡單很多,只是后期維護(hù)或者做項(xiàng)目移植時(shí)需要特別注意修改。
發(fā)起session刷新的接口請求參數(shù)也是同樣的處理。不再一一贅述。

4. 存在問題

長時(shí)間在后臺(tái)靜默APP,數(shù)據(jù)有可能會(huì)被gc掉,所以這種情況下,系統(tǒng)不會(huì)無縫的去成功刷新session并執(zhí)行目標(biāo)請求的業(yè)務(wù)邏輯,而是會(huì)直接啟動(dòng)登錄界面。
這個(gè)攔截器,僅僅針對(duì)了session過期的情況,其實(shí)功能邏輯具有通用性,可以考慮和業(yè)務(wù)解耦,通過注入的方式支持更多異常的無縫處理。

以上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容