一、okhttp3 简介
okhttp3 是一个高效的 http 客户端,由 square 公司开发,具有以下核心特点:
- 连接池 - 减少请求延迟,支持http/2和spdy
- 透明gzip压缩 - 自动压缩请求体,减少数据传输量
- 响应缓存 - 避免重复网络请求
- 自动重试 - 处理瞬时故障和网络问题
- 异步/同步支持 - 灵活的调用方式
二、使用示例
准备工作
引入依赖:
<dependency>
<groupid>com.squareup.okhttp3</groupid>
<artifactid>okhttp</artifactid>
<version>4.12.0</version>
</dependency>创建okhttpclient实例
import okhttp3.*;
import java.io.ioexception;
import java.util.concurrent.timeunit;
public class okhttpexample {
// 创建全局okhttpclient实例
private static final okhttpclient client = new okhttpclient.builder()
.connecttimeout(10, timeunit.seconds)
.readtimeout(30, timeunit.seconds)
.writetimeout(30, timeunit.seconds)
.addinterceptor(new logginginterceptor()) // 添加日志拦截器
.build();
// 简单的日志拦截器
static class logginginterceptor implements interceptor {
@override
public response intercept(chain chain) throws ioexception {
request request = chain.request();
long starttime = system.nanotime();
system.out.println(string.format("sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
response response = chain.proceed(request);
long endtime = system.nanotime();
system.out.println(string.format("received response for %s in %.1fms%n%s",
response.request().url(), (endtime - starttime) / 1e6d, response.headers()));
return response;
}
}
}1.发送get请求
下面的示例涵盖普通get请求,带查询参数的get请求和带请求头的get请求。
public class getrequestexample {
public static void basicgetrequest() throws ioexception {
string url = "https://jsonplaceholder.typicode.com/posts/1";
request request = new request.builder()
.url(url)
.get() // 显式声明get方法,可选
.build();
try (response response = client.newcall(request).execute()) {
if (!response.issuccessful()) {
throw new ioexception("unexpected code: " + response);
}
string responsebody = response.body().string();
system.out.println("response: " + responsebody);
}
}
// 带查询参数的get请求
public static void getwithqueryparams() throws ioexception {
httpurl url = httpurl.parse("https://jsonplaceholder.typicode.com/posts")
.newbuilder()
.addqueryparameter("userid", "1")
.addqueryparameter("_limit", "5")
.build();
request request = new request.builder()
.url(url)
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("response: " + response.body().string());
}
}
// 带请求头的get请求
public static void getwithheaders() throws ioexception {
request request = new request.builder()
.url("https://api.github.com/users/octocat")
.addheader("user-agent", "okhttp-example")
.addheader("accept", "application/vnd.github.v3+json")
.addheader("authorization", "bearer your-token-here")
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("response: " + response.body().string());
}
}
}2. 发送post请求
下面的示例涵盖,发送json数据,表单数据和文件上传的post请求
public class postrequestexample {
// post json数据
public static void postjson() throws ioexception {
string json = "{\"title\":\"foo\",\"body\":\"bar\",\"userid\":1}";
requestbody body = requestbody.create(
json,
mediatype.parse("application/json; charset=utf-8")
);
request request = new request.builder()
.url("https://jsonplaceholder.typicode.com/posts")
.post(body)
.addheader("content-type", "application/json")
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("response: " + response.body().string());
}
}
// 发送表单数据
public static void postform() throws ioexception {
requestbody formbody = new formbody.builder()
.add("username", "john_doe")
.add("password", "secret123")
.add("grant_type", "password")
.build();
request request = new request.builder()
.url("https://httpbin.org/post")
.post(formbody)
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("response: " + response.body().string());
}
}
// 发送multipart表单(文件上传)
public static void postmultipart() throws ioexception {
requestbody requestbody = new multipartbody.builder()
.settype(multipartbody.form)
.addformdatapart("title", "my file")
.addformdatapart("file", "filename.txt",
requestbody.create("file content", mediatype.parse("text/plain")))
.addformdatapart("image", "image.jpg",
requestbody.create(new byte[]{/* 图片数据 */}, mediatype.parse("image/jpeg")))
.build();
request request = new request.builder()
.url("https://httpbin.org/post")
.post(requestbody)
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("response: " + response.body().string());
}
}
}3.发送put请求
public static void putrequest() throws ioexception {
string json = "{\"id\":1,\"title\":\"updated title\",\"body\":\"updated body\",\"userid\":1}";
requestbody body = requestbody.create(
json,
mediatype.parse("application/json; charset=utf-8")
);
request request = new request.builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.put(body)
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("put response: " + response.body().string());
}
}4.发送patch请求
patch 请求用于对资源进行部分更新,与 put(全量更新)不同,patch 只更新提供的字段。
public static void patchrequest() throws ioexception {
string json = "{\"title\":\"patched title\"}";
requestbody body = requestbody.create(
json,
mediatype.parse("application/json; charset=utf-8")
);
request request = new request.builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.patch(body)
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("patch response: " + response.body().string());
}
}5.发送delete请求
public static void deleterequest() throws ioexception {
request request = new request.builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.delete()
.build();
try (response response = client.newcall(request).execute()) {
system.out.println("delete response: " + response.body().string());
}
}6.发送异步请求
public class asyncrequestexample {
public static void asyncgetrequest() {
request request = new request.builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.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 {
if (!response.issuccessful()) {
throw new ioexception("unexpected code: " + response);
}
string responsebody = response.body().string();
system.out.println("async response: " + responsebody);
// 注意:在异步回调中需要手动关闭response body
response.close();
}
});
system.out.println("request sent asynchronously...");
}
// 多个异步请求并行执行
public static void multipleasyncrequests() {
string[] urls = {
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
};
for (string url : urls) {
request request = new request.builder().url(url).build();
client.newcall(request).enqueue(new callback() {
@override
public void onfailure(call call, ioexception e) {
system.err.println("request failed: " + e.getmessage());
}
@override
public void onresponse(call call, response response) throws ioexception {
if (response.issuccessful()) {
system.out.println("response from " + call.request().url() + ": " +
response.body().string().substring(0, 50) + "...");
}
response.close();
}
});
}
}
}7.高级功能和配置
涵盖:添加认证token、重试拦截器、下载文件和使用cookie
public class advancedfeatures {
// 自定义配置的client
private static final okhttpclient customclient = new okhttpclient.builder()
.connecttimeout(15, timeunit.seconds)
.readtimeout(30, timeunit.seconds)
.writetimeout(30, timeunit.seconds)
.addinterceptor(chain -> {
// 添加认证token
request original = chain.request();
request authenticated = original.newbuilder()
.header("authorization", "bearer " + getauthtoken())
.build();
return chain.proceed(authenticated);
})
.addinterceptor(chain -> {
// 重试拦截器
int maxretries = 3;
int retrycount = 0;
response response = null;
while (retrycount < maxretries) {
try {
response = chain.proceed(chain.request());
if (response.issuccessful() || retrycount == maxretries - 1) {
break;
}
} catch (ioexception e) {
if (retrycount == maxretries - 1) {
throw e;
}
}
retrycount++;
system.out.println("retrying request, attempt: " + (retrycount + 1));
}
return response;
})
.build();
private static string getauthtoken() {
return "your-auth-token";
}
// 下载文件
public static void downloadfile() throws ioexception {
request request = new request.builder()
.url("https://httpbin.org/image/jpeg")
.build();
try (response response = client.newcall(request).execute()) {
if (response.issuccessful()) {
byte[] filedata = response.body().bytes();
// 保存文件到本地
// files.write(paths.get("image.jpg"), filedata);
system.out.println("file downloaded, size: " + filedata.length + " bytes");
}
}
}
// 使用cookie
public static void withcookiejar() {
cookiejar cookiejar = new cookiejar() {
private final list<cookie> cookies = new arraylist<>();
@override
public void savefromresponse(httpurl url, list<cookie> cookies) {
this.cookies.addall(cookies);
}
@override
public list<cookie> loadforrequest(httpurl url) {
return cookies;
}
};
okhttpclient clientwithcookies = new okhttpclient.builder()
.cookiejar(cookiejar)
.build();
}
}8.okhttp工具类
简单mini版的使用示例
public class okhttputils {
private static final okhttpclient client = new okhttpclient();
public static string doget(string url) throws ioexception {
request request = new request.builder().url(url).build();
try (response response = client.newcall(request).execute()) {
if (!response.issuccessful()) {
throw new ioexception("request failed: " + response);
}
return response.body().string();
}
}
public static string dopost(string url, string json) throws ioexception {
requestbody body = requestbody.create(
json,
mediatype.parse("application/json; charset=utf-8")
);
request request = new request.builder()
.url(url)
.post(body)
.build();
try (response response = client.newcall(request).execute()) {
if (!response.issuccessful()) {
throw new ioexception("request failed: " + response);
}
return response.body().string();
}
}
// 使用示例
public static void main(string[] args) {
try {
// get请求
string getresponse = doget("https://jsonplaceholder.typicode.com/posts/1");
system.out.println("get response: " + getresponse);
// post请求
string json = "{\"title\":\"test\",\"body\":\"content\",\"userid\":1}";
string postresponse = dopost("https://jsonplaceholder.typicode.com/posts", json);
system.out.println("post response: " + postresponse);
} catch (ioexception e) {
e.printstacktrace();
}
}
}三、适用场景
- 移动应用开发;
- 微服务间的http通信;
- 文件上传下载;
- 需要精细控制http请求的场景;
- web爬虫和数据采集。
四、性能优势场景
高并发请求
// 连接池复用,适合高并发
for (int i = 0; i < 1000; i++) {
request request = new request.builder()
.url("http://api.example.com/items/" + i)
.build();
client.newcall(request).enqueue(callback); // 连接复用
}五、注意事项
同步请求:使用 execute() 方法,会阻塞当前线程
异步请求:使用 enqueue() 方法,不会阻塞当前线程
请求构建:使用 request.builder 构建请求
响应处理:注意需要手动关闭response body
连接池:okhttp自动管理连接池,提高性能
拦截器:可以添加各种拦截器实现日志、认证、重试等功能
六、与其他http客户端对比
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| android应用 | okhttp3 | 官方推荐,性能优化 |
| spring boot微服务 | openfeign | 声明式,集成性好 |
| 简单java应用 | okhttp3 | 轻量,易用 |
| 高并发爬虫 | okhttp3 | 连接池,异步支持 |
| 需要精细控制 | okhttp3 | 拦截器,自定义配置 |
到此这篇关于java使用okhttp3发送请求的实现示例的文章就介绍到这了,更多相关java okhttp3发送请求内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论