需求分析
当请求任意接口时, 返回需要获取Token
的错误时, 拿到token
并且重新请求接口.
源码
public class TokenInterceptor implements Interceptor {
private static final Charset UTF8 = Charset.forName("UTF-8");
Charset charset;
OnTokenListener tokenListener;
/**
* 重试次数
*/
int tryCount = 1;
StringBuilder responseBodyBuilder = new StringBuilder();
public TokenInterceptor(OnTokenListener tokenListener) {
this.tokenListener = tokenListener;
charset = UTF8;
}
public TokenInterceptor(int tryCount, Charset charset, OnTokenListener tokenListener) {
this.charset = charset;
this.tokenListener = tokenListener;
this.tryCount = tryCount;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request originRequest = chain.request();
if (tokenListener == null) {
return chain.proceed(originRequest);
}
//拿到正常接口请求的数据
Request tokenRequest = setToken(originRequest);
Response originResponse = chain.proceed(tokenRequest);
Response resultResponse = originResponse;
if (tokenListener != null) {
int index = 0;
while (index++ < tryCount) {
try {
Response oldResponse = resultResponse;
resultResponse = doIt(chain, originRequest, resultResponse);
if (oldResponse != resultResponse && tryCount > 1) {
//返回的结果不一样, 并且重试次数大于1
if (isTokenInvalid(resultResponse)) {
//再次判断返回结果是否是token失效
} else {
//token有效, 退出循环
break;
}
}
} catch (Exception e) {
resultResponse = originResponse;
break;
}
}
}
return resultResponse;
}
private String getResponseBodyString(Response response) throws IOException {
if (response == null) {
return "";
}
responseBodyBuilder.delete(0, responseBodyBuilder.length());
ResponseBody responseBody = response.body();
if (responseBody != null
&& responseBody.contentType() != null
&& responseBody.contentLength() > 0) {
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE);
Buffer buffer = source.buffer();
responseBodyBuilder.append(buffer.clone().readString(charset));
}
return responseBodyBuilder.toString();
}
/**
* 通过返回结果, 判断token是否过期
*/
private boolean isTokenInvalid(Response resultResponse) throws IOException {
return tokenListener != null &&
tokenListener.isTokenInvalid(resultResponse, getResponseBodyString(resultResponse));
}
/**
* 获取token, 并且重新请求接口
*/
private Response doIt(Chain chain, Request originRequest, Response resultResponse) throws IOException {
Response result = resultResponse;
//判断token是否过期
if (isTokenInvalid(resultResponse)) {
CountDownLatch countDownLatch = new CountDownLatch(1);
//Token失效
tokenListener.tryGetToken(countDownLatch);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//重新请求本次接口
Request tokenRequest = setToken(originRequest);
result = chain.proceed(tokenRequest);
}
return result;
}
/**
* 为这个请求, 设置token信息
**/
private Request setToken(Request request) {
Request result = request;
if (tokenListener != null) {
result = tokenListener.initToken(request);
}
return result;
}
public interface OnTokenListener {
/**
* 设置token
*/
Request initToken(@NonNull Request originRequest);
/**
* 根据接口返回值, 判断token是否失效
*
* @return true token失效
*/
boolean isTokenInvalid(@NonNull Response response, @NonNull String bodyString);
/**
* 重新获取token
* 获取token成功之后, 请调用 {@link CountDownLatch#countDown()}
*/
void tryGetToken(@NonNull CountDownLatch latch);
}
}
使用方式
//初始化对象
val tokenInterceptor = TokenInterceptor(object : TokenInterceptor.OnTokenListener {
//为请求设置token
override fun initToken(originRequest: Request): Request {
return originRequest.newBuilder()
.addHeader("token-header", "token value")
.build()
}
//判断接口返回值, 是否是token失效
override fun isTokenInvalid(response: Response, bodyString: String): Boolean {
val errorBean = bodyString.fromJson(ErrorBean::class.java)
return errorBean.code == 401
}
//重新获取token
override fun tryGetToken(latch: CountDownLatch) {
UserHelper.login { data, error ->
latch.countDown()
}
}
})
//添加拦截器
OkHttpClient.Builder()
.addInterceptor(tokenInterceptor)
群内有各(pian)种(ni)各(jin)样(qun)
的大佬,等你来撩.
联系作者
请使用QQ扫码加群, 小伙伴们都在等着你哦!
关注我的公众号, 每天都能一起玩耍哦!