南京 网站开发什么待遇啊wordpress电脑安装教程视频
一、概述
HTTP是现代应用程序网络的方式。这就是我们交换数据和媒体的方式。执行 HTTP 有效地使您的资料加载速度更快并节省带宽。
OkHttp 是一个默认高效的 HTTP 客户端:
- HTTP/2 支持允许对同一主机的所有请求共享一个套接字。
- 连接池可减少请求延迟(如果 HTTP/2 不可用)。
- 透明 GZIP 可缩小下载大小。
- 响应缓存完全避免了重复请求的网络。
OkHttp在网络出现问题时坚持不懈:它将从公共连接中静默恢复 问题。如果您的服务有多个 IP 地址,OkHttp 将尝试备用地址,如果 首次连接失败。这对于 IPv4+IPv6 和托管在冗余数据中的服务是必需的。 中心。OkHttp支持现代TLS功能(TLS 1.3,ALPN,证书固定)。它可以是 配置为回退以实现广泛的连接。
使用OkHttp很容易。它的请求/响应 API 设计有流畅的构建器和不变性。它 支持同步阻塞调用和带回调的异步调用。
1、引入依赖
目前比较推荐的版本:
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version></dependency>
二、方法
我们编写了一些方法,演示如何使用 OkHttp 解决常见问题。通读它们,了解一切如何协同工作。
Synchronous Get
下载一个文件,打印其标题,并将其响应体打印为字符串。
响应体上的string()方法对于小型文档来说既方便又高效。但是,如果响应主体很大(大于1MIB),请避免字符串(),因为它会将整个文档加载到内存中。在这种情况下,更倾向于将主体作为流进行处理。
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来分部分接收响应主体。
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());}}});}
Accessing Headers
通常,HTTP头的工作方式类似于Map<String,String>:每个字段都有一个值或没有值。但有些标头允许多个值,如Guava的Multimap。例如,HTTP响应提供多个Vary标头是合法且常见的。OkHttp的API试图让这两种情况都变得舒适。
在写入请求标头时,使用标头(name,value)将唯一出现的name设置为value。如果存在现有值,则在添加新值之前,这些值将被删除。使用addHeader(name,value)添加标头,而不删除已存在的标头。
读取响应标头时,使用标头(名称)返回命名值的最后一次出现。通常这也是唯一的情况!如果不存在任何值,则标头(名称)将返回null。要将字段的所有值作为列表读取,请使用标头(名称)。
要访问所有标头,请使用支持按索引访问的headers类。
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文档发布到web服务,该web服务将markdown呈现为HTML。因为整个请求主体同时在内存中,所以避免使用此API发布大型(大于1MIB)文档。
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 Streaming
在这里,我们将请求主体作为流进行POST。这个请求主体的内容是在编写过程中生成的。此示例直接流式传输到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());}}
Posting a File
使用文件作为请求主体很容易。
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());}}
Posting form parameters
使用FormBody.Builder构建一个类似于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());}}
三、开发示例
准备工作
Maven项目在pom文件中引入jar包:
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.2</version>
</dependency>
工具类代码
import okhttp3.*;import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;public class OkHttpUtils {private static volatile OkHttpClient okHttpClient = null;private static volatile Semaphore semaphore = null;private Map<String, String> headerMap;private Map<String, String> paramMap;private String url;private Request.Builder request;/*** 初始化okHttpClient,并且允许https访问*/private OkHttpUtils() {if (okHttpClient == null) {synchronized (OkHttpUtils.class) {if (okHttpClient == null) {TrustManager[] trustManagers = buildTrustManagers();okHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS).writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS).sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0]).hostnameVerifier((hostName, session) -> true).retryOnConnectionFailure(true).build();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");}}}}/*** 用于异步请求时,控制访问线程数,返回结果** @return*/private static Semaphore getSemaphoreInstance() {//只能1个线程同时访问synchronized (OkHttpUtils.class) {if (semaphore == null) {semaphore = new Semaphore(0);}}return semaphore;}/*** 创建OkHttpUtils** @return*/public static OkHttpUtils builder() {return new OkHttpUtils();}/*** 添加url** @param url* @return*/public OkHttpUtils url(String url) {this.url = url;return this;}/*** 添加参数* * @param key 参数名* @param value 参数值* @return*/public OkHttpUtils addParam(String key, String value) {if (paramMap == null) {paramMap = new LinkedHashMap<>(16);}paramMap.put(key, value);return this;}/*** 添加请求头** @param key 参数名* @param value 参数值* @return*/public OkHttpUtils addHeader(String key, String value) {if (headerMap == null) {headerMap = new LinkedHashMap<>(16);}headerMap.put(key, value);return this;}/*** 初始化get方法** @return*/public OkHttpUtils get() {request = new Request.Builder().get();StringBuilder urlBuilder = new StringBuilder(url);if (paramMap != null) {urlBuilder.append("?");try {for (Map.Entry<String, String> entry : paramMap.entrySet()) {urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).append("=").append(URLEncoder.encode(entry.getValue(), "utf-8")).append("&");}} catch (Exception e) {e.printStackTrace();}urlBuilder.deleteCharAt(urlBuilder.length() - 1);}request.url(urlBuilder.toString());return this;}/*** 初始化post方法** @param isJsonPost true等于json的方式提交数据,类似postman里post方法的raw* false等于普通的表单提交* @return*/public OkHttpUtils post(boolean isJsonPost) {RequestBody requestBody;if (isJsonPost) {String json = "";if (paramMap != null) {json = JSON.toJSONString(paramMap);} requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);} else {FormBody.Builder formBody = new FormBody.Builder();if (paramMap != null) {paramMap.forEach(formBody::add);}requestBody = formBody.build();}request = new Request.Builder().post(requestBody).url(url);return this;}/*** 同步请求** @return*/public String sync() {setHeader(request);try {Response response = okHttpClient.newCall(request.build()).execute();assert response.body() != null;return response.body().string();} catch (IOException e) {e.printStackTrace();return "请求失败:" + e.getMessage();}}/*** 异步请求,有返回值*/public String async() {StringBuilder buffer = new StringBuilder("");setHeader(request);okHttpClient.newCall(request.build()).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {buffer.append("请求出错:").append(e.getMessage());}@Overridepublic void onResponse(Call call, Response response) throws IOException {assert response.body() != null;buffer.append(response.body().string());getSemaphoreInstance().release();}});try {getSemaphoreInstance().acquire();} catch (InterruptedException e) {e.printStackTrace();}return buffer.toString();}/*** 异步请求,带有接口回调** @param callBack*/public void async(ICallBack callBack) {setHeader(request);okHttpClient.newCall(request.build()).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {callBack.onFailure(call, e.getMessage());}@Overridepublic void onResponse(Call call, Response response) throws IOException {assert response.body() != null;callBack.onSuccessful(call, response.body().string());}});}/*** 为request添加请求头** @param request*/private void setHeader(Request.Builder request) {if (headerMap != null) {try {for (Map.Entry<String, String> entry : headerMap.entrySet()) {request.addHeader(entry.getKey(), entry.getValue());}} catch (Exception e) {e.printStackTrace();}}}/*** 生成安全套接字工厂,用于https请求的证书跳过** @return*/private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {SSLSocketFactory ssfFactory = null;try {SSLContext sc = SSLContext.getInstance("SSL");sc.init(null, trustAllCerts, new SecureRandom());ssfFactory = sc.getSocketFactory();} catch (Exception e) {e.printStackTrace();}return ssfFactory;}private static TrustManager[] buildTrustManagers() {return new TrustManager[]{new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}}};}/*** 自定义一个接口回调*/public interface ICallBack {void onSuccessful(Call call, String data);void onFailure(Call call, String errorMsg);}
}
调用代码:
public static void main(String[] args) {// get请求,方法顺序按照这种方式,切记选择post/get一定要放在倒数第二,同步或者异步倒数第一,才会正确执行OkHttpUtils.builder().url("请求地址,http/https都可以")// 有参数的话添加参数,可多个.addParam("参数名", "参数值").addParam("参数名", "参数值")// 也可以添加多个.addHeader("Content-Type", "application/json; charset=utf-8").get()// 可选择是同步请求还是异步请求//.async();.sync();// post请求,分为两种,一种是普通表单提交,一种是json提交OkHttpUtils.builder().url("请求地址,http/https都可以")// 有参数的话添加参数,可多个.addParam("参数名", "参数值").addParam("参数名", "参数值")// 也可以添加多个.addHeader("Content-Type", "application/json; charset=utf-8")// 如果是true的话,会类似于postman中post提交方式的raw,用json的方式提交,不是表单// 如果是false的话传统的表单提交.post(true).sync();// 选择异步有两个方法,一个是带回调接口,一个是直接返回结果OkHttpUtils.builder().url("").post(false).async();OkHttpUtils.builder().url("").post(false).async(new OkHttpUtils.ICallBack() {@Overridepublic void onSuccessful(Call call, String data) {// 请求成功后的处理}@Overridepublic void onFailure(Call call, String errorMsg) {// 请求失败后的处理}});
}
OkHttp3 详解及开发实例—官方原版(二)