App的Token

App的Token_第1张图片
无标题.png
package com.jh.jtestone.net;

import android.text.TextUtils;

import com.jh.jtestone.callback.IGlobalManager;
import com.jh.jtestone.net.exception.TokenInvalidException;
import com.jh.jtestone.net.exception.TokenNotExistException;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;

/**
 * Created by 暗号 on 2017/9/3.
 */

public class ProxyHandler implements InvocationHandler{

    private final static String TAG = "Token_Proxy";

    private final static String TOKEN = "token";

    private final static int REFRESH_TOKEN_VALID_TIME = 30;
    private static long tokenChangedTime = 0;
    private Throwable mRefreshTokenError = null;
    private boolean mIsTokenNeedRefresh;


    private Object mProxyObject;
    private IGlobalManager iGlobalManager;

    public ProxyHandler(Object mProxyObject, IGlobalManager iGlobalManager) {
        this.mProxyObject = mProxyObject;
        this.iGlobalManager = iGlobalManager;
    }

    @Override
    public Object invoke(Object o, final Method method,final Object[] objects) throws Throwable {
        return Observable.just(null).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Object o) throws Exception {
                try {
                    if(mIsTokenNeedRefresh){
                        updateMethodToken(method,objects);
                    }
                    return (Observable) method.invoke(mProxyObject,objects);
                } catch (InvocationTargetException  e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }).retryWhen(new Function, ObservableSource>() {
            @Override
            public ObservableSource apply(@NonNull Observable throwableObservable) throws Exception {
                return throwableObservable.flatMap(new Function>() {
                    @Override
                    public ObservableSource apply(@NonNull Throwable throwable) throws Exception {
                        if(throwable instanceof TokenInvalidException){
                            return refreshTokenWhenTokenInvalid();
                        }else if(throwable instanceof TokenNotExistException){
                            // Token 不存在,执行退出登录的操作。(为了防止多个请求,都出现 Token 不存在的问题,
                            // 这里需要取消当前所有的网络请求)
                            iGlobalManager.exitLogin();
                            return Observable.error(throwable);
                        }
                        return Observable.error(throwable);
                    }
                });
            }
        });
    }

    /**
     * Refresh the token when the current token is invalid.
     *
     * @return Observable
     */
    private Observable refreshTokenWhenTokenInvalid() {
        synchronized (ProxyHandler.class) {
            // Have refreshed the token successfully in the valid time.
            if (new Date().getTime() - tokenChangedTime < REFRESH_TOKEN_VALID_TIME) {
                mIsTokenNeedRefresh = true;
                return Observable.just(true);
            } else {
                // call the refresh token api.
                RetrofitUtil.getInstance().get(IApiService.class).refreshToken().subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        mRefreshTokenError = e;
                    }

                    @Override
                    public void onNext(TokenModel model) {
                        if (model != null) {
                            mIsTokenNeedRefresh = true;
                            tokenChangedTime = new Date().getTime();
                            GlobalToken.updateToken(model.token);
                            Log.d(TAG, "Refresh token success, time = " + tokenChangedTime);
                        }
                    }
                });
                if (mRefreshTokenError != null) {
                    return Observable.error(mRefreshTokenError);
                } else {
                    return Observable.just(true);
                }
            }
        }
    }


    /**
     * Update the token of the args in the method.
     *
     * PS: 因为这里使用的是 GET 请求,所以这里就需要对 Query 的参数名称为 token 的方法。
     * 若是 POST 请求,或者使用 Body ,自行替换。因为 参数数组已经知道,进行遍历找到相应的值,进行替换即可(更新为新的 token 值)。
     */
    private void updateMethodToken(Method method, Object[] args) {
        if (mIsTokenNeedRefresh && !TextUtils.isEmpty(GlobalToken.getToken())) {
            Annotation[][] annotationsArray = method.getParameterAnnotations();
            Annotation[] annotations;
            if (annotationsArray != null && annotationsArray.length > 0) {
                for (int i = 0; i < annotationsArray.length; i++) {
                    annotations = annotationsArray[i];
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof Query) {
                            if (TOKEN.equals(((Query) annotation).value())) {
                                args[i] = GlobalToken.getToken();
                            }
                        }
                    }
                }
            }
            mIsTokenNeedRefresh = false;
        }
    }
}

你可能感兴趣的:(App的Token)