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 }