Android:如何通过Retrofit从响应头中获取Cookie?
嘿,作为Retrofit新手,能把Dagger、Rx、MVP这些技术栈凑到一起做登录功能,已经超棒啦!针对你说的这个场景——发送JSON格式的登录参数、后端返回true的响应体还在响应头带Cookie,我给你梳理一下具体的实现思路和代码示例,帮你踩坑:
1. 定义Retrofit接口
首先要写一个符合需求的Retrofit接口,因为要同时获取响应体和响应头,我们得让接口返回Observable<Response<Boolean>>(而不是直接返回Boolean),这样就能拿到完整的响应信息:
// 如果你用Java,语法类似,把data class换成POJO就行 interface AuthService { @POST("Authentication.svc/json/Login") fun login(@Body loginRequest: LoginRequest): Observable<Response<Boolean>> } // 登录请求的实体类,字段要和后端要求的JSON键完全匹配 data class LoginRequest( val username: String, val password: String, val customCredential: String, val isPersistent: Boolean )
2. 在MVP Presenter中处理请求
结合RxJava的线程调度,在Presenter里发起请求,同时处理响应体和响应头的Cookie:
class LoginPresenter( private val authService: AuthService, private val view: LoginContract.View, private val context: Context ) : LoginContract.Presenter { private val compositeDisposable = CompositeDisposable() override fun performLogin(username: String, password: String, customCredential: String) { val loginReq = LoginRequest(username, password, customCredential, false) val disposable = authService.login(loginReq) .subscribeOn(Schedulers.io()) // 网络请求在IO线程执行 .observeOn(AndroidSchedulers.mainThread()) // 结果回调到主线程更新UI .subscribe( { response -> if (response.isSuccessful && response.body() == true) { // 登录成功,提取响应头里的Cookie val cookieHeader = response.headers().get("Set-Cookie") cookieHeader?.let { saveAuthCookie(it) } view.onLoginSuccess() } else { view.onLoginFailed("登录失败:后端返回非成功状态") } }, { error -> error.printStackTrace() view.onLoginFailed("网络出错:${error.message ?: "未知错误"}") } ) compositeDisposable.add(disposable) } // 把Cookie保存到SharedPreferences,方便后续请求携带 private fun saveAuthCookie(cookie: String) { val sharedPref = context.getSharedPreferences("AppAuthPrefs", Context.MODE_PRIVATE) sharedPref.edit().putString("AUTH_COOKIE", cookie).apply() } // 页面销毁时清理Rx订阅,防止内存泄漏 override fun onDestroy() { compositeDisposable.dispose() } }
3. 配置Retrofit(结合Dagger依赖注入)
要确保Retrofit配置了Gson转换器(用来序列化/反序列化JSON)和RxJava适配器(让接口返回Observable),同时可以加上日志拦截器来输出你贴的那种请求日志:
@Module class NetworkModule { @Provides fun provideGson(): Gson = GsonBuilder().create() @Provides fun provideOkHttpClient(): OkHttpClient { // 配置日志拦截器,对应你贴的请求日志 val loggingInterceptor = HttpLoggingInterceptor { msg -> Log.d("Payesh", msg) }.setLevel(HttpLoggingInterceptor.Level.BODY) return OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() } @Provides fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("http://test.com/") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() } @Provides fun provideAuthService(retrofit: Retrofit): AuthService = retrofit.create(AuthService::class.java) }
几个关键注意点
- 如果后续接口需要携带这个Cookie,记得给OkHttpClient加一个请求拦截器,把保存的Cookie放到请求头里
- 响应头里的
Set-Cookie可能有多个值,如果你需要全部获取,可以用response.headers("Set-Cookie")拿到一个列表 - 如果实体类字段和JSON键名不一致,记得用
@SerializedName("键名")注解来映射
内容的提问来源于stack exchange,提问作者Cyrus the Great
相关产品推荐
相关产品推荐

