我们都知道,HTTP协议是无状态的,一旦数据交换完毕,连接就关闭,客户端和服务端互不相关,那么浏览器是怎么做到维持登录状态的呢还有保持用户数据的呢?答案是利用Cookie和Session。
我们来看看这张图。
此图是我第一次打开http://www.iconfont.cn/的返回头。画出红框的的是第一次请求 Servelet 或者 Jsp 等服务端程序返回的。
然后我刷新该页面,返回头变成了下图所示
留意到Set-Cookie只变成了一个了吗。这是后台的处理。
另外一个其实加入到了请求头的Cookie中,这是浏览器的默认行为,用于维持服务端的Session对象
在此后面的请求,浏览器则会将其加入请求头的Cookie中,其中保存着一些用户的数据。
显然,在安卓端我们也可以模仿这种做法(当然,前提是后台的确有利用Cookie和Session存储数据)
下面我以Retrofit为例编写代码
//Interceptor即拦截器,可用于修改请求前的请求体,以及请求后的返回体
public class CookieInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
String cookie;
Request request;
Response response;
//cookieMgr是封装的一个SharePreference类。 这里不用太在意
CookieMgr cookieMgr = new CookieMgr("cookie")
//获取存储在本地的cookie
if(!(cookie = cookieMgr.get("Set-Cookie","")).equals("")){
Request.Builder builder = chain.request().newBuilder();
//将cookie加入请求头中
builder.addHeader("Cookie",cookie);
request = builder.build();
Log.e("CookieInterceptor",cookie);
}else{
request = chain.request();
}
response = chain.proceed(request);
//如果是第一次请求,则会在返回头得到Set-Cookie。获取并存储在本地
if(response.header("Set-Cookie") != null){
cookieMgr .clear("Set-Cookie");
cookieMgr .save("Set-Cookie",response.header("Set-Cookie"));
}
return response;
}
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(8, TimeUnit.SECONDS)
//构建okhttpClient加入自定义的拦截器,实现每次请求都加入Cookie
.addInterceptor(new CookieInterceptor())
.build();
client = new Retrofit.Builder().client(okHttpClient).baseUrl(Constant.IP)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build().create(Api.class);
到此,每次用Retrofit请求数据,都会带上Cookie,服务端的Session就得以维持。
后台就可以利用维持的Session或Cookie存储数据,实现需求,比如维持登录状态,带验证码的登录,等等