Android OkHttp Retrofit Token过期重新请求接口

遇到问题:

请求接口时遇到token过期重新获取token之后,不会再次请求当前接口。

解决办法:

在 OkHttpManager 这个类 里面 直接把 30001 和30002 拦截 重新获取接口 在重新请求一遍方法 虽然是这么简单,但是走了好多弯路,所以几下笔记,避免更多小伙伴踩坑

参考:

http://www.jianshu.com/p/8d1ee61bc2d2

遇到的坑

报java.lang.IllegalStateException: closed,java.lang.IllegalStateException: closed,原因为OkHttp请求回调中response.body().string()只能有效调用一次

解决办法

     @Override
    public Response intercept(Chain chain) throws IOException
    {
        Request request = chain.request();
        logForRequest(request);
        Response response = chain.proceed(request);
       MediaType mediaType = response.body().contentType();
        String content= response.body().string();
        Log.e("tag", content);
        return response.newBuilder()
                .body(ResponseBody.create(mediaType, string))
                .build();
      // return logForResponse(response);

贴出代码部分


public class OkHttpManager {

    private static OkHttpClient mOkHttpClient;
    public static OkHttpClient getInstance() {
        if (mOkHttpClient == null) {
            synchronized (OkHttpManager.class) {
                if (mOkHttpClient == null) {

//                    //设置 请求的缓存
//                    File cacheFile = new File(IeouApplication.getInstance().getCacheDir(), "cache");
//                    Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //50Mb

                    mOkHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                            .readTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
 //                           .addInterceptor(mIntercepter)
                            .addInterceptor(new TokenInterceptor())
                            .addInterceptor(new OKHTTPLogInterceptor())
                            .addNetworkInterceptor(new HttpCacheInterceptor())
//                            .cache(cache)
                            .build();
                }
            }
        }
        return mOkHttpClient;
    }

    /**
     * 通用的请求头
     */
    private static HashMap addHeader() {
        HashMap header = new HashMap<>();
        header.put(Constants.HEADER_Client, PsUtils.getString(IeouApplication.getInstance(), "accessToken") == null ? Constants.FROM_ANDROID :
                PsUtils.getString(IeouApplication.getInstance(), "accessToken"));
        header.put("account_type", "CUSTOMER");
        return header;
    }

    /**
     * 拦截器 给所有的请求添加消息头
     */
    private static Interceptor mIntercepter = chain -> {

        Request.Builder builder = chain.request().newBuilder();

        HashMap header = addHeader();

        if (header != null) {
            for (HashMap.Entry entry : header.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        return chain.proceed(builder.build());
    };

  /**
     * 重新获取token
     */
    private static class TokenInterceptor implements Interceptor {

        private Handler mHandler = new Handler();
        private String resultStr;

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request().newBuilder()
                    .header("access_token", PsUtils.getString(IeouApplication.getInstance(), "accessToken") == null ? Constants.FROM_ANDROID :
                            PsUtils.getString(IeouApplication.getInstance(), "accessToken"))
                    .header("account_type", "CUSTOMER")
                    .build();
            ;
            Response response = chain.proceed(request);
//            HashMap header = addHeader();
//            if (header != null) {
//                for (HashMap.Entry entry : header.entrySet()) {
//                    request.newBuilder().addHeader(entry.getKey(), entry.getValue());
//                }
//            }
            MediaType mediaType = response.body().contentType();


            if (isTokenExpired(response)) {
                //同步请求方式,获取最新的Token
                Log.e("OkHttpManager", "静默自动刷新Token,然后重新请求数据");
                //同步请求方式,获取最新的Token
                String newSession = getNewToken();
                //使用新的Token,创建新的请求
                if (null != newSession && newSession.length() > 0) {
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("access_token", newSession)
                            .header("account_type", "CUSTOMER")
                            .build();
                    //重新请求上次的接口
                    return chain.proceed(newRequest.newBuilder().build());
                }

            }
            //如果token正常返回结果
            return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
        }
        /**
         * 根据Response,判断Token是否失效
         *
         * @param response
         * @return
         */
        private boolean isTokenExpired(Response response) {
            try {
                resultStr = response.body().string();
                RequestCode requestCode = new Gson().fromJson(resultStr, RequestCode.class);
                Log.e("OkHttpManager", requestCode.getResultCode() + "----requestCode");
                Log.e("OkHttpManager", resultStr + "----requestCode");
                if (requestCode.getResultCode() == 30001) {
                    Log.e("OkHttpManager", "----requestCode,Token登录过期了");
                    return true;
                }
                if (requestCode.getResultCode() == 30002) {
                    Log.e("OkHttpManager", "----requestCode,Token过期了");
                    return true;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            return false;
        }

        String getNewToken() {
//            Call bodyCall = HttpFactory.getHttpApi().getTasks(PsUtils.getString(IeouApplication.getInstance(), "refreshToken"));
//            retrofit2.Response response = bodyCall.execute();

          /**
             * 必须使用同步请求
             */
            String url = IeouUrl.baseUrl + "user/refreshToken?refreshToken=" + PsUtils.getString(IeouApplication.getInstance(), "refreshToken");
            Log.e("OkHttpManager", "重新请求---" + url);
            OkHttpClient client = new OkHttpClient();

            Request request = new Request.Builder().url(url).build();
            okhttp3.Call call = client.newCall(request);
            try {
                Response response = call.execute();
                TokenEntity data = new Gson().fromJson(response.body().string(), TokenEntity.class);
                Log.e("OkHttpManager", "重新请求---"+data.resultCode);
                if (data.resultCode == 0) {
                    if (null != data.data.accessToken && null != data.data.refreshToken) {
                        PsUtils.putString(IeouApplication.getInstance(), "accessToken", data.data.accessToken);
                        PsUtils.putString(IeouApplication.getInstance(), "refreshToken", data.data.refreshToken);
                        PsUtils.putString(IeouApplication.getInstance(), "upToken", data.data.upToken);
                        Log.e("OkHttpManager", data.data.accessToken);
                    }
                }else {
                    mHandler.post(() -> ToastUtils.showToast("登录已过期,请重新登录..."));
                    JPushInterface.deleteAlias(IeouApplication.getInstance(), 1);
                    AppManager.getInstance().finishAllActivity();
                    MyIntent(LoginActivity.class);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }


            return PsUtils.getString(IeouApplication.getInstance(), "accessToken");
        }

        /**
         * 跳转页面
         */
        public void MyIntent(Class clazz) {
            Intent intent = new Intent(IeouApplication.getInstance(), clazz);
            intent.putExtra("fromWhere", getClass().getSimpleName());
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            IeouApplication.getInstance().startActivity(intent);
        }

    }

    /**
     * log 拦截器
     */
    private static class OKHTTPLogInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = chain.proceed(chain.request());
            okhttp3.MediaType mediaType = response.body().contentType();
            String content = response.body().string();
//            Logger.e(mediaType.toString());
            Logger.e(request.toString());
            Logger.init("json");
            Logger.json(content);

            if (response.body() != null) {
                // 打印 body 后原 ResponseBody 会被清空,需要重新设置 body
                ResponseBody body = ResponseBody.create(mediaType, content);
                return response.newBuilder().body(body).build();
            } else {
                return response;
            }
        }
    }

    /**
     * 缓存拦截器
     */
    static class HttpCacheInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetUtils.isConnected(IeouApplication.getInstance())) {
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }

            Response originalResponse = chain.proceed(request);
            if (NetUtils.isConnected(IeouApplication.getInstance())) {
                // 有网的时候读接口上的 @Headers 里的配置,你可以在这里进行统一的设置
                String cacheControl = request.cacheControl().toString();
                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                        .removeHeader("Pragma")
                        .build();
            }
        }
    }
}

请求接口封装

public abstract class BaseSubCallback extends Subscriber {
    private static final String TAG = "BaseCallback";
    private static final int CODEOK = 0;
    private static final int INLOGINSOMEWHEREELSE = 30001;
    private static final int BEOVERDUE = 30002;
    private Context mContext;
    private AlertDialog mDialog;
    private CompositeSubscription compositeSubscription = new CompositeSubscription();

    public BaseSubCallback(Context mContext) {
        this.mContext = mContext;
    }

    protected abstract void onDone(int code, String object, String msg) throws IOException;

    /**
     * 显示进度条
     */
    @Override
    public void onStart() {
        if (!NetUtils.isConnected(mContext)) {
            ToastUtils.showToast("亲,你断网了啊!");
            // 一定要调用这个方法才会生效
            onCompleted();
            return;
        }
        showProgressDialog();
//        onCompleted();
    }

    /**
     * 关闭进度条
     */
    @Override
    public void onCompleted() {
        Log.d(TAG, "onCompleted----------------");
        hideProgressDialog();

    }

    /**
     * 网络请求发生错误的处理
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
        hideProgressDialog();
        if (!NetUtils.isConnected(mContext)) {
            ToastUtils.showToast("服务器连接失败,请检查网络设置!");
            return;
        }
        ToastUtils.showToast("服务器链接超时");

    }

    /**
     * @param
     */
    @Override
    public void onNext(T responseBody) {
        Log.d(TAG, "accessToken--" + PsUtils.getString(mContext, "accessToken"));
        ResponseBody body = (ResponseBody) responseBody;
        try {
            String result = new String(body.bytes());
            Log.d("BaseonNext---------", result);
            RequestCode requestCode = new Gson().fromJson(result, RequestCode.class);
            JSONObject jsonObject = new JSONObject(result);
            if (requestCode.getResultCode() == CODEOK) {

                onDone(requestCode.getResultCode(), jsonObject.getString("data"), requestCode.getMessage());
            }
//            else if (requestCode.getResultCode() == INLOGINSOMEWHEREELSE) {//30001
//                ToastUtils.showToast("登录已过期,请重新登录...");
//            }
//            else if (requestCode.getResultCode() == BEOVERDUE) {//30002
////                ToastUtils.showToast("登录已过期,请重新登录...");
//            }
            else {
                ToastUtils.showToast(requestCode.getMessage());
                Log.e("BaseonNext---------", jsonObject.getString("data"));
            }
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }


    }
}

你可能感兴趣的:(Android OkHttp Retrofit Token过期重新请求接口)