如何在两个Retrofit实例间共享登录会话(JSESSIONID)
其实核心思路很简单:让两个Retrofit实例共用同一个OkHttpClient实例,因为Cookie的管理是由OkHttpClient的CookieJar负责的,只要共用这个客户端,登录后存储的JSESSIONID就会自动被后续请求带上。
我给你重构一下代码,让它更合理且能实现会话共享:
第一步:抽离共享的OkHttpClient配置
先把Cookie管理、拦截器、超时这些通用配置抽成一个可复用的单例,这样所有Retrofit实例都能共用它:
object HttpClientProvider { // 全局唯一的CookieManager,用来存储登录后的JSESSIONID private val cookieHandler = CookieManager() // 懒加载创建OkHttpClient实例 val sharedClient: OkHttpClient by lazy { val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } OkHttpClient.Builder() .addNetworkInterceptor(loggingInterceptor) // 绑定CookieManager,自动处理Cookie的存储和携带 .cookieJar(JavaNetCookieJar(cookieHandler)) .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build() } }
第二步:重构登录用的MyService
让它直接使用上面的共享OkHttpClient:
interface MyService { @POST("api/login") fun login(@Header("cred") id: String): Completable companion object { operator fun invoke(): MyService { return Retrofit.Builder() .baseUrl("http://mytestapi.com") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 使用共享的OkHttpClient .client(HttpClientProvider.sharedClient) .build() .create(MyService::class.java) } } }
第三步:创建第二个查询用的Retrofit接口
同样使用共享的OkHttpClient,这样它就能自动带上登录后的JSESSIONID:
// 示例:查询用的接口 interface QueryService { @GET("api/query/user-info") fun getUserInfo(): Observable<UserInfo> // 替换成你的实际返回类型 companion object { operator fun invoke(): QueryService { return Retrofit.Builder() .baseUrl("http://mytestapi.com") // 如果域名和登录接口一致,直接复用;不同的话修改即可 .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 关键:使用同一个共享OkHttpClient .client(HttpClientProvider.sharedClient) .build() .create(QueryService::class.java) } } }
为什么这样能行?
当你调用MyService.login()成功后,服务器返回的JSESSIONID Cookie会被CookieManager自动存储起来。之后,任何使用这个sharedClient的Retrofit请求(比如QueryService的请求),都会自动在请求头里带上这个Cookie,服务器就能识别到用户的登录会话了。
而且这种方式还能保证所有请求的超时、拦截器配置一致,避免重复代码,后续要修改配置也只需要改一处,非常方便。
内容的提问来源于stack exchange,提问作者mamenejr
相关产品推荐
相关产品推荐

