技术标签: java HttpClient
Square 公司开源的 OkHttp
okhttp 官网 https://square.github.io/okhttp/
1)支持HTTP2,对一台机器的所有请求共享同一个socket连接(同域名下所有通信都在单个连接上完成,消除了因多个连接而带来的延时和内存消耗)。
2)内置连接池,支持连接复用,减少请求延迟
3)透明的GZIP压缩减少响应数据的大小
4)通过缓存避免重复请求
5)失败时自动重连,自动重定向
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
使用:OkHttp 是一个适用于 Android、Kotlin 和 Java 应用的 HTTP 和 HTTP/2 客户端,它的请求/响应 API 使用构造器模式 builders 来设计,它支持阻塞式的同步请求和带回调的异步请求。
如果你使用 OkHttpClient,你不用重写你的代码,okhttp-urlconnection 模块实现了 java.net.HttpURLConnection 中的API,okhttp-apache 模块实现了 HttpClient 中的API
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
持续更新,和上面的同版本更新
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>4.9.3</version>
</dependency>
2016 停止更新
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp-apache</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
因为是测试,OkHttpClient 是新建的对象,所以不需要配置类,如果需要 bean 工厂可以添加配置类步骤七
,工具类步骤八
@Test
public void getUrlParams() throws IOException {
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.build();
String url = "http://127.0.0.1:8080/rest/get/url_path_params?name=admin&id=98";
Request.Builder builder = new Request.Builder();
Request request = builder.url(url).build();
Response response = okHttpClient.newCall(request).execute();
ResponseBody body = response.body();
System.out.println(body.string());
}
post 请求传递 json 数据 Content-Type:application/json; charset=utf-8
@PostMapping("/post/params_json_list")
public JSONObject postParamsJsonList(@RequestBody List<Map<String, Object>> list) {
JSONObject jsonObject = JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200,\"type\":\"okhttp3\"}");
jsonObject.put("body", list);
return jsonObject;
}
RequestBody 封装 body 参数
@Test
public void postParamsJson() throws IOException {
OkHttpClient build = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS).build();
String json = "{\"name\": \"admin\",\"id\": 10}";
String url = "http://127.0.0.1:8080/okhttp3/post/params_json";
RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().post(requestBody).url(url).build();
Response execute = build.newCall(request).execute();
ResponseBody responseBody = execute.body();
assert responseBody != null;
log.info(responseBody.string());
}
form 表单上传表单(含文件)Content-Type:multipart/form-data;
@PostMapping("/post/params_from_async")
public JSONObject postParamsFromAsync(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws InterruptedException, IOException, ServletException {
TimeUnit.SECONDS.sleep(30);
JSONObject jsonObject;
TreeMap<String, Object> treeMap = new TreeMap<>();
Collection<Part> parts = request.getParts();
parts.forEach((part) -> {
if (part.getContentType() == null) {
treeMap.put(part.getName(), request.getParameter(part.getName()));
}
});
String s = UUID.randomUUID().toString().replace("-", "").substring(0, 5) + Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().indexOf("."));
try {
file.transferTo(new File("I:\\spring\\spring-boot-aop-test\\file\\" + s));
jsonObject = JSON.parseObject("{\"message\":\"文件下载成功\",\"code\":200,\"type\":\"okhttp3\"}");
jsonObject.put("body", treeMap);
} catch (IOException e) {
e.printStackTrace();
jsonObject = JSON.parseObject("{\"message\":\"文件下载失败\",\"code\":201,\"type\":\"okhttp3\"}");
}
return jsonObject;
}
测试方法
@Test
public void postParamsFromAsync() throws IOException {
String url = "http://127.0.0.1:8080/okhttp3/post/params_from_async";
File file = new File("C:\\Users\\Administrator\\Pictures\\图标\\influxdb-studio.png");
RequestBody multipartBody = MultipartBody.create(file, MediaType.parse("image/png"));
MultipartBody body = new MultipartBody.Builder()
.addFormDataPart("file", "influxdb.png", multipartBody)
.addFormDataPart("age", "18")
.build();
Request request = new Request.Builder()
.post(body)
.url(url)
.addHeader("Connection", "keep-alive")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
log.error("okhttp", "onFailure: " + e.getMessage());
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
log.info("okhttp", "onResponse: " + response.body().string());
}
});
}
form 表单上传表单 Content-Type:application/x-www-form-urlencoded
@PostMapping("/post/params_from")
public JSONObject postParamsFrom(HttpServletRequest request) throws InterruptedException, IOException, ServletException {
JSONObject jsonObject;
Map<String, Object> treeMap = new TreeMap<>();
Map<String, String[]> parameterMap = request.getParameterMap();
parameterMap.forEach((key, value) -> {
if (value.length == 1) {
treeMap.put(key, value[0]);
} else {
treeMap.put(key, value);
}
});
jsonObject = JSON.parseObject("{\"message\":\"表单读取成功\",\"code\":200,\"type\":\"okhttp3\"}");
if (treeMap.keySet().size() > 0) {
jsonObject.put("body", treeMap);
}
return jsonObject;
}
测试方法
@Autowired
OkHttpClient okHttpClient;
@Test
public void postParamsFrom() throws IOException {
String url = "http://127.0.0.1:8080/okhttp3/post/params_from";
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("password", "123456");
linkedHashMap.put("address", "西安");
FormBody.Builder builder = new FormBody.Builder();
builder.add("name", "admin");
linkedHashMap.forEach((key, value) -> {
builder.add(key, value);
});
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.post(formBody)
.url(url)
.addHeader("Connection", "keep-alive")
.build();
Response response = okHttpClient.newCall(request).execute();
log.info(response.body().string());
}
详细配置参考 https://www.freesion.com/article/3815946206/
@Configuration
@Slf4j
public class OkHttpConfig {
@Bean
public OkHttpClient okHttpClient() throws NoSuchAlgorithmException, KeyStoreException {
// 详细配置可参考 https://www.freesion.com/article/3815946206/
return new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS) //设置连接超时
.readTimeout(60, TimeUnit.SECONDS) //设置读超时
.writeTimeout(60, TimeUnit.SECONDS) //设置写超时
.retryOnConnectionFailure(true) //是否自动重连
// 设置https配置,此处忽略了所有证书
.sslSocketFactory(sslSocketFactory(), new EasyX509TrustManager(null))
// 验证服务器的证书域名。在https握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
// 拦截器日志记录
.addInterceptor((Interceptor.Chain chain) -> {
Request request = chain.request();
log.info("intercept 接口地址:" + request.url()
+ "\r\n接口参数):" + request.body().toString());
return chain.proceed(chain.request());
})
// 添加证书,一般不要设置
.certificatePinner(new CertificatePinner.Builder()
.add("test1.com", "sha1/sdfsdsdsdsdsdsdsdsdsdsdds=")
.add("test2.com", "sha1/sdsdsdsdsdsdsdsdsdssdssds=")
.build())
//.connectionSpecs(...) // 设置连接的规格、TLS版本和密码套件等,最好不要去设置
//.socketFactory(new SocketFactory() {...}) // 使用定制的用于http请求的套接字
/* .authenticator(new Authenticator() { // 添加授权证书
@Override
public Request authenticate(Route route, Response response) throws IOException {
}
}) */
.cache(new Cache(new File("cache.tmp"), 10 * 1024 * 1024)) // 10M缓存
// 定义连接池,最多有五个空闲连接,每个空闲连接最多保持6分钟
.connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))
// 指定分发器,即异步执行http请求时的线程池,http响应的回调也是在此线程池的线程中执行
// .dispatcher(new Dispatcher(new ThreadPoolExecutor(...)))
.followRedirects(true) // 允许http重定向
.followSslRedirects(false) // 截断https的重定向
.pingInterval(30, TimeUnit.SECONDS) // 设置ping检测网络连通性的间隔。默认为0
//.proxy(...) // 设置单个代理
//.proxyAuthenticator(...) // 设置代理验证
//.proxySelector(...) // 为不同的链接设置不同的代理
.build();
}
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
/**
* Constructor for EasyX509TrustManager.
*/
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException,
KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
/**
* @see X509TrustManager#checkClientTrusted(X509Certificate[],
* String authType)
*/
public void checkClientTrusted(X509Certificate[] certificates, String authType)
throws CertificateException {
standardTrustManager.checkClientTrusted(certificates, authType);
}
/**
* @see X509TrustManager#checkServerTrusted(X509Certificate[],
* String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates, String authType)
throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
certificates[0].checkValidity();
} else {
standardTrustManager.checkServerTrusted(certificates, authType);
}
}
/**
* @see X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
public SSLSocketFactory sslSocketFactory() {
try {
//信任任何链接
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{
new EasyX509TrustManager(null)}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return null;
}
}
@Slf4j
@Component
public class OkHttpUtil{
private static OkHttpClient okHttpClient;
@Autowired
public OkHttpUtil(OkHttpClient okHttpClient) {
OkHttpUtil.okHttpClient= okHttpClient;
}
/**
* get
* @param url 请求的url
* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
*/
public static String get(String url, Map<String, String> queries) {
String responseBody = "";
StringBuffer sb = new StringBuffer(url);
if (queries != null && queries.keySet().size() > 0) {
boolean firstFlag = true;
Iterator iterator = queries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry<String, String>) iterator.next();
if (firstFlag) {
sb.append("?" + entry.getKey() + "=" + entry.getValue());
firstFlag = false;
} else {
sb.append("&" + entry.getKey() + "=" + entry.getValue());
}
}
}
Request request = new Request.Builder()
.url(sb.toString())
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
log.error("okhttp3 put error >> ", e);
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
* post
*
* @param url 请求的url
* @param params post form 提交的参数
* @return
*/
public static String post(String url, Map<String, String> params) {
String responseBody = "";
FormBody.Builder builder = new FormBody.Builder();
//添加参数
if (params != null && params.keySet().size() > 0) {
for (String key : params.keySet()) {
builder.add(key, params.get(key));
}
}
Request request = new Request.Builder()
.url(url)
.post(builder.build())
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
log.error("okhttp3 post error >> ", e);
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
* get
* @param url 请求的url
* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
* @return
*/
public static String getForHeader(String url, Map<String, String> queries) {
String responseBody = "";
StringBuffer sb = new StringBuffer(url);
if (queries != null && queries.keySet().size() > 0) {
boolean firstFlag = true;
Iterator iterator = queries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry<String, String>) iterator.next();
if (firstFlag) {
sb.append("?" + entry.getKey() + "=" + entry.getValue());
firstFlag = false;
} else {
sb.append("&" + entry.getKey() + "=" + entry.getValue());
}
}
}
Request request = new Request.Builder()
.addHeader("key", "value")
.url(sb.toString())
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
log.error("okhttp3 put error >> ", e);
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
* Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
* 参数一:请求Url
* 参数二:请求的JSON
* 参数三:请求回调
*/
public static String postJsonParams(String url, String jsonParams) {
String responseBody = "";
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
log.error("okhttp3 post error >> ", e);
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
* Post请求发送xml数据....
* 参数一:请求Url
* 参数二:请求的xmlString
* 参数三:请求回调
*/
public static String postXmlParams(String url, String xml) {
String responseBody = "";
RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
log.error("okhttp3 post error >> "+ e);
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
}
okhttp 创建 request 请求常见的 body 类型
创建 okhttp 请求,主要生成 request(包含 method、url、body、header),最后通过 OkHttpClient 执行同步(execute)异步(enqueue)方法
Request request = new Request.Builder()
.post(formBody)
.url(url)
.addHeader("Connection", "keep-alive")
.build();
Response response = okHttpClient.newCall(request).execute();
1、OkHttp3使用起来简单,但是实际上其原理代码十分复杂,这也使得OkHttp3功能很强大,包括缓存、gzip、长连接、重定向等。
2、OkHttp3原理复杂,但是它的主要功能就是网络访问,网络访问就是要完成读写功能,于是我们只需要好好把握HttpEngine中的sendRequest作用和readResponse作用即可,即sendRequest完成初始化,并通过Socket方式建立同服务器的网络连接,而readResponse通过Socket完成读写功能。
3、OkHttp3依赖于Okio,主要体现在网络访问数据放在okio.Buffer中,通过okio.Okio write方法写服务器数据,通过okio.Okio read方法读取服务器返回数据。
本人Java菜鸟一枚,很多地方写的不好,请见谅!这次做的是在JavaWeb端显示出DATE_COMPUTE_DAY(函数作用:传日期,获取星期几。例如输入20160809 Result:2)函数的作用。首先我们先看一下DATE_COMPUTE_DAY函数的参数:在这个图片中 我们可以看出DATE_COMPUTE_DAY函数的导入参数是DATE 导出参数是DATE
# https://github.com/heartInsert/randaugment/blob/master/Rand_Augment.pyfrom PIL import Image, ImageEnhance, ImageOpsimport randomclass Rand_Augment(): def __init__(self, Numbers=None, max_Magn...
ERROR:ORA-01034: ORACLE not availableORA-27101: shared memory realm does not exist[@[email protected]]ERROR:ORA-01034: ORACLE not availableORA-27101: shared memory realm does not exist进程 ID: 0会话 ID: 0 序列号: 0sqlpl...
今天遇见一个很蛋疼的问题,不知道是不是我配置的问题,IDE直接run就报错。问题描述在开发代码过程中,经常会因为逻辑处理而对代码进行分类,放进不同的文件里面;像这样,同一个包下的两个文件,点击idea的运行按钮或者运行go run main.go命令时,就会报错,如图所示。那就好吧,我直接命令运行咯,go run main.go,一样的结果。IDE...
描述系统主要基于thinkphp5.0框架开发。php版本可以使用5版本。适用于小学期毕业设计等。加载连接资源下载地址图片示例首页博客主页分类页留言板页面个人介绍页面随笔页面后台后台登录页后台主页后台网页信息管理页面后台banner友情链接后台seo后台标签后台分类后台文章列表后台文章发布随笔列表后台随笔发布后台评论列表后台留言账号密码账号:admin 密码: 123456...
upstream appserver{ip_hash;server 127.0.0.1:8090;server 127.0.0.1:8091;server 127.0.0.1:8092;}server {listen 443 ssl;server_name m.yexun.com;ssl_certificate /usr/etc/1996477_m.yexun.com.pem;ssl_certif...
public class Test { public static void main(String[] args) { System.out.println(System.getProperty("user.home")); System.out.println(System.getProperty("java.version")); System.out.println(Syst
Git和GitHub1.git1.1 git介绍 1>git是一个免费的,开源的分布式控制系统,可以快速的处理从小到大的各种项目 2>为什么要用git的分布式版本控制? 3>版本控制工具 [1]SVN,CVS,VSS等集中式版本控制工具 坏处就是中央服务器的故障问题,如果中央服务器宕机,那么谁都无法协同工作 [2]Git等分布式控制工具 好处就是可以解决远程服务器宕机的情况 且每个客户端都保存着整个项目的完整的版
POJ 1743 不可重叠最长重复子串二分答案。 即子串的长度,假设为k时。利用height数组,将排序后的后缀分为若干组。每组内的height值都不小于k。然后只需查看组内是否有满足要求的两个不会产生重叠的子串即可。#include #include #include #include #include #include #include #defin
Android操作系统是一个由Google和开放手持设备联盟共同开发发展的移动设备操作系统。最早的一款系统是2008年9月,谷歌正式发布的Android 1.0系统,也就是Android最早的版本,随后不断的更新Android系统,2.1、2.2、2.3的连续推出使Android占据了大量的市场,2011年google发布了Android 3.0系统这个系统是为了平板电脑设计的,但是是一个
web版在线打字程序演示地址:http://itkey.fun/index.jsp代码:<html><head> <meta http-equiv="Content-Type" content="text/html; charset=gbk" /> <title>旭哥的五笔3-计时可暂停版本</title> <script src="/js/vue.js"></script> &l..
学机电的同学去实习就是一种锻炼,那么你们知道自己的实习报告要怎么写吗?下面是学习啦小编为大家整理的机电实习报告范文3000字,欢迎阅读。机电实习报告范文3000字篇1一、实习目的这次实习是毕业前的一次综合性实习。本次实习是为了拓展知识面,扩大与社会的接触面,锻炼和提高能力,将理论知识与实践相结合,在以后走入社会能够更快的进入工作,更快的融入社会。在生活和工作中能够很好的处理各方面的问题,进一步运用...