手机调用接口,关键数据请求需要验证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); }六、运行结果的截图: