今天实现登陆和注册功能,发送数据到服务器的过程中遇到两次提交数据的情况。而出现这个情况的原因是因为我使用两个拦截器。代码如下所示。首先这里设置请求头,将cookie放到请求头中,发送到服务器实现登陆与注册验证码的校验。
public class AddCookiesInterceptor implements Interceptor {
Context context;
public AddCookiesInterceptor(Context context) {
this.context = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
/*设置cookie*/
Request.Builder builder = chain.request().newBuilder();
HashSet<String> preferences = (HashSet) this.context.getSharedPreferences("config",
this.context.MODE_PRIVATE).getStringSet("cookie", null);
if (preferences != null) {
for (String cookie : preferences) {
builder.addHeader("Cookie", cookie);
builder.addHeader("Content-Type", "text/html; charset=UTF-8");
Log.v("OkHttp", "Adding Header: " + cookie); // This is done so I know which headers are being added; this interceptor is used after the normal logging of OkHttp
}
}
chain.proceed(chain.request());
return chain.proceed(builder.build());
}
}
而另外一个拦截器则定义如下所示。主要是接收cookie,存储到移动端。在下一次也就是填好数据后,将cookie发送到服务器。
public class ReceivedCookiesInterceptor implements Interceptor {
Context context;
public ReceivedCookiesInterceptor(Context context) {
this.context = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = new HashSet<>();
for (String header : originalResponse.headers("Set-Cookie")) {
cookies.add(header);
}
SharedPreferences.Editor config = context.getSharedPreferences("config", context.MODE_PRIVATE)
.edit();
config.putStringSet("cookie", cookies);
config.commit();
}
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Content-Type", "text/html; charset=UTF-8");
//return originalResponse;
return chain.proceed(builder.build());
}
}
问题就出现在上面的这段代码,与后台交互过程中,出现两次请求,开始我也很懵逼。好像代码没有问题,后面发现问题出现在这一句代码。执行这句后,会发送发送一次请求。那么加上最开始那个类的chain.proceed(chain),一共就是两次请求了。
chain.proceed(chain.request());
这是因为在okhttp中做这样的拦截。
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间
builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间
builder.retryOnConnectionFailure(false);
//https://segmentfault.com/q/1010000003894433
builder.addInterceptor(new AddCookiesInterceptor(mContext));
builder.addInterceptor(new ReceivedCookiesInterceptor(mContext));
出现这样的问题后,导致我发送的验证码,无法和服务器相对应。好了,最后找到解决方案。如下代码。
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
builder.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl httpUrl, List<Cookie> cookies) {
cookieStore.put(httpUrl.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl httpUrl) {
List<Cookie> cookies = cookieStore.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
});