简介
OkHttp是一个高效的HTTP库,它建立在HttpUrlConnection之上。OkHttp支持 SPDY ,共享同一个Socket来处理同一个服务器的所有请求,如果SPDY不可用,则通过连接池来减少请求延时;无缝的支持GZIP来减少数据流量;缓存响应数据来减少重复的网络请求;当网络出现拥挤的时候,使用OKHttp可以避免常见的网络问题,如果服务器配端置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。对现在IPv4+IPv6 中常见的把服务冗余部署在不同的数据中心上,OkHttp 将使用现在TLS特性(SNI ALPN) 来初始化新的连接,如果连接失败,将切换到SLLv3;另外,OkHttp还处理了代理服务器问题和SSL连接失败的问题。
小知识SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。OkHttp直接架构于Java Socket本身而没有依赖于其他第三方类库(如下图所示),因此开发者可以直接用在JVM中,而不仅仅是Android。为了简化代码迁移速度,OkHttp实现了类似于HttpUrlConnection与Apache Client的接口,比如:okhttp-urlconnection模块实现了 java.net.HttpURLConnection 中的API、okhttp-apache模块实现了HttpClient中的API。因此使用OkHttp重构之前的代码,基本上不需要再做大量的工作。 目前OkHttp支持如下特性:
- 支持基于HTTP/2以及SPDY的多路复用
- 支持连接池、会降低并发连接数
- 透明GZIP加密减少传输的数据量
- 响应缓存避免大量重复请求
- 同时支持同步的阻塞式调用与异步回调式调用
com.squareup.okhttp3
okhttp
4.8.1
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
服务器端代码
@RestController
public class DispatchController {
@GetMapping("/get")
public String get() {
return "get";
}
@PostMapping("/post")
public String post(String username,String password) {
System.out.println(username+" : "+password);
return "post";
}
@RequestMapping("/header")
public String header(HttpServletRequest request, HttpServletResponse response) {
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name + " : " + value);
}
response.setHeader("xxx", "13579");
response.setHeader("yyy", "24680");
return "header";
}
}
OkHttp测试代码
@SpringBootTest
public class OkHttpTest {
@Test
public void get() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://localhost/od/get")
.method("GET", null)
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String res = response.body().string();
System.out.println(res);
} else {
throw new IOException("Unexpected code " + response);
}
}
@Test
public void post() throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.Companion.create("", mediaType);
String username = "lisi";
String password = "123456";
Request request = new Request.Builder()
.url("http://localhost/od/post?username=" + username + "&password=" + password)
.method("POST", body)
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
Headers headers = response.headers();
}
@Test
public void header() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://localhost/od/header")
.addHeader("Xaa", "application/json; q=0.5")
.addHeader("Xbb", "application/vnd.github.v3+json")
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String res = response.body().string();
System.out.println(res);
Headers headers = response.headers();
System.out.println(headers.get("xxx"));
System.out.println(headers.get("yyy"));
} else {
throw new IOException("Unexpected code " + response);
}
}
}