如何用Retrofit2 Interceptor实现先获取Cookie再调用目标API?
嘿,我太懂你现在的困扰了——每次调用API都要嵌套一层Cookie验证的请求,重复代码堆得像山,不仅写着烦,后期维护也头疼。用Retrofit的Interceptor就能把这个验证逻辑彻底抽离出来,让业务请求和Cookie验证完全解耦,再也不用写那些嵌套的Callback了!
核心思路
Interceptor就像请求的“前置过滤器”,所有经过Retrofit的请求都会先经过它。我们可以在这里统一处理Cookie验证:
- 拦截需要验证的请求
- 同步验证当前Cookie的有效性
- 验证通过就放行原请求;不通过就触发登录(或刷新Cookie),中断当前请求
1. 编写Cookie验证Interceptor
注意:Interceptor的intercept方法是阻塞式的,所以Cookie验证要用同步请求,不能用异步的enqueue。另外UI操作要切回主线程,因为Interceptor默认在子线程执行。
public class AuthCookieInterceptor implements Interceptor { private final AuthCookieModel authCookieModel; private final Context context; public AuthCookieInterceptor(AuthCookieModel authCookieModel, Context context) { this.authCookieModel = authCookieModel; this.context = context; } @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); // 先同步验证Cookie有效性 ValidateAuthCookieModel validateResult = validateCookieSync(authCookieModel.getCookie()); if (validateResult == null || !validateResult.valid) { // Cookie无效,切回主线程跳登录 ((Activity) context).runOnUiThread(this::openLogin); // 抛出异常中断请求,让业务层可以捕获处理 throw new IOException("Cookie验证失败,已跳转登录"); } // Cookie有效,放行原请求 return chain.proceed(originalRequest); } // 同步调用Cookie验证API private ValidateAuthCookieModel validateCookieSync(String cookie) throws IOException { OkHttpClient tempClient = new OkHttpClient(); Request validateRequest = new Request.Builder() .url(ApiUtil.VALIDATE_COOKIE_URL) // 替换成你的验证API地址 .addHeader("Cookie", cookie) .build(); Response response = tempClient.newCall(validateRequest).execute(); if (response.isSuccessful()) { return new Gson().fromJson(response.body().string(), ValidateAuthCookieModel.class); } return null; } private void openLogin() { // 这里写你的登录页面跳转逻辑 Intent intent = new Intent(context, LoginActivity.class); context.startActivity(intent); } }
2. 给Retrofit配置Interceptor
把上面的Interceptor添加到Retrofit的OkHttpClient里,这样所有请求都会自动走验证流程:
OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new AuthCookieInterceptor(authCookieModel, yourContext)) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiUtil.BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); // 创建你的API Service接口实例 ApiService apiService = retrofit.create(ApiService.class);
3. 优化后的业务请求代码
现在你原来的嵌套代码可以简化成一行,再也不用写双层Callback了:
apiService.addLike(item.getId(), mCookie).enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { // 处理点赞成功的业务逻辑 } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 可以在这里捕获Cookie验证失败的异常 if (t instanceof IOException && t.getMessage().contains("Cookie验证失败")) { // 已经在Interceptor里跳了登录,这里不用重复处理 } else { // 处理其他请求失败情况(比如网络错误) } } });
额外优化小技巧
- 跳过特定请求的验证:如果有些公共API不需要Cookie验证,可以给请求加自定义Header,在Interceptor里判断跳过:
// Interceptor里添加判断 if (originalRequest.header("Skip-Cookie-Validation") != null) { return chain.proceed(originalRequest); } // API接口里添加Header @GET("public/article") Call<ArticleModel> getPublicArticles(@Header("Skip-Cookie-Validation") String skip); // 调用时传"true"即可跳过验证 apiService.getPublicArticles("true").enqueue(...); - 自动刷新Cookie:如果你的系统支持用refresh token刷新Cookie,可以在Interceptor里替换跳登录的逻辑,先尝试刷新Cookie,成功后自动重试原请求,提升用户体验。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

