我我的理解:Cookie其实就是记录用户的一些信息、状态行为等。有这样一种场景,用户在登陆成功后,服务端会返回Cookie,里面包含用户的登录状态信息等,这样用户在访问本身的收藏列表时,加上这个Cookie,那么就可直接获取到文章列表,若是没有Cookie,那服务端怎么知道你是要获取哪一个用户的文章列表呢。java
在浏览器上,返回的Cookie会保存在浏览器中,在下次访问时会自动加上该段Cookie,而Android端,须要咱们本身来保存服务端返回的Cookie,并在下次访问的时候本身添加上。至于如何保存(Cookie持久化),方法不少,能够用数据库、文件、SharedPreferences、也可使用Webview的CookieManager。android
你们能够看这篇文章Cookie介绍及在Android中的使用总结超详细,看这一篇就够了git
Cookie访问时添加上其实就是使用header来添加头部信息,至于怎么添加上篇文章已经介绍,但显然不能这样,总不能在每一个须要Cookie的api上都写上头部信息或动态添加,那这样也太繁琐了,接下来咱们将经过拦截器来动态添加。github
本篇文章我将采用Wandroid网站中的登录接口和收藏文章列表接口数据库
登录json
https://www.wanandroid.com/user/login
方法:POST
参数:
username,password
复制代码
登陆后会在cookie中返回帐号密码,只要在客户端作cookie持久化存储便可自动登陆验证。api
收藏文章列表浏览器
https://www.wanandroid.com/lg/collect/list/0/json
方法:GET
参数: 页码:拼接在连接中,从0开始。
复制代码
在网站上登陆后,能够直接访问www.wanandroid.com/lg/collect/…查看本身收藏的文章。服务器
你们能够如今该网站上注册个帐号而且收藏几篇文章,供下面使用。cookie
为何要说OkHttp呢,由于Retrofit底层就是使用OkHttp实现的,只是对其进行了封装,咱们能够经过Okhttp中的Interceptor拦截器来设置请求头,而后经过retrofit.client(okhttpclient)对请求头进行修改,这样就省去了咱们手动添加请求头的步骤。
这里咱们建立两个拦截器,一个用于登陆时接收Cookie保存在本地,另外一个拦截器用于访问时在请求里添加Cookie。
public class ReceivedCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
//拦截的cookie保存在originalResponse中
Response originalResponse = chain.proceed(chain.request());
//打印cookie信息
Log.i(TAG, "intercept: "+ originalResponse.headers("Set-Cookie").toString());
...
return originalResponse;
}
}
复制代码
经过chain.proceed(chain.request())
获取到的response内保存了拦截到的cookie信息。
经过Log.i(TAG, "intercept: "+ originalResponse.headers("Set-Cookie").toString());
打印头部信息日志
咱们能够看到网络请求返回的cookie信息,咱们要作的就是将这个cookie保存在本地。
这里我将采用sharepreference的方式来存储Cookie
先判断Set-Cookie的头部不为空
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
...
}
复制代码
经过循环将Cookie信息放入到HashSet集合中
HashSet<String> cookies = new HashSet<>();
for(String header: originalResponse.headers("Set-Cookie"))
{
cookies.add(header);
}
复制代码
经过SharePreference将Cookie信息保存在本地
//保存的sharepreference文件名为cookieData
SharedPreferences sharedPreferences = context.getSharedPreferences("cookieData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putStringSet("cookie", cookies);
editor.commit();
复制代码
public class ReceivedCookiesInterceptor implements Interceptor {
public ReceivedCookiesInterceptor() {
super();
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
//这里获取请求返回的cookie
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = new HashSet<>();
for(String header: originalResponse.headers("Set-Cookie"))
{
LogUtil.i(TAG, "拦截的cookie是:"+header);
cookies.add(header);
}
//保存的sharepreference文件名为cookieData
SharedPreferences sharedPreferences = App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putStringSet("cookie", cookies);
editor.commit();
}
return originalResponse;
}
}
复制代码
public class AddCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
}
}
复制代码
Request.Builder builder = chain.request().newBuilder();
HashSet<String> perferences = (HashSet) App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE).getStringSet("cookie", null);
if (perferences != null) {
for (String cookie : perferences) {
builder.addHeader("Cookie", cookie);
}
}
return chain.proceed(builder.build());
复制代码
public class AddCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
HashSet<String> perferences = (HashSet) App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE).getStringSet("cookie", null);
if (perferences != null) {
for (String cookie : perferences) {
builder.addHeader("Cookie", cookie);
}
}
return chain.proceed(builder.build());
}
}
复制代码
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new ReceivedCookiesInterceptor())
.build();
复制代码
private Retrofit retrofitLogin;
retrofitLogin = new Retrofit.Builder()
.baseUrl("https://a/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
复制代码
public interface Api {
//登陆接口
@FormUrlEncoded
@POST
Call<UserBean> login(@Url String url, @FieldMap Map<String, String> param);
}
复制代码
private Api loginApi;
loginApi = retrofitLogin.create(Api.class);
复制代码
Map<String, String> param = new HashMap<>();
param.put("username", etUsername.getText().toString());
param.put("password", etPwd.getText().toString());
loginApi.login(loginUrl, param).enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
if (response != null && response.body() != null) {
if (response.body().getErrorCode() == 0) {
Toast.makeText(getApplicationContext(), "登陆成功", Toast.LENGTH_SHORT).show();}
else {
Toast.makeText(getApplicationContext(), "登陆失败" + response.body().getErrorCode() + response.body().getErrorMsg(), Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
Toast.makeText(getApplicationContext(), "登陆失败"+t, Toast.LENGTH_SHORT).show();
}
});
}
else {
Toast.makeText(this, "请输入完整的用户信息", Toast.LENGTH_SHORT).show();
}
复制代码
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new AddCookiesInterceptor())
.build();
复制代码
retrofitCollect = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
复制代码
public interface Api {
//获取收藏列表
@GET("lg/collect/list/{page}/json")
Call<MyCollectionBean> getCollecEssay(@Path("page") int page);
}
复制代码
private Retrofit retrofitCollect;
private Api getCollectApi;
getCollectApi = retrofitCollect.create(Api.class);
复制代码
getCollectApi.getCollecEssay(0).enqueue(new Callback<MyCollectionBean>() {
@Override
public void onResponse(Call<MyCollectionBean> call, Response<MyCollectionBean> response) {
if (response != null && response.body() != null) {
if (response.body().getErrorCode() == 0) {
Log.i(TAG, "onResponse: 获取文章列表成功");
for (int i = 0; i < response.body().getData().getDatas().size(); i++) {
Log.i(TAG, "\n 收藏的标题名为:" + response.body().getData().getDatas().get(i).getTitle());
}
} else {
Log.i(TAG, "onResponse: 获取文章列表失败"+response.body().getErrorMsg());
}
}
}
@Override
public void onFailure(Call<MyCollectionBean> call, Throwable t) {
Log.i(TAG, "onResponse: 获取文章列表失败"+t);
}
});
复制代码
以上就是所有内容,具体代码见Github。
其实咱们使用拦截器的目的就是为了将Cookie信息拦截保存到本地和经过拦截器将Cookie添加到头部信息里,是为了简化咱们手动去添加头部信息这一步。
以上就是所有内容,若是有错误的地方还望指出,对你有帮助的话麻烦看官给个start呗。关于Retrofit的图片上传文章还在编辑中,至于怎么用云服务器给你们写个图片上传接口,还在想怎么搞,后台小白一枚,会的大佬麻烦指导指导我。