这篇文章主要介绍“如何使用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网络请求框架”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/dllwh/blog/4868717