You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在两个Retrofit实例间共享登录会话(JSESSIONID)

如何在多个Retrofit实例间共享登录会话(JSESSIONID Cookie)

其实核心思路很简单:让两个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:12:51