okhttp的簡單使用

1.同步get請求

   對于小文檔,響應(yīng)體上的string()方法非常方便和高效。但是,如果響應(yīng)主體很大(大于1 MB),則應(yīng)避免string(),因為它會將整個文檔加載到內(nèi)存中。在這種情況下,將主體處理為流。
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());
    }
  }

2.異步get請求

     在工作線程上下載一個文件,并在響應(yīng)可讀時得到回調(diào)?;卣{(diào)是在準備好響應(yīng)頭之后進行的。讀取響應(yīng)體可能仍然會阻塞。OkHttp目前不提供異步api來接收部分響應(yīng)體。
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());
       }
     }
   });
 }

添加請求頭

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"));
   }
 }

3.post String上傳

   使用HTTP POST向服務(wù)發(fā)送請求體。本例將markdown文檔發(fā)布到web服務(wù)器呈現(xiàn)為HTML。由于整個請求體同時位于內(nèi)存中,因此避免使用此API發(fā)布大型(大于1 MB)文檔。
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());
   }

4. post 流上傳

   這里,我們將請求體作為一個流發(fā)布。此請求體的內(nèi)容在編寫時生成。這個例子直接流進Okio緩沖池。您的程序可能更喜歡OutputStream,您可以從BufferedSink.outputStream()中獲得它。
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());
   }
 }

5. post 文件上傳

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());
   }
 }

6. post 上傳表單

   使用FormBody。構(gòu)建器來構(gòu)建一個類似于HTML <form>標記的請求體。名稱和值將使用html兼容的表單URL編碼進行編碼
private final OkHttpClient client = new OkHttpClient();

 public void run() throws Exception {
   RequestBody formBody = new FormBody.Builder()
       .add("search", "Jurassic Park")
       .build();
   Request request = new Request.Builder()
       .url("https://en.wikipedia.org/w/index.php")
       .post(formBody)
       .build();

   try (Response response = client.newCall(request).execute()) {
     if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

     System.out.println(response.body().string());
   }
 }

7. post 多種請求體上傳

MultipartBody.Builder 可以構(gòu)建與HTML文件上傳表單兼容的復(fù)雜請求體。復(fù)雜請求體的每個部分本身都是一個請求體,并且可以定義自己的頭。如果存在,這些頭應(yīng)該描述部件主體,比如它的內(nèi)容配置。如果內(nèi)容長度和內(nèi)容類型頭可用,則自動添加它們 。

     private static final String IMGUR_CLIENT_ID = "...";
 private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

 private final OkHttpClient client = new OkHttpClient();

 public void run() throws Exception {
   // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
   RequestBody requestBody = new MultipartBody.Builder()
       .setType(MultipartBody.FORM)
       .addFormDataPart("title", "Square Logo")
       .addFormDataPart("image", "logo-square.png",
           RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
       .build();

   Request request = new Request.Builder()
       .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
       .url("https://api.imgur.com/3/image")
       .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());
   }
 }

8. response caching

    要緩存響應(yīng),您需要一個可以讀寫的緩存目錄,以及緩存大小的限制。緩存目錄應(yīng)該是私有的,不受信任的應(yīng)用程序不應(yīng)該能夠讀取它的內(nèi)容!
    多個緩存同時訪問同一個緩存目錄是錯誤的。大多數(shù)應(yīng)用程序應(yīng)該只調(diào)用new OkHttpClient()一次,用它們的緩存配置它,并在任何地方使用相同的實例。否則,這兩個緩存實例將相互踐踏,破壞響應(yīng)緩存,并可能導(dǎo)致程序崩潰。
      Response caching uses HTTP headers for all configuration. You can add request headers like Cache-Control: max-stale=3600 and OkHttp's cache will honor them. Your webserver configures how long responses are cached with its own response headers, like Cache-Control: max-age=9600. There are cache headers to force a cached response, force a network response, or force the network response to be validated with a conditional GET.
private final OkHttpClient client;

 public CacheResponse(File cacheDirectory) throws Exception {
   int cacheSize = 10 * 1024 * 1024; // 10 MiB
   Cache cache = new Cache(cacheDirectory, cacheSize);

   client = new OkHttpClient.Builder()
       .cache(cache)
       .build();
 }

 public void run() throws Exception {
   Request request = new Request.Builder()
       .url("http://publicobject.com/helloworld.txt")
       .build();

   String response1Body;
   try (Response response1 = client.newCall(request).execute()) {
     if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);

     response1Body = response1.body().string();
     System.out.println("Response 1 response:          " + response1);
     System.out.println("Response 1 cache response:    " + response1.cacheResponse());
     System.out.println("Response 1 network response:  " + response1.networkResponse());
   }

   String response2Body;
   try (Response response2 = client.newCall(request).execute()) {
     if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);

     response2Body = response2.body().string();
     System.out.println("Response 2 response:          " + response2);
     System.out.println("Response 2 cache response:    " + response2.cacheResponse());
     System.out.println("Response 2 network response:  " + response2.networkResponse());
   }

   System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
 }

9. Canceling a Call

      Use Call.cancel() to stop an ongoing call immediately. If a thread is currently writing a request or reading a response, it will receive an IOException. Use this to conserve the network when a call is no longer necessary; for example when your user navigates away from an application. Both synchronous and asynchronous calls can be canceled.
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
 private final OkHttpClient client = new OkHttpClient();

 public void run() throws Exception {
   Request request = new Request.Builder()
       .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
       .build();

   final long startNanos = System.nanoTime();
   final Call call = client.newCall(request);

   // Schedule a job to cancel the call in 1 second.
   executor.schedule(new Runnable() {
     @Override public void run() {
       System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
       call.cancel();
       System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
     }
   }, 1, TimeUnit.SECONDS);

   System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
   try (Response response = call.execute()) {
     System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
         (System.nanoTime() - startNanos) / 1e9f, response);
   } catch (IOException e) {
     System.out.printf("%.2f Call failed as expected: %s%n",
         (System.nanoTime() - startNanos) / 1e9f, e);
   }
 }

10. Timeout

Use timeouts to fail a call when its peer is unreachable. Network partitions can be due to client connectivity problems, server availability problems, or anything between. OkHttp supports connect, read, and write timeouts.
 private final OkHttpClient client;

 public ConfigureTimeouts() throws Exception {
   client = new OkHttpClient.Builder()
       .connectTimeout(10, TimeUnit.SECONDS)
       .writeTimeout(10, TimeUnit.SECONDS)
       .readTimeout(30, TimeUnit.SECONDS)
       .build();
 }

 public void run() throws Exception {
   Request request = new Request.Builder()
       .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
       .build();

   try (Response response = client.newCall(request).execute()) {
     System.out.println("Response completed: " + response);
   }
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容