Java【okhttp3】

1、添加依赖

1  <dependecies>
2    <dependency>
3        <groupId>com.squareup.okhttp3</groupId>
4        <artifactId>okhttp</artifactId>
5        <version>4.9.0</version>
6     </dependency>
7  </dependencies>

2、实例化OkHttpClient

1 //方式一:创建OkHttpClient实例,使用默认构造函数,创建默认配置OkHttpClient(官方建议全局只有一个实例)
2 OkHttpClient okHttpClient = new OkHttpClient();
3 //方式二:使用静态内部类
4 OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(13, TimeUnit.SECONDS).build();
5 //方式三:使用实例方法newBuilder(), 其实也是使用的静态内部类
6 OkHttpClient okHttpClient2 = new OkHttpClient();
7 OkHttpClient client = okHttpClient2.newBuilder().build();

3、设置超时

1 OkHttpClient okHttpClient = new OkHttpClient.Builder()
2         .connectTimeout(2, TimeUnit.SECONDS)
3         .writeTimeout(2, TimeUnit.SECONDS)
4         .readTimeout(2, TimeUnit.SECONDS)
5         .build();

4、设置连接池

1 OkHttpClient okHttpClient = new OkHttpClient.Builder()
2         // 参数1:最大连接数
3         // 参数2:连接存活的时间
4         // 参数3:连接存活的时间单位
5         .connectionPool(new ConnectionPool(10, 10, TimeUnit.MINUTES))
6         .build();

5、设置缓存

  OkHttp3具有一个高效、自动化的缓存模式。缓存默认可以减少网络请求延迟,提高应用性能和用户体验

1 OkHttpClient okHttpClient = new OkHttpClient.Builder()
2         // 参数1:缓存文件
3         // 参数2:缓存大小, 10 * 1024 * 1024 = 10M
4         .cache(new Cache(new File("/home/work/cache.tmp"), 10 * 1024 * 1024))
5         .build();

6、https支持

 1 private static TrustManager[] buildTrustManagers() {
 2     return new TrustManager[]{
 3             new X509TrustManager() {
 4                 @Override
 5                 public void checkClientTrusted(X509Certificate[] chain, String authType) {
 6                 }
 7 
 8                 @Override
 9                 public void checkServerTrusted(X509Certificate[] chain, String authType) {
10                 }
11 
12                 @Override
13                 public X509Certificate[] getAcceptedIssuers() {
14                     return new X509Certificate[]{};
15                 }
16             }
17     };
18 }
19 
20 /**
21  * 生成安全套接字工厂,用于https请求的证书跳过
22  */
23 private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
24     SSLSocketFactory ssfFactory = null;
25     try {
26         SSLContext sc = SSLContext.getInstance("SSL");
27         sc.init(null, trustAllCerts, new SecureRandom());
28         ssfFactory = sc.getSocketFactory();
29     } catch (Exception e) {
30         e.printStackTrace();
31     }
32     return ssfFactory;
33 }
34 
35 TrustManager[] trustManagers = buildTrustManagers();
36 OkHttpClient client = new OkHttpClient.Builder()
37         // 跳过ssl认证(https)
38         .sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
39         .hostnameVerifier((hostname, session) -> true)
40         .build();

7、同步发送get请求

 1 try {
 2     OkHttpClient client = new OkHttpClient();
 3     Request request = new Request.Builder().url("https://www.baidu.com").get().build();
 4     Response response = client.newCall(request).execute();
 5     // 响应状态码
 6     int code = response.code();
 7     // 响应body
 8     ResponseBody body = response.body();
 9     // 响应body1: 字符串, 当响应内容比较小的时候使用, 响应内容太大最好使用后面的方式, 因为该方法会将内容全部加载到内容
10     String str = body.string();
11     // 响应body2: 字节数组
12     byte[] bytes = body.bytes();
13     // 响应body3: 字符流
14     Reader reader = body.charStream();
15     // 响应body4: 字节流
16     InputStream stream = body.byteStream();
17 } catch (IOException e) {
18     e.printStackTrace();
19 }

8、异步发送get请求

 1 OkHttpClient client = new OkHttpClient();
 2 Request request = new Request.Builder().url("https://www.baidu.com").get().build();
 3 client.newCall(request).enqueue(new Callback() {
 4     @Override
 5     public void onFailure(Call call, IOException e) {
 6         
 7     }
 8 
 9     @Override
10     public void onResponse(Call call, Response response) throws IOException {
11         String result = response.body().string();
12         System.out.println(result);
13     }
14 });
常见的类型:
  • application/x-www-form-urlencoded 数据是个普通表单;
  • multipart/form-data                           数据里有文件;
  • application/json                                 数据是个json。

9、发送post请求,参数为类型为 application/json

 1 try {
 2     OkHttpClient client = new OkHttpClient();
 3     /**
 4      * 构建RequestBody常用的三种方法
 5      * public static RequestBody create(@Nullable MediaType contentType, String content)
 6      * public static RequestBody create(@Nullable MediaType contentType, byte[] content)
 7      * public static RequestBody create(@Nullable final MediaType contentType, final File file)
 8      */
 9     // 构建请求参数
10     HashMap<String, String> param = new HashMap<>();
11     param.put("name", "zhangsan");
12     // 设置参数类型
13     MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
14     RequestBody requestBody = RequestBody.create(mediaType, JSON.toJSONString(param));
15 
16     Request request = new Request.Builder().url("https://xxxx").post(requestBody).build();
17     Response response = client.newCall(request).execute();
18     System.out.println(response.body().string());
19 } catch (IOException e) {
20     e.printStackTrace();
21 }

10、发送post请求,参数类型为application/x-www-form-urlencoded

 1 try {
 2     OkHttpClient client = new OkHttpClient();
 3     // 构建表单body
 4     FormBody.Builder builder  = new FormBody.Builder();
 5     builder.add("name", "zhangsan");
 6     FormBody formBody = builder.build();
 7     
 8     Request request = new Request.Builder().url("https://xxxx").post(formBody).build();
 9     Response response = client.newCall(request).execute();
10     System.out.println(response.body().string());
11 } catch (IOException e) {
12     e.printStackTrace();
13 }

11、发送post请求,参数类型为multipart/form-data,指定文件路径

  Content-Type参照表:http://tools.jb51.net/table/http_content_type

 1 try {
 2     OkHttpClient client = new OkHttpClient();
 3     // 构建带文件的body
 4     MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
 5     // 键值参数
 6     builder.addFormDataPart("name", "zhangsan");
 7     // 文件, 二进制流数据 application/octet-stream, 不关注文件的扩展类型
 8     // 不同类型文件对应的Content-Type:  http://tools.jb51.net/table/http_content_type
 9     RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), new File("/home/work/1.txt"));  // 可以参照上面连接中的文件扩展对应的Content-Type进行MediaType的设置
10     builder.addFormDataPart("file", "1.txt", requestBody);
11     MultipartBody multipartBody = builder.build();
12     Request request = new Request.Builder().url("https://xxxx").post(multipartBody).build();
13     Response response = client.newCall(request).execute();
14     System.out.println(response.body().string());
15 } catch (IOException e) {
16     e.printStackTrace();
17 }

12、发送post请求,参数类型为multipart/form-data,指定字节数组

 1 try {
 2     OkHttpClient client = new OkHttpClient();
 3 
 4     MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
 5     builder.addFormDataPart("name", "zhangsan");
 6     RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), new byte[]{1, 2, 3}); // 此处可以是将文件内容读取转成byte[]
 7     builder.addFormDataPart("file", "1.txt", requestBody);
 8     MultipartBody multipartBody = builder.build();
 9 
10     Request request = new Request.Builder().url("https://xxxx").post(multipartBody).build();
11     Response response = client.newCall(request).execute();
12     System.out.println(response.body().string());
13 } catch (IOException e) {
14     e.printStackTrace();
15 }

 13、登录验证

 1 try {
 2     OkHttpClient okHttpClient =
 3             new OkHttpClient
 4                     .Builder()
 5                     .authenticator(new Authenticator() {
 6                         public Request authenticate(Route route, Response response) throws IOException {
 7                             System.out.println(response.challenges().toString());
 8                             String credential = Credentials.basic("jesse", "password1");
 9                             return response
10                                     .request()
11                                     .newBuilder()
12                                     .addHeader("Authorization", credential)
13                                     .build();
14                         }
15                     })
16                     .build();
17     Request request = new Request.Builder().url("http://xxxx").build();
18     Response response = okHttpClient.newCall(request).execute();
19     if (response.isSuccessful() && response.body() != null) {
20         System.out.println(response.body().string());
21     }
22 } catch (IOException e) {
23     e.printStackTrace();
24 }

14、请求携带cookie

  自动存储和携带cookie

 1 Map<String, List<Cookie>> cookieStore = new HashMap<>();
 2 try {
 3     OkHttpClient okHttpClient =
 4             new OkHttpClient
 5                     .Builder()
 6                     .cookieJar(new CookieJar() {
 7                         @Override
 8                         public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
 9                             cookieStore.put(httpUrl.host(), list);
10                         }
11 
12                         @Override
13                         public List<Cookie> loadForRequest(HttpUrl httpUrl) {
14                             List<Cookie> cookies = cookieStore.get(httpUrl.host());
15                             return cookies != null ? cookies : Collections.emptyList();
16                         }
17                     })
18                     .build();
19     Request request = new Request.Builder().url("http://xxxx").build();
20     Response response = okHttpClient.newCall(request).execute();
21     if (response.isSuccessful() && response.body() != null) {
22         System.out.println(response.body().string());
23     }
24 } catch (IOException e) {
25     e.printStackTrace();
26 }

 

工具类

  1 import okhttp3.*;
  3 import javax.net.ssl.SSLContext;
  4 import javax.net.ssl.SSLSocketFactory;
  5 import javax.net.ssl.TrustManager;
  6 import javax.net.ssl.X509TrustManager;
  7 import java.io.File;
  8 import java.io.FileOutputStream;
  9 import java.io.IOException;
 10 import java.io.InputStream;
 11 import java.net.URLEncoder;
 12 import java.security.SecureRandom;
 13 import java.security.cert.X509Certificate;
 14 import java.util.LinkedHashMap;
 15 import java.util.Map;
 16 import java.util.concurrent.Semaphore;
 17 import java.util.concurrent.TimeUnit;
 18 
 19 public class OkHttpUtils2 {
 20     private static volatile OkHttpClient okHttpClient = null;
 21     private static volatile Semaphore semaphore = null;
 22     private Map<String, String> headerMap;
 23     private Map<String, String> paramMap;
 24     private String url;
 25     private Request.Builder request;
 27 
 28     /**
 29      * 初始化okHttpClient,并且允许https访问
 30      */
 31     private OkHttpUtils2() {
 32         if (okHttpClient == null) {
 33             synchronized (OkHttpUtils2.class) {
 34                 if (okHttpClient == null) {
 35                     TrustManager[] trustManagers = buildTrustManagers();
 36                     okHttpClient = new OkHttpClient.Builder()
 37                             // 设置连接超时时间
 38                             .connectTimeout(60, TimeUnit.SECONDS)
 39                             // 写入超时时间
 40                             .writeTimeout(60, TimeUnit.SECONDS)
 41                             // 从连接成功到响应的总时间
 42                             .readTimeout(60, TimeUnit.SECONDS)
 43                             // 跳过ssl认证(https)
 44                             .sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
 45                             .hostnameVerifier((hostName, session) -> true)
 46                             .retryOnConnectionFailure(true)
 47                             // 设置连接池最大连接数量, 持续存活的连接
 48                             .connectionPool(new ConnectionPool(10, 10, TimeUnit.MINUTES))
 49                             .build();
 50                     addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
 51                 }
 52             }
 53         }
 54     }
 55 
 56     /**
 57      * 用于异步请求时,控制访问线程数,返回结果
 58      */
 59     private static Semaphore getSemaphoreInstance() {
 60         // 只能1个线程同时访问
 61         synchronized (OkHttpUtils2.class) {
 62             if (semaphore == null) {
 63                 semaphore = new Semaphore(0);
 64             }
 65         }
 66         return semaphore;
 67     }
 68 
 69     /**
 70      * 创建OkHttpUtils
 71      */
 72     public static OkHttpUtils2 builder() {
 73         return new OkHttpUtils2();
 74     }
 75 
 76     /**
 77      * 添加url
 78      */
 79     public OkHttpUtils2 url(String url) {
 80         this.url = url;
 81         return this;
 82     }
 83 
 84     /**
 85      * 添加参数
 86      */
 87     public OkHttpUtils2 addParam(String key, String value) {
 88         if (paramMap == null) {
 89             paramMap = new LinkedHashMap<>(16);
 90         }
 91         paramMap.put(key, value);
 92         return this;
 93     }
 94 
 95     /**
 96      * 添加请求头
 97      */
 98     public OkHttpUtils2 addHeader(String key, String value) {
 99         if (headerMap == null) {
100             headerMap = new LinkedHashMap<>(16);
101         }
102         headerMap.put(key, value);
103         return this;
104     }
105 
106     /**
107      * GET
108      */
109     public OkHttpUtils2 get() {
110         request = new Request.Builder().get();
111         StringBuilder urlBuilder = new StringBuilder(url);
112         if (paramMap != null) {
113             urlBuilder.append("?");
114             try {
115                 for (Map.Entry<String, String> entry : paramMap.entrySet()) {
116                     urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).
117                             append("=").
118                             append(URLEncoder.encode(entry.getValue(), "utf-8")).
119                             append("&");
120                 }
121             } catch (Exception e) {
122                 e.printStackTrace();
123             }
124             urlBuilder.deleteCharAt(urlBuilder.length() - 1);
125         }
126         request.url(urlBuilder.toString());
127         return this;
128     }
129 
130     /**
131      * POST -> application/json; charset=utf-8
132      */
133     public OkHttpUtils post() {
134         RequestBody requestBody;
135         String json = "{}";
136         if (paramMap != null) {
137             json = JSON.toJSONString(paramMap);
138         }
139         requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
140         request = new Request.Builder().post(requestBody).url(url);
141         return this;
142     }
143 
144     /**
145      * POST -> application/x-www-form-urlencoded
146      */
147     public OkHttpUtils2 postForm() {
148         FormBody.Builder formBody = new FormBody.Builder();
149         if (paramMap != null) {
150             paramMap.forEach(formBody::add);
151         }
152         RequestBody requestBody = formBody.build();
153         request = new Request.Builder().post(requestBody).url(url);
154         return this;
155     }
156 
157     /**
158      * POST -> multipart/form-data
159      */
160     public OkHttpUtils2 postFormData(String fileName, byte[] content) {
161         MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
162 
163         // 表单
164         if (content != null) {
165             builder.addFormDataPart("file", fileName, RequestBody.create(MediaType.parse("application/octet-stream"), content));
166         }
167 
168         for (Map.Entry<String, String> entry : paramMap.entrySet()) {
169             builder.addFormDataPart(entry.getKey(), entry.getValue());
170         }
171 
172         RequestBody requestBody = builder.build();
173         request = new Request.Builder().post(requestBody).url(url);
174         return this;
175     }
176 
177     /**
178      * POST -> multipart/form-data
179      */
180     public OkHttpUtils2 postFormData(String fileName, File file) {
181         MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
182 
183         if (file != null) {
184             builder.addFormDataPart("file", fileName, RequestBody.create(MediaType.parse("application/octet-stream"), file));
185         }
186         for (Map.Entry<String, String> entry : paramMap.entrySet()) {
187             builder.addFormDataPart(entry.getKey(), entry.getValue());
188         }
189 
190         RequestBody requestBody = builder.build();
191         request = new Request.Builder().post(requestBody).url(url);
192         return this;
193     }
194 
195     /**
196      * 同步请求
197      */
198     public String sync() {
199         setHeader(request);
200         try {
201             Response response = okHttpClient.newCall(request.build()).execute();
202             if (response.code() != 200) {
203                 return null;
204             }
205             return response.body().string();
206         } catch (IOException e) {
207             e.printStackTrace();
208             return null;
209         }
210     }
211 
212     public byte[] syncDownload() {
213         setHeader(request);
214         try {
215             Response response = okHttpClient.newCall(request.build()).execute();
216             if (response.code() != 200) {
217                 return null;
218             }
219             return response.body().bytes();
220         } catch (IOException e) {
221             e.printStackTrace();
222             return null;
223         }
224     }
225 
226     public void syncDownload(String filePath) {
227         setHeader(request);
228         InputStream is = null;
229         byte[] b = new byte[2048];
230         int len;
231         FileOutputStream fos = null;
232         try {
233             Response response = okHttpClient.newCall(request.build()).execute();
234             if (response.code() != 200) {
235                 return;
236             }
237             is = response.body().byteStream();
238             File file = new File(filePath);
239             if (!file.exists() && !file.getParentFile().exists()) {
240                 file.getParentFile().mkdirs();
241             }
242             fos = new FileOutputStream(filePath);
243             while ((len = is.read(b)) != -1) {
244                 fos.write(b, 0, len);
245             }
246             fos.flush();
247         } catch (IOException e) {
248             e.printStackTrace();
249         } finally {
250             try {
251                 if (is != null) {
252                     is.close();
253                 }
254                 if (fos != null) {
255                     fos.close();
256                 }
257             } catch (IOException e) {
258                 e.printStackTrace();
259             }
260         }
261     }
262 
263     /**
264      * 异步请求,有返回值
265      */
266     public String async() {
267         StringBuilder buffer = new StringBuilder("");
268         setHeader(request);
269         okHttpClient.newCall(request.build()).enqueue(new Callback() {
270             @Override
271             public void onFailure(Call call, IOException e) {
272                 buffer.append("请求出错:").append(e.getMessage());
273             }
274 
275             @Override
276             public void onResponse(Call call, Response response) throws IOException {
277                 assert response.body() != null;
278                 buffer.append(response.body().string());
279                 getSemaphoreInstance().release();
280             }
281         });
282         try {
283             getSemaphoreInstance().acquire();
284         } catch (InterruptedException e) {
285             e.printStackTrace();
286         }
287         return buffer.toString();
288     }
289 
290     /**
291      * 异步请求,带有接口回调
292      */
293     public void async(ICallBack callBack) {
294         setHeader(request);
295         okHttpClient.newCall(request.build()).enqueue(new Callback() {
296             @Override
297             public void onFailure(Call call, IOException e) {
298                 callBack.onFailure(call, e.getMessage());
299             }
300 
301             @Override
302             public void onResponse(Call call, Response response) throws IOException {
303                 assert response.body() != null;
304                 callBack.onSuccessful(call, response.body().string());
305             }
306         });
307     }
308 
309     /**
310      * 为request添加请求头
311      */
312     private void setHeader(Request.Builder request) {
313         if (headerMap != null) {
314             try {
315                 for (Map.Entry<String, String> entry : headerMap.entrySet()) {
316                     request.addHeader(entry.getKey(), entry.getValue());
317                 }
318             } catch (Exception e) {
319                 e.printStackTrace();
320             }
321         }
322     }
323 
324     /**
325      * 生成安全套接字工厂,用于https请求的证书跳过
326      */
327     private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
328         SSLSocketFactory ssfFactory = null;
329         try {
330             SSLContext sc = SSLContext.getInstance("SSL");
331             sc.init(null, trustAllCerts, new SecureRandom());
332             ssfFactory = sc.getSocketFactory();
333         } catch (Exception e) {
334             e.printStackTrace();
335         }
336         return ssfFactory;
337     }
338 
339     private static TrustManager[] buildTrustManagers() {
340         return new TrustManager[]{
341                 new X509TrustManager() {
342                     @Override
343                     public void checkClientTrusted(X509Certificate[] chain, String authType) {
344                     }
345 
346                     @Override
347                     public void checkServerTrusted(X509Certificate[] chain, String authType) {
348                     }
349 
350                     @Override
351                     public X509Certificate[] getAcceptedIssuers() {
352                         return new X509Certificate[]{};
353                     }
354                 }
355         };
356     }
357 
358     /**
359      * 自定义一个接口回调
360      */
361     public interface ICallBack {
362         void onSuccessful(Call call, String data);
363 
364         void onFailure(Call call, String errorMsg);
365     }
366 }

 

posted @ 2023-08-11 16:01  为你编程  阅读(107)  评论(0编辑  收藏  举报