这篇文章主要介绍“如何使用OkHttp网络请求框架”,在日常操作中,相信很多人在如何使用OkHttp网络请求框架问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用OkHttp网络请求框架”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽。OkHttp是一个优秀的网络请求框架,它有以下默认特性:
支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
连接池减少请求延时
透明的GZIP压缩减少响应数据的大小
缓存响应内容,避免一些完全重复的请求
:@@@. .@@@@@@@: +@@ `@@ @@` @@ @@ .@@@@'@@@@: +@@ `@@ @@` @@ @@ @@@ @@@ +@@ `@@ @@` @@ @@ .@@ @@: +@@ @@@ `@@ @@` @@@@@@ @@@@@@ @@;@@@@@ @@@ @@@ +@@ @@@ `@@ @@` @@@@@@ @@@@@@ @@@@@@@@@ @@@ @@@ +@@ @@@ `@@@@@@@@@@` @@ @@ @@@ :@@ @@@ @@@ +@@@@@ `@@@@@@@@@@` @@ @@ @@# @@+ @@@ @@@ +@@@@@+ `@@ @@` @@ @@ @@: @@# @@: .@@` +@@@+@@ `@@ @@` @@ @@ @@# @@+ @@@. .@@@ +@@ @@@ `@@ @@` @@ @@ @@@ ,@@ @@@@@@@@@ +@@ @@@ `@@ @@` @@@@ @@@@ @@@@#@@@@ @@@@@@@ +@@ #@@ `@@ @@` @@@@: @@@@: @@'@@@@@ @@: @@: @@:
引入maven依赖:
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> <dependency> <groupid>com.squareup.okhttp3</groupid> <artifactid>okhttp</artifactid> <version>${laster.version}</version> </dependency>
OkHttp 项目有如下模块:
模块 | 内容 |
---|---|
okhttp | 实现OkHttp库的模块 |
okhttp-tests | OkHttp库单元测试的模块 |
okhttp-android-support | 支持android平台使用OkHttp库的模块 |
okhttp-apache | 实现ApacheHttpClient接口(下一版本会弃用) |
okhttp-testing-support | 支持单元测试的模块 |
okhttp-urlconnection | 实现HttpURLConnection接口(下一版本会弃用) |
okhttp-ws | 支持WebSocket |
okhttp-logging-interceptor | 实现Logging拦截器 |
okcurl | 实现OkCurl |
mockwebserver | 脚本化WebServer,用于测试HTTP客户端 |
OkHttp 项目父模块中主要包含以下插件:
插件 | 用途 |
---|---|
maven-compiler-plugin | 编译项目 |
maven-surefire-plugin | 执行测试 |
maven-javadoc-plugin | 生成文档 |
maven-release-plugin | 自动化项目版本发布 |
maven-checkstyle-plugin | 检测编码风格 |
animal-sniffer-maven-plugin | 检测代码API |
官方介绍
github源码
使用OkHttp进行Get
请求只需要四步即可完成:
创建okHttpClient对象
OkHttpClient client = new OkHttpClient();
构造Request对象
// 首先构造一个Request对象,参数最起码有个url,当然可以通过Request.Builder设置更多的参数比如:header、method等 Request request = new Request.Builder().get().url("https://api.github.com/users/dllwh").build();
将Request封装为Call
// 通过request的对象去构造得到一个Call对象,类似于将请求封装成了任务 Call call = client.newCall(request);
根据需要调用同步或者异步请求方法
// 同步调用,返回Response,需要这里会抛出IO异常 Response response = call.execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); }
> 同步调用会阻塞主线程,直到 HTTP 响应返回,对应 OKHTTP 中的 execute 方法,一般不适用。
// 以异步的方式去执行请求 call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, final Response response) throws IOException { // http响应行的code,如果访问成功则返回200。这个不是服务器设置的,而是http协议中自带的。 final int httpCode = response.code(); ResponseBody responseBody = response.body(); // 返回的字符串,只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。 final String res = responseBody.string(); // 返回的二进制字节数组 final byte[] bytes = responseBody.bytes(); // 返回的InputStream final InputStream inputStream = responseBody.byteStream(); } });
> 以异步调用的方式去执行非阻塞式请求,它的执行结果一般都是通过接口回调的方式告知调用者,它对应 OKHTTP 中的 enqueue 方法。
很多时候我们会需要通过POST方式把键值对数据传送到服务器,OkHttp提供了很方便的方式来做这件事情。使用OkHttp进行Post
请求和进行Get
请求很类似,只需要五步即可完成:
创建okHttpClient对象
OkHttpClient client = new OkHttpClient();
构建FormBody,传入参数
okhttp3.FormBody.Builder builder = new FormBody.Builder(); builder.add("username", "admin"); builder.add("password", "admin"); FormBody formBody = builder.build();
> post的参数是通过构造一个FormBody
通过键值对的方式来添加进去的,其实post方法需要传入的是一个RequestBody
对象,用它来携带我们要提交的数据,FormBody
是RequestBody
的子类。
构建Request,将FormBody作为Post方法的参数传入
Request request = new Request.Builder().url(url).post(formBody).build();
将Request封装为Call
Call call = client.newCall(request);
根据需要调用同步或者异步请求方法。
// 同步调用,返回Response,它对应 OKHTTP 中的 execute 方法,会抛出IO异常。 Response response = call.execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); }
// 以异步的方式去执行非阻塞式请求,它的执行结果一般都是通过接口回调的方式告知调用者,它对应 OKHTTP 中的 enqueue 方法。 call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, final Response response) throws IOException { if (response.isSuccessful()) { } } });
创建okHttpClient对象
OkHttpClient client = new OkHttpClient();
构建RequestBody,传入参数
MediaType mediaType = MediaType.parse("application/json;charset=UTF-8"); RequestBody requestBody = RequestBody.create(mediaType, "{username:admin;password:admin}");
> 这种方式与前面的区别就是在构造Request对象时,需要多构造一个RequestBody对象,用它来携带我们要提交的数据。在构造 RequestBody
需要指定MediaType
,用于描述请求/响应 body
的内容类型。
构建Request,将FormBody作为Post方法的参数传入
Request request = new Request.Builder().url("http://www.jianshu.com/").post(requestBody).build();
将Request封装为Call
Call call = client.newCall(request);
根据需要调用同步或者异步请求方法。
// 同步调用,返回Response,会抛出IO异常 Response response = call.execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); }
/// 以异步的方式去执行非阻塞式请求,它的执行结果一般都是通过接口回调的方式告知调用者,它对应 OKHTTP 中的 enqueue 方法。 call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, final Response response) throws IOException { if (response.isSuccessful()) { } } });
我们在网页上经常会遇到用户注册的情况,需要你输入用户名、密码(当然还有其他参数,这里仅仅举例说明),这其实就是一个表单,那么接下来我们看看如何利用OkHttp来进行表单提交。经过上面的学习,大家肯定也明白,主要的区别就在于构造不同的RequestBody
传递给post
方法即可。这里我们会用到一个MuiltipartBody
,这是RequestBody
的一个子类,我们提交表单就是利用这个类来构建一个RequestBody
,下面的代码我们会发送一个包含用户民、密码到服务端。
@Test public void doPostForm() throws IOException { OkHttpClient okHttpClient = new OkHttpClient(); okhttp3.MultipartBody.Builder builder = new MultipartBody.Builder(); // 如果提交的是表单,一定要设置这句 builder.setType(MultipartBody.FORM); builder.addFormDataPart("username", "admin"); builder.addFormDataPart("password", "admin"); RequestBody requestBody = builder.build(); Request request = new Request.Builder().url("https://en.wikipedia.org/w/index.php").post(requestBody).build(); Response response = okHttpClient.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } System.out.println(response.body().string()); }
接下来我们在介绍一个可以构造RequestBody的Builder,叫做MultipartBuilder
。当我们需要做类似于表单上传的时候,就可以使用它来构造我们的requestBody。
@Test public void doGetFilePro() { OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response = okHttpClient.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } Headers headers = response.headers(); for (int i = 0; i < headers.size(); i++) { System.out.println(headers.name(i) + ": " + headers.value(i)); } System.out.println(response.body().string()); }
典型的HTTP头就是像是一个 Map<string, string>
,每个字段都有一个或没有值。
当写请求头的时候,使用header(name, value)
可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)
可以添加多值(添加,不移除已有的)。
当读取响应头时,使用header(name)
返回最后出现的name、value。通常情况这也是唯一的name、value。如果没有值,那么header(name)
将返回null。如果想读取字段对应的所有值,使用headers(name)
会返回一个list。
@Test public void doHeader() throws IOException { OkHttpClient okHttpClient = new OkHttpClient(); 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(); Response response = okHttpClient.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")); }
通过上面的例子我们可以发现,OkHttp在很多时候使用都是很方便的,而且很多代码也有重复,而且 OkHttp 官方文档并不建议我们创建多个OkHttpClient,因此全局可以使用一个。
import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import java.io.IOException; import java.util.Map; /** * 把今天最好的表现当作明天最新的起点..~ * <p> * Today the best performance as tomorrow newest starter! * * @类描述: OkHttp 基本使用 * @author: <a href="mailto:duleilewuhen@sina.com">独泪了无痕</a> * @创建时间: 2020-12-22 11:54 * @版本: V 1.0.1 * @since: JDK 1.8 * @see <a href="https://square.github.io/okhttp/">官方介绍</a> */ @Slf4j public final class OkHttpHelper { static ObjectMapper mapper = new ObjectMapper(); /** * 获取操作类 */ private static final OkHttpClient okHttpClient = new OkHttpClient(); private static final String CHARSET_NAME = "UTF-8"; private static final MediaType JSONMediaType = MediaType.parse("application/json;charset=UTF-8"); /** * 同步get方式请求 * * @param url * @return * @throws IOException */ public static String doGet(String url) throws IOException { Request request = new Request.Builder().get().url(url).build(); Call call = okHttpClient.newCall(request); return execute(request); } /** * 异步get方式请求 * * @param url * @return * @throws IOException */ public static void doSyncGet(String url) throws IOException { Request request = new Request.Builder().get().url(url).build(); Call call = okHttpClient.newCall(request); enqueue(request); } /** * 同步post方式请求 */ public static String doPost(String url, Map<string, object> params) throws IOException { RequestBody requestBody = RequestBody.create(JSONMediaType, mapper.writeValueAsString(params)); Request.Builder builder = new Request.Builder(); Request request = builder.url(url).post(requestBody).build(); log.info("do post request and url[{}]", mapper.writeValueAsString(request)); return execute(request); } /** * 同步post方式请求 */ public static String doPost(String url, String params) throws IOException { RequestBody requestBody = RequestBody.create(JSONMediaType, params); Request.Builder builder = new Request.Builder(); Request request = builder.url(url).post(requestBody).build(); log.info("do post request and url[{}]", mapper.writeValueAsString(request)); return execute(request); } /** * 异步post方式请求 */ public static void doSyncPost(String url, String params) { RequestBody body = RequestBody.create(JSONMediaType, params); Request request = new Request.Builder().url(url).post(body).build(); enqueue(request); } public static String doPostJSON(String url, Map<string, object> params, Headers headers) throws IOException { RequestBody requestBody = RequestBody.create(JSONMediaType, mapper.writeValueAsString(params)); Request.Builder builder = new Request.Builder(); Request request = builder.url(url).post(requestBody).headers(headers).build(); log.info("do post request and url[{}]", mapper.writeValueAsString(request)); return execute(request); } /** * 同步请求,不会开始异步线程 * * @param request * @return * @throws IOException */ private static String execute(Request request) throws IOException { log.info("请求开始:请求地址为:{}", request.url()); Response response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { String res = response.body().string(); log.info("请求返回:{}", res); return res; } else { throw new IOException("Unexpected code " + response); } } /** * 开启异步线程访问 * * @param request * @param responseCallback */ public static void enqueue(Request request, Callback responseCallback) { okHttpClient.newCall(request).enqueue(responseCallback); } /** * 开启异步线程访问网络, 且不在意返回结果(实现空callback) * * @param request */ private static void enqueue(Request request) { okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { log.error("",e); } @Override public void onResponse(Call call, Response response) throws IOException {ßß if (response.isSuccessful()) { log.info("Successful data acquisition . . . "); log.info("response.code()==" + response.code()); log.info("response.body().string()==" + response.body().string()); } } }); } }
到此,关于“如何使用OkHttp网络请求框架”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。