OkHttp是一個高效的HTTP客戶端,在Android中用的比較多,也可以用在Java中;本文主要介紹OkHttp在java中的使用,文中所使用到的軟件版本:Java 1.8.0_191、SpringBoot 2.2.1.RELEASE。
1、OkHttp特點
a、支持HTTP/2,允許所有同一個主機地址的請求共享同一個socket連接
b、連接池減少請求延時
c、透明的GZIP壓縮減少響應數據的大小
d、緩存響應內容,避免一些完全重復的請求
2、服務端
3、調用Http接口
添加依賴如下:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.8.1</version> </dependency>
由於okHttp 4.x用到了kotline,所以需要kotline的環境;在IDEA中可以直接下載kotline的插件。
3.1、GET請求
@Test public void get() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(requestPath).get().build(); Response response = client.newCall(request).execute(); System.out.println("get返回狀態:" + response.code()); System.out.println("get返回結果:" + response.body().string()); response.close(); }
3.2、POST請求(發送鍵值對數據)
@Test public void post() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/getUser"; OkHttpClient client = new OkHttpClient(); RequestBody body = new FormBody.Builder() .add("userId", "1000") .add("userName", "李白") .build(); Request request = new Request.Builder() .url(requestPath).post(body).build(); Response response = client.newCall(request).execute(); System.out.println("post返回狀態:" + response.code()); System.out.println("post返回結果:" + response.body().string()); response.close(); }
3.3、POST請求(發送JSON數據)
@Test public void post2() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/addUser"; OkHttpClient client = new OkHttpClient(); String param = "{\"userId\": \"1001\",\"userName\":\"杜甫\"}"; RequestBody body = RequestBody.create(param, MediaType.get("application/json; charset=utf-8")); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("post2返回狀態:" + response.code()); System.out.println("post2返回結果:" + response.body().string()); response.close(); }
3.4、上傳文件
@Test public void upload() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/upload"; OkHttpClient client = new OkHttpClient(); File file = new File("d:/a.jpg"); RequestBody body = RequestBody.create(file, MediaType.get("file/*")); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("upload返回狀態:" + response.code()); System.out.println("upload返回結果:" + response.body().string()); response.close(); }
3.5、上傳文件及發送鍵值對數據
@Test public void mulit() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/multi"; OkHttpClient client = new OkHttpClient(); File file = new File("d:/a.jpg"); RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), RequestBody.create(file, MediaType.parse("image/png"))) .addFormDataPart("param1", "參數1") .addFormDataPart("param2", "參數2") .build(); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("mulit返回狀態:" + response.code()); System.out.println("mulit返回結果:" + response.body().string()); response.close(); }
3.6、完整例子

package com.inspur.demo.http.client; import okhttp3.*; import org.junit.Test; import java.io.File; import java.io.IOException; /** * 通過OkHttp調用Http接口 */ public class OkHttpCase { /** * GET請求 */ @Test public void get() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(requestPath).get().build(); Response response = client.newCall(request).execute(); System.out.println("get返回狀態:" + response.code()); System.out.println("get返回結果:" + response.body().string()); response.close(); } /** * POST請求(發送鍵值對數據) */ @Test public void post() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/getUser"; OkHttpClient client = new OkHttpClient(); RequestBody body = new FormBody.Builder() .add("userId", "1000") .add("userName", "李白") .build(); Request request = new Request.Builder() .url(requestPath).post(body).build(); Response response = client.newCall(request).execute(); System.out.println("post返回狀態:" + response.code()); System.out.println("post返回結果:" + response.body().string()); response.close(); } /** * POST請求(發送json數據) */ @Test public void post2() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/addUser"; OkHttpClient client = new OkHttpClient(); String param = "{\"userId\": \"1001\",\"userName\":\"杜甫\"}"; RequestBody body = RequestBody.create(param, MediaType.get("application/json; charset=utf-8")); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("post2返回狀態:" + response.code()); System.out.println("post2返回結果:" + response.body().string()); response.close(); } /** * 上傳文件 */ @Test public void upload() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/upload"; OkHttpClient client = new OkHttpClient(); File file = new File("d:/a.jpg"); RequestBody body = RequestBody.create(file, MediaType.get("file/*")); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("upload返回狀態:" + response.code()); System.out.println("upload返回結果:" + response.body().string()); response.close(); } /** * 上傳文件及發送鍵值對數據 */ @Test public void mulit() throws IOException { String requestPath = "http://localhost:8080/demo/httptest/multi"; OkHttpClient client = new OkHttpClient(); File file = new File("d:/a.jpg"); RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), RequestBody.create(file, MediaType.parse("image/png"))) .addFormDataPart("param1", "參數1") .addFormDataPart("param2", "參數2") .build(); Request request = new Request.Builder() .url(requestPath) .post(body) .build(); Response response = client.newCall(request).execute(); System.out.println("mulit返回狀態:" + response.code()); System.out.println("mulit返回結果:" + response.body().string()); response.close(); } }
4、調用Https接口
與調用Http接口不一樣的部分主要在設置sslSocketFactory和hostnameVerifier部分,下面用GET請求來演示sslSocketFactory和hostnameVerifier的設置,其他調用方式類似。
package com.inspur.demo.http.client; import com.inspur.demo.common.util.FileUtil; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.junit.Test; import javax.net.ssl.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * 通過OkHttp調用Https接口 */ public class OkHttpHttpsCase { /* * 請求有權威證書的地址 */ @Test public void test() throws IOException { String requestPath = "https://www.baidu.com/"; OkHttpClient client = new OkHttpClient.Builder() //.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS)) .build(); Request request = new Request.Builder() .url(requestPath).get().build(); Response response = client.newCall(request).execute(); System.out.println("get返回狀態:" + response.code()); System.out.println("get返回結果:" + response.body().string()); response.close(); } /** * 請求自定義證書的地址,不需要客戶端證書 * * @throws Exception */ @Test public void test2() throws Exception { String requestPath = "https://10.40.103.48:9010/zsywservice"; //獲取信任證書庫 KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456"); //KeyStore trustStore = null; //trustStore為null也可以 OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(getSSLSocketFactory(null, null, trustStore), new DefaultTrustManager()) .hostnameVerifier((s, sslSession) -> true).build(); Request request = new Request.Builder() .url(requestPath).get().build(); Response response = client.newCall(request).execute(); System.out.println("get返回狀態:" + response.code()); System.out.println("get返回結果:" + response.body().string()); response.close(); } /** * 請求自定義證書的地址,需要客戶端證書 * * @throws IOException */ @Test public void test3() throws Exception { String requestPath = "https://10.40.103.48:9016/zsywservice"; //獲取客戶端證書 KeyStore keyStore = getkeyStore("pkcs12", "d:/client.p12", "123456"); //獲取信任證書庫 KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456"); //KeyStore trustStore = null; //trustStore為null也可以 OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(getSSLSocketFactory(keyStore, "123456", trustStore), new DefaultTrustManager()) .hostnameVerifier((s, sslSession) -> true).build(); Request request = new Request.Builder() .url(requestPath).get().build(); Response response = client.newCall(request).execute(); System.out.println("get返回狀態:" + response.code()); System.out.println("get返回結果:" + response.body().string()); response.close(); } /** * 獲取證書 * * @return */ private KeyStore getkeyStore(String type, String filePath, String password) { KeyStore keySotre = null; FileInputStream in = null; try { keySotre = KeyStore.getInstance(type); in = new FileInputStream(new File(filePath)); keySotre.load(in, password.toCharArray()); } catch (Exception e) { e.printStackTrace(); } finally { FileUtil.close(in); } return keySotre; } private SSLSocketFactory getSSLSocketFactory(KeyStore keyStore, String keyStorePassword, KeyStore trustStore) throws Exception { KeyManager[] keyManagers = null; TrustManager[] trustManagers = null; if (keyStore != null) { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); keyManagers = keyManagerFactory.getKeyManagers(); } if (trustStore != null) { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); trustManagerFactory.init(trustStore); trustManagers = trustManagerFactory.getTrustManagers(); } else { trustManagers = new TrustManager[]{new DefaultTrustManager()}; } //設置服務端支持的協議 SSLContext context = SSLContext.getInstance("TLSv1.2"); context.init(keyManagers, trustManagers, null); SSLSocketFactory sslFactory = context.getSocketFactory(); return sslFactory; } private final class DefaultTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }