Retrofit2.0+Gson+RxJava 框架 之 Session保持(解決Session無效問題) 【Android】
Retrofit2.0中,每個請求之間是獨立開的,這產生一個問題,也就是如何保持Session資訊,更通俗易懂的說,就是如何保持登入狀態,如果不做任何操作,那麼不管登入多少次,都是無效的,無法進行其他許可權操作。這裡要提交到瀏覽器,瀏覽器是預設自動儲存伺服器傳送過來的Session資訊的,也就是預設保持Session資訊的,只有當瀏覽器關閉,才會清除這些Session資訊。
說到這裡,你可能會說Session不是儲存在伺服器的嗎?注意,這裡用的是“保持”,換一種說法,就是讓伺服器知道這還是你,而不是新的使用者連線。
Session 機制:
一般來說,伺服器使用Session來判斷使用者是否登入,也就是:
當伺服器與客戶建立新的連線時,會建立一個會話Session,每個使用者的Session的id都是不一樣的,這是識別每個客戶的一個id,當建立客戶的Session後會放在響應體Response的頭部資訊中,具體位置為:
也就是Cookie的第一個字元到第一個;之間,注意,這是一個key-value,我們只需要在登入後返回的Response的頭部將這一串資訊拿下,並在以後每一次請求中,在Cookie加入這一串Session資訊,即可實現Session保持,或者說 保持登入狀態。
實現步驟:
1.導包
匯入攔截器,主要作用是:1.攔截每一次請求。2.在攔截的請求中的Cookie中加入Session資訊。
compile 'com.squareup.okhttp3:logging-interceptor:3.8.1'
2.在第一次請求的響應體中,從Cookie中拿出Session資訊。如下:
主要程式碼:
public class UserController { public static UserService userService= RetrofitFactory.createRetrofit().create(UserService.class); public static void login(String username, String password, final NetCallback callback) { Map<String,Object> map=new HashMap<>(); map.put("userId",username); map.put("password",password); Call<ResponseBody> call=userService.login(map); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if(response.isSuccessful()){ try { HeaderInterceptor.cookie=response.headers().get("set-cookie"); Log.e("NetWork=>headers", HeaderInterceptor.cookie); callback.onSuccess(new Gson().fromJson(response.body().string(), ValidateResult.class)); } catch (IOException e) { callback.onError(10001); } } else{ Log.e("NetWork",response.message()); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e("NetWork",t.getLocalizedMessage()); callback.onError(10002); } }); } }
其中:獲取如下:
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccessful()){
try {
HeaderInterceptor.cookie=response.headers().get("set-cookie");
Log.e("NetWork=>headers", HeaderInterceptor.cookie);
callback.onSuccess(new Gson().fromJson(response.body().string(), ValidateResult.class));
} catch (IOException e) {
callback.onError(10001);
}
}
else{
Log.e("NetWork",response.message());
}
}
使用 response.headers().get('set-cookie");獲取cookie資訊,並將其儲存下來,這裡儲存在自定義攔截器HeaderInterceptor裡面.
3.建立攔截器HeaderInterceptor
程式碼如下:
public class HeaderInterceptor implements Interceptor {
//儲存cookie
public static String cookie=null;
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
if(cookie!=null) {
builder.addHeader("Cookie", cookie);
if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
builder.addHeader("Connection", "close");
}
}
else{
Log.e("Cookie","Cookie not found");
}
return chain.proceed(builder.build());
}
}
4.測試。