遇到问题:
请求接口时遇到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();
}
}
}