您的位置:首页 > 理论基础 > 计算机网络

基于retrofit网络请求token过期的处理逻辑

2017-08-31 15:42 381 查看
手机调用接口,关键数据请求需要验证token,token设置按照一定周期就过期。验证token需要判断token是否过期,如果过期就需要后台调用登陆接口获取新的token,并且用新的token替换原来的token,在后台继续完成原来未完成的请求。

经过尝试,基本完成实现与优化。

一、首先贴出接口代码,采用SpringBoot编写的简单接口:

@RestController
public class UserController {
private static String newToken="ZTAwNjIyOGQtZmU1Zi00NmNiLWJjNTgtMTY1MmE4OTI4OTkwCHRISCHEN";

/**
* 获取用户信息,验证token
* @param body
* @return
*/
@PostMapping("/getUserInfo")
public String getUserInfo(@RequestBody NetRequest body) {
String token=body.protocol.token;
if (newToken.equals(token)){
return GsonUtils.toJson(new NetResult<>(0,"getUserInfo success",new UserModel("kalychen","man",45)));
}else {
return GsonUtils.toJson(new NetResult<>(999,"Token time out",""));
}
}

/**
* 登录,获得新的token
* @param body
* @return
*/
@PostMapping("/login")
public String login(@RequestBody NetRequest body) {
//此处省略对请求参数的验证
return GsonUtils.toJson(new NetResult<>(0,"give you a new token",newToken));
}

}


二、用Java做测试,用到的工具类

public class RequestUtils {

/**
* 替换RequestBody中NetRequest自定义协议内的Token
*
* @param body
* @param newToken
* @return
*/
public static RequestBody replaceToken(RequestBody body, String newToken) {
NetRequest requestBody = getRequestBody(body);
requestBody.protocol.token = newToken;
return RequestBody.create(body.contentType(), JsonUtils.objToJson(requestBody));
}

/**
* 获得NetRequest类型的requestBody,便于取出其中的协议信息
*
* @param body
* @return
*/
public static NetRequest getRequestBody(RequestBody body) {
return JsonUtils.jsonToObj(getRequestBodyJson(body), NetRequest.class);
}

/**
* 获得request中body的json字符串,便于打印
*
* @param body
* @return
* @throws IOException
*/
public static String getRequestBodyJson(RequestBody body) {
Buffer buffer = new Buffer();
try {
body.writeTo(buffer);
Charset charset = Charset.forName("UTF-8");
MediaType mediaType = body.contentType();
if (mediaType != null) {
charset = mediaType.charset(StandardCharsets.UTF_8);
}
return buffer.readString(charset);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* token过期,重新请求
* @param oldRequest
* @return
* @throws IOException
*/
public static Request reRequest(Request oldRequest) throws IOException {
//1.登录接口,拿到新的Token
NetResult<String> netResult = (NetResult) TestApi.loginSync("13333333333", "123456").body();//同步登录
String token=netResult.data;
//2.替换掉Token
RequestBody oldRequestBody = oldRequest.body();//获取旧的requestBody
RequestBody requestBody = replaceToken(oldRequestBody, token);//替换Token
//3.重新构建
return new Request.Builder().post(requestBody).url(oldRequest.url()).build();//重新构建request
}


三、同步登陆

public class TestApi extends NetApi implements UrlConsts {
private static TestService service = NetClient.getRetrofit(TEST_BASE_URL).create(TestService.class);

public static void getUserInfo(NetCallback<UserBean> callback) {
Map<String, Object> map = new HashMap<>();
Call call = service.getUserInfo(postRequestBody(map));
call.enqueue(callback);
NetManager.addRequest(call);
}

public static void login(String phoneNumber, String password, NetCallback<String> callback) {
Map<String, Object> map = new HashMap<>();
map.put("phoneNumber", phoneNumber);
map.put("password", password);
Call call = service.login(postRequestBody(map));
call.enqueue(callback);
NetManager.addRequest(call);
}

/**
* 同步请求
*
* @param phoneNumber
* @param password
*/
public static Response loginSync(String phoneNumber, String password) throws IOException {
Map<String, Object> map = new HashMap<>();
map.put("phoneNumber", phoneNumber);
map.put("password", password);
Call call = service.login(postRequestBody(map));
return call.execute();
}

}


四、处理问题主要在拦截器内

public class NetInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);//执行请求
String responseBodyStr = handResponse(response);//获得处理后的数据字符串
if (tokenException(responseBodyStr)) {//判断是否token过期
responseBodyStr = handResponse(chain.proceed(RequestUtils.reRequest(request)));
}
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), responseBodyStr))
.build();
}

/**
* 判断是否被告知Token过期
*
* @param responseBodyStr
* @return
*/
private boolean tokenException(String responseBodyStr) {
NetResult netResult = JsonUtils.jsonToObj(responseBodyStr, NetResult.class);
return netResult.code == 999;
}

/**
* 处理response
*
* @param response
* @return
* @throws IOException
*/
private String handResponse(Response response) throws IOException {
String passWord = "chrischen";//加密解密专用密码
ResponseBody responseBody = response.body();
String responseBodyStr = responseBody.string();
String requestUrl = response.request().url().url().toString();//请求路径
MsgUtils.show("MobileAPI:" + requestUrl + "  返回数据==>" + responseBodyStr);
return responseBodyStr;
}
}


五、测试代码

private static void test() throws Exception {
NetCallback<UserBean> callback = new NetCallback<UserBean>() {
@Override
protected void onComplete(NetResponse<UserBean> netResponse) {

}
};
TestApi.getUserInfo(callback);
}


六、运行结果的截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息