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

51 篇文章 1 订阅
27 篇文章 0 订阅

手机调用接口,关键数据请求需要验证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);
    }


六、运行结果的截图:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值