其他设置
其他设置
Header 设置
@Test
public void whenSetHeader_thenCorrect() throws IOException {
Request request = new Request.Builder()
.url(SAMPLE_URL)
.addHeader("Content-Type", "application/json")
.build();
Call call = client.newCall(request);
Response response = call.execute();
response.close();
}
在此示例中,我们将看到如何在客户端本身上配置默认标头,而不是在每个请求上都设置默认标头。例如,如果要为每个请求设置内容类型 application/json,则需要为客户端设置拦截器。方法如下:
@Test
public void whenSetDefaultHeader_thenCorrect()
throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(
new DefaultContentTypeInterceptor("application/json"))
.build();
Request request = new Request.Builder()
.url(SAMPLE_URL)
.build();
Call call = client.newCall(request);
Response response = call.execute();
response.close();
}
这是 DefaultContentTypeInterceptor,它是 Interceptor 的扩展版本:
public class DefaultContentTypeInterceptor implements Interceptor {
public Response intercept(Interceptor.Chain chain) throws IOException {
Request originalRequest = chain.request();
Request requestWithUserAgent = originalRequest
.newBuilder()
.header("Content-Type", contentType)
.build();
return chain.proceed(requestWithUserAgent);
}
}
避免重定向
在此示例中,我们将看到如何配置 OkHttpClient 以停止跟随重定向。默认情况下,如果使用 HTTP 301 永久移动响应了 GET 请求,则会自动遵循重定向。在某些用例中,可能会很好,但是在某些用例中肯定是不需要的。为了实现此行为,在构建客户端时,需要将 followRedirects 设置为 false。请注意,响应将返回 HTTP 301 状态代码:
@Test
public void whenSetFollowRedirects_thenNotRedirected()
throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder()
.followRedirects(false)
.build();
Request request = new Request.Builder()
.url("http://t.co/I5YYd9tddw")
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(301));
}
如果我们使用 true 参数打开重定向(或将其完全删除),则客户端将遵循重定向,并且测试将失败,因为返回码将为 HTTP 200。
超时与取消
当对方无法访问时,请使用超时使呼叫失败。网络故障可能是由于客户端连接问题,服务器可用性问题或两者之间的任何原因引起的。OkHttp 支持连接,读取和写入超时。在此示例中,我们以 1 秒的 readTimeout 构建客户端,而以 2 秒的延迟提供 URL:
@Test
public void whenSetRequestTimeout_thenFail()
throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(1, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url(BASE_URL + "/delay/2")
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(200));
}
使用 Call.cancel() 立即停止正在进行的呼叫。如果线程当前正在写入请求或读取响应,则将抛出 IOException。当不再需要通话时,使用此功能可以节省网络。例如,当您的用户离开应用程序时:
@Test(expected = IOException.class)
public void whenCancelRequest_thenCorrect()
throws IOException {
ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1);
Request request = new Request.Builder()
.url(BASE_URL + "/delay/2")
.build();
int seconds = 1;
long startNanos = System.nanoTime();
Call call = client.newCall(request);
executor.schedule(() -> {
logger.debug("Canceling call: "
+ (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
logger.debug("Canceled call: "
+ (System.nanoTime() - startNanos) / 1e9f);
}, seconds, TimeUnit.SECONDS);
logger.debug("Executing call: "
+ (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
logger.debug(Call was expected to fail, but completed: "
+ (System.nanoTime() - startNanos) / 1e9f, response);
}
响应缓存
要创建一个缓存,我们需要一个我们可以读写的缓存目录,以及对缓存大小的限制。客户端将使用它来缓存响应:
@Test
public void whenSetResponseCache_thenCorrect()
throws IOException {
int cacheSize = 10 * 1024 * 1024;
File cacheDirectory = new File("src/test/resources/cache");
Cache cache = new Cache(cacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response1 = client.newCall(request).execute();
logResponse(response1);
Response response2 = client.newCall(request).execute();
logResponse(response2);
}
启动测试后,第一个调用的响应将不会被缓存。对方法 cacheResponse 的调用将返回 null,而对方法 networkResponse 的调用将返回来自网络的响应。此外,缓存文件夹中将填充缓存文件。第二次调用执行将产生相反的效果,因为响应已经被缓存了。这意味着对 networkResponse 的调用将返回 null,而对 cacheResponse 的调用将返回来自缓存的响应。为了防止响应使用缓存,请使用 CacheControl.FORCE_NETWORK。若要阻止它使用网络,请使用 CacheControl.FORCE_CACHE。