Recipes 我们已经编写了一些使用方法,演示如何使用OkHttp解决常见问题。 仔细阅读它们,了解一切如何协同工作。自由剪切和粘贴这些例子;
Synchronous Get 下载文件,打印其标题,并将其响应正文打印为字符串。 响应体上的string()方法对于小文档来说非常方便有效。 但是如果响应体很大(大于1 MiB),请避免使用string(),因为它会将整个文档加载到内存中。在这种情况下,更喜欢将消息体作为流来处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { Request request = new Request.Builder() .url("https://publicobject.com/helloworld.txt" ) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0 ; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(response.body().string()); } }
Asynchronous Get 在工作线程上下载文件,并在响应可读时回调。 回调是在响应头准备好之后进行的。 阅读响应正文可能仍会阻止。 OkHttp目前不提供异步API来接收部分响应主体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt" ) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure (Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse (Call call, Response response) throws IOException { try (ResponseBody responseBody = response.body()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0 , size = responseHeaders.size(); i < size; i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(responseBody.string()); } } }); }
通常,HTTP标头的工作方式类似于Map <String,String>:每个字段都有一个值或没有。 但是一些标题允许多个值,例如Guava的Multimap。 例如,HTTP响应提供多个Vary标头是合法且常见的。 OkHttp的API试图使两种情况都很舒适。
在编写请求标头时,使用标头(名称,值)将name的唯一出现设置为value。 如果存在现有值,则在添加新值之前将删除它们。 使用addHeader(name,value)添加标头而不删除已存在的标头。
读取响应标头时,使用标头(名称)返回最后一次出现的命名值。 通常这也是唯一的发生! 如果没有值,则header(name)将返回null。 要将所有字段的值作为列表读取,请使用标题(名称)。
要访问所有标头,请使用支持索引访问的Headers类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { Request request = new Request.Builder() .url("https://api.github.com/repos/square/okhttp/issues" ) .header("User-Agent" , "OkHttp Headers.java" ) .addHeader("Accept" , "application/json; q=0.5" ) .addHeader("Accept" , "application/vnd.github.v3+json" ) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println("Server: " + response.header("Server" )); System.out.println("Date: " + response.header("Date" )); System.out.println("Vary: " + response.headers("Vary" )); } }
Posting a String 使用HTTP POST将请求正文发送到服务。 此示例将markdown文档发布到将markdown呈现为HTML的Web服务。 由于整个请求主体同时在内存中,因此请避免使用此API发布大型(大于1 MiB)文档。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8" ); private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { String postBody = "" + "Releases\n" + "--------\n" + "\n" + " * _1.0_ May 6, 2013\n" + " * _1.1_ June 15, 2013\n" + " * _1.2_ August 11, 2013\n" ; Request request = new Request.Builder() .url("https://api.github.com/markdown/raw" ) .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody)) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } }
Post a file 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8" ); private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { File file = new File("README.md" ); Request request = new Request.Builder() .url("https://api.github.com/markdown/raw" ) .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } }
Post Streaming 在这里,我们将请求主体作为流发布。 该请求正文的内容正在编写时生成。 此示例直接流入Okio缓冲接收器。 您的程序可能更喜欢OutputStream,您可以从BufferedSink.outputStream()获取它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8" ); private final OkHttpClient client = new OkHttpClient(); public void run () throws Exception { RequestBody requestBody = new RequestBody() { @Override public MediaType contentType () { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo (BufferedSink sink) throws IOException { sink.writeUtf8("Numbers\n" ); sink.writeUtf8("-------\n" ); for (int i = 2 ; i <= 997 ; i++) { sink.writeUtf8(String.format(" * %s = %s\n" , i, factor(i))); } } private String factor (int n) { for (int i = 2 ; i < n; i++) { int x = n / i; if (x * i == n) return factor(x) + " × " + i; } return Integer.toString(n); } }; Request request = new Request.Builder() .url("https://api.github.com/markdown/raw" ) .post(requestBody) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } }
Posting form parameters 使用FormBody.Builder构建一个像HTML