Skip to content

拦截器的使用

xuexiangjys edited this page Mar 16, 2019 · 2 revisions

日志拦截器

(1)框架默认提供一个实现好的日志拦截器HttpLoggingInterceptor,通过XHttpSDK.debug("XHttp");就可以设置进去,它有5种打印模式

  • NONE: 不打印log

  • BASIC: 只打印"请求首行"和"响应首行"。

  • HEADERS: 打印请求和响应的所有 Header

  • PARAM: 只打印请求和响应参数

  • BODY: 打印所有数据(默认是这种)

(2)如果需要对网络请求的相关参数进行自定义记录的话,可以继承HttpLoggingInterceptor实现一个自己的网络请求日志拦截器,重写logForRequestlogForResponse两个方法即可。

(3)设置自定义的日志拦截器.

XHttpSDK.debug(new CustomLoggingInterceptor());

动态参数添加拦截器

有时候,我们需要对所有请求添加一些固定的请求参数,但是这些参数的值又是变化的,这个时候我们就需要动态添加请求参数【例如,请求的token、时间戳以及签名等】

(1)继承BaseDynamicInterceptor,实现updateDynamicParams方法,如下:

@Override
protected TreeMap<String, Object> updateDynamicParams(TreeMap<String, Object> dynamicMap) {
    if (isAccessToken()) {//是否添加token
        dynamicMap.put("token", TokenManager.getInstance().getToken());
    }
    if (isSign()) {//是否添加签名
        dynamicMap.put("sign", TokenManager.getInstance().getSign());
    }
    if (isTimeStamp()) {//是否添加请求时间戳
        dynamicMap.put("timeStamp", DateUtils.getNowMills());
    }
    return dynamicMap;//dynamicMap:是原有的全局参数+局部参数+新增的动态参数
}

(2)设置动态参数添加拦截器。

XHttpSDK.addInterceptor(new CustomDynamicInterceptor()); //设置动态参数添加拦截器

失效请求校验拦截器

当服务端返回一些独特的错误码(一般是token校验错误、失效,请求过于频繁等),需要我们进行全局性的拦截捕获,并作出相应的响应时,我们就需要定义一个特殊的拦截器求处理这些请求。

(1)继承BaseExpiredInterceptor,实现isResponseExpiredresponseExpired方法,如下:

/**
 * 判断是否是失效的响应
 *
 * @param oldResponse
 * @param bodyString
 * @return {@code true} : 失效 <br>  {@code false} : 有效
 */
@Override
protected ExpiredInfo isResponseExpired(Response oldResponse, String bodyString) {
    int code = JSONUtils.getInt(bodyString, ApiResult.CODE, 0);
    ExpiredInfo expiredInfo = new ExpiredInfo(code);
    switch (code) {
        case TOKEN_INVALID:
        case TOKEN_MISSING:
            expiredInfo.setExpiredType(KEY_TOKEN_EXPIRED)
                    .setBodyString(bodyString);
            break;
        case AUTH_ERROR:
            expiredInfo.setExpiredType(KEY_UNREGISTERED_USER)
                    .setBodyString(bodyString);
            break;
        default:
            break;
    }
    return expiredInfo;
}

/**
 * 失效响应的处理
 *
 * @return 获取新的有效请求响应
 */
@Override
protected Response responseExpired(Response oldResponse, Chain chain, ExpiredInfo expiredInfo) {
    switch(expiredInfo.getExpiredType()) {
        case KEY_TOKEN_EXPIRED:
            User user = TokenManager.getInstance().getLoginUser();
            if (user != null) {
                final boolean[] isGetNewToken = {false};
                HttpLog.e("正在重新获取token...");
                XHttpProxy.proxy(TestApi.IAuthorization.class, ThreadType.IN_THREAD)
                        .login(user.getLoginName(), user.getPassword())
                        .subscribeWith(new NoTipRequestSubscriber<LoginInfo>() {
                            @Override
                            protected void onSuccess(LoginInfo loginInfo) {
                                TokenManager.getInstance()
                                        .setToken(loginInfo.getToken())
                                        .setLoginUser(loginInfo.getUser());
                                isGetNewToken[0] = true;
                                HttpLog.e("重新获取token成功:" + loginInfo.getToken());
                            }
                        });
                if (isGetNewToken[0]) {
                    try {
                        HttpLog.e("使用新的token重新进行请求...");
                        return chain.proceed(HttpUtils.updateUrlParams(chain.request(), "token", TokenManager.getInstance().getToken()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                XRouter.getInstance().build("/xhttp/login").navigation();
                return HttpUtils.getErrorResponse(oldResponse, expiredInfo.getCode(), "请先进行登录!");
            }
            break;
        case KEY_UNREGISTERED_USER:
            return HttpUtils.getErrorResponse(oldResponse, expiredInfo.getCode(), "非法用户登录!");
        default:
            break;
    }
    return null;
}

(2)设置失效请求校验拦截器。

XHttpSDK.addInterceptor(new CustomExpiredInterceptor()); //请求失效校验拦截器

拦截器使用注意点

由于拦截器可能设置有多个,且无法设置优先级,因此添加拦截器的顺序就是其执行的顺序。这里需要注意哪些只拦截请求或者响应的拦截器的添加顺序及其执行顺序。

请求拦截器尽量优先于响应拦截器添加

1.在同时使用动态参数添加拦截器和失效请求校验拦截器时

错误的设置方式:

XHttpSDK.addInterceptor(new CustomExpiredInterceptor()); //请求失效校验拦截器
XHttpSDK.addInterceptor(new CustomDynamicInterceptor()); //设置动态参数添加拦截器

由于动态参数添加拦截器拦截的是请求,而失效请求校验拦截器拦截的是响应。如果失效请求校验拦截器先于动态参数添加拦截器添加(先执行),当请求失效的使用,失效请求校验拦截器会优先执行,判断失效后可能会重新进行请求以刷新本地状态,然后重新进行请求,这个时候动态参数添加拦截器拦截又被执行,又将上一次的失效的参数又重新设置进去,导致请求无法正常进行。

正确的设置方式:

XHttpSDK.addInterceptor(new CustomDynamicInterceptor()); //设置动态参数添加拦截器
XHttpSDK.addInterceptor(new CustomExpiredInterceptor()); //请求失效校验拦截器