OkHttp3使用教程,实现get、post请求发送,自动重试,打印响应日志。
一、创建线程安全的okhttp单例
import service.NetworkIntercepter;
import service.RetryIntercepter;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit; public class HttpUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
private static final int CONNECTION_TIME_OUT = 2000;//连接超时时间
private static final int SOCKET_TIME_OUT = 2000;//读写超时时间
private static final int MAX_IDLE_CONNECTIONS = 30;// 空闲连接数
private static final long KEEP_ALLIVE_TIME = 60000L;//保持连接时间 private OkHttpClient okHttpClient;
private volatile static HttpUtils httpUtils; public static HttpUtils getInstance(){
if(httpUtils == null){
synchronized (HttpUtils.class){
if(httpUtils == null){
httpUtils = new HttpUtils();
}
}
}
return httpUtils; }
public HttpUtils(){
ConnectionPool connectionPool = new ConnectionPool(MAX_IDLE_CONNECTIONS,KEEP_ALLIVE_TIME,TimeUnit.MILLISECONDS);
this.okHttpClient = new OkHttpClient()
.newBuilder()
.readTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
.writeTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
.connectionPool(connectionPool)
.retryOnConnectionFailure(false) //自动重连设置为false
.connectTimeout(CONNECTION_TIME_OUT,TimeUnit.MILLISECONDS)
.addInterceptor(new RetryIntercepter(2)) //重试拦截器2次
.addNetworkInterceptor(new NetworkIntercepter()) //网络拦截器,统一打印日志
.build();
}
}
重试拦截器:
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response; import java.io.IOException; public class RetryIntercepter implements Interceptor{
public int maxRetryCount;
private int count = 0;
public RetryIntercepter(int maxRetryCount) {
this.maxRetryCount = maxRetryCount;
} @Override
public Response intercept(Chain chain) throws IOException { return retry(chain);
} public Response retry(Chain chain){
Response response = null;
Request request = chain.request();
try {
response = chain.proceed(request);
while (!response.isSuccessful() && count < maxRetryCount) {
count++;
response = retry(chain);
}
}
catch (Exception e){
while (count < maxRetryCount){
count++;
response = retry(chain);
}
}
return response;
}
}
注意:两处while是因为如果请求中出现异常,也能进行重试,比如超时,后面会有例子。
网络拦截器,打印请求、响应时间、响应状态码,响应内容
import okhttp3.*;
import okio.Buffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.IOException;
import java.nio.charset.Charset; public class NetworkIntercepter implements Interceptor{
private static Logger LOGGER = LoggerFactory.getLogger(NetworkIntercepter.class);
@Override
public Response intercept(Interceptor.Chain chain) {
long start = System.currentTimeMillis();
Response response=null;
String responseBody = null;
String responseCode = null;
String url = null;
String requestBody = null;
try {
Request request = chain.request();
url = request.url().toString();
requestBody = getRequestBody(request);
response = chain.proceed(request);
responseBody = response.body().string();
responseCode = String.valueOf(response.code());
MediaType mediaType = response.body().contentType();
response = response.newBuilder().body(ResponseBody.create(mediaType,responseBody)).build();
}
catch (Exception e){
LOGGER.error(e.getMessage());
}
finally {
long end = System.currentTimeMillis();
String duration = String.valueOf(end - start);
LOGGER.info("responseTime= {}, requestUrl= {}, params={}, responseCode= {}, result= {}",
duration, url,requestBody,responseCode,responseBody);
} return response;
} private String getRequestBody(Request request) {
String requestContent = "";
if (request == null) {
return requestContent;
}
RequestBody requestBody = request.body();
if (requestBody == null) {
return requestContent;
}
try {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = Charset.forName("utf-8");
requestContent = buffer.readString(charset);
} catch (IOException e) {
e.printStackTrace();
}
return requestContent;
}
}
二、GET请求
1、带参数的get请求
/*
* 发送待url参数的get
*/
public String get(String url,Map<String,String> pathParams){
HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
for(String key:pathParams.keySet()){
builder.addQueryParameter(key,pathParams.get(key) );
}
Request request = new Request.Builder()
.url(builder.build().toString())
.build();
return execute(request);
} private String execute(Request request){
String responseBody=null;
try {
Response response = okHttpClient.newCall(request).execute();
responseBody = response.body().string();
} catch (IOException |NullPointerException e) {
e.printStackTrace();
}
return responseBody;
}
测试:
String url = "http://localhost:8080/test/12346/query";
Map<String,String> params = new HashMap<>();
params.put("aaa","111");
params.put("bbb","222");
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.get(url,params); 打印日志如下:
[main][2019-09-21 10:19:02.072] [INFO] [NetworkIntercepter.intercept:40] responseTime= 62, requestUrl= http://localhost:8080/test/12346/query?aaa=111&bbb=222, params=, responseCode= 200, result= {"result_code":"success","data":{"aaa":"111"},"path":"/test/12346/query"}
2、不带参数的get请求
测试:
String url = "http://localhost:8080/test/12346/query?ccc=1&ddd=2";
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.get(url); 打印日志如下:
[main][2019-09-21 10:25:46.943] [INFO] [NetworkIntercepter.intercept:38] responseTime= 11, requestUrl= http://localhost:8080/test/12346/query?ccc=1&ddd=2, params=, responseCode= 200, result= {"result_code":"success","data":{"aaa":"111"},"path":"/test/12346/query"}
三、POST请求
1、post发送带url参数的json
/*
* post发送带url参数的json
*/
public String post(String url, Map<String,String> pathParams, String body){
RequestBody requestBody = RequestBody.
create(MediaType.parse("application/json;charset=utf-8"), body);
HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
for(String key:pathParams.keySet()){
builder.addQueryParameter(key,pathParams.get(key) );
}
Request request = new Request.Builder()
.post(requestBody)
.url(builder.build().toString())
.build();
return execute(request);
}
测试:
Gson gson = new Gson();
String url = "http://localhost:8080/test/12346/query";
Map<String,String> params = new HashMap<>();
params.put("aaa","111");
params.put("bbb","222"); Map<String,Object> bodyMap = new HashMap<>();
bodyMap.put("name","zhangsan");
bodyMap.put("age",15);
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.post(url,params,gson.toJson(bodyMap)); 打印日志
[main][2019-09-21 10:37:04.577] [INFO] [NetworkIntercepter.intercept:38] responseTime= 304, requestUrl= http://localhost:8080/test/12346/query?aaa=111&bbb=222, params={"name":"zhangsan","age":15}, responseCode= 200, result= {"result_code":"success","data":{"aaa":"111"},"path":"/test/12346/query"}
2、post发送json
/*
* post发送json
*/
public String post(String url,String body){
Map<String,String> pathParams = new HashMap<>();
return post(url,pathParams ,body );
}
测试:
Gson gson = new Gson();
String url = "http://localhost:8080/test/12346/query";
Map<String,Object> bodyMap = new HashMap<>();
bodyMap.put("name","zhangsan");
bodyMap.put("age",15);
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.post(url,gson.toJson(bodyMap));
打印日志:
[main][2019-09-21 10:44:00.835] [INFO] [NetworkIntercepter.intercept:38] responseTime= 17, requestUrl= http://localhost:8080/test/12346/query, params={"name":"zhangsan","age":15}, responseCode= 200, result= {"result_code":"success","data":{"aaa":"111"},"path":"/test/12346/query"}
3、post发送表单
/*
* post发送表单
*/
public String post(String url, Map<String,String> pathParams){
FormBody.Builder formBodyBuilder = new FormBody.Builder();
HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
for(String key:pathParams.keySet()){
formBodyBuilder.add(key,pathParams.get(key) );
}
RequestBody requestBody = formBodyBuilder.build();
Request request = new Request.Builder()
.post(requestBody)
.url(builder.build().toString())
.build();
return execute(request);
}
测试:
String url = "http://localhost:8080/test/12346/query";
Map<String,String> params = new HashMap<>();
params.put("aaa","111");
params.put("bbb","222");
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.post(url,params); 打印日志:
[main][2019-09-21 10:49:54.136] [INFO] [NetworkIntercepter.intercept:38] responseTime= 21, requestUrl= http://localhost:8080/test/12346/query, params=aaa=111&bbb=222, responseCode= 200, result= {"result_code":"success","data":{"aaa":"111"},"path":"/test/12346/query"}
四、网络拦截器
1、404重试
测试:
String url = "http://localhost:8080/test/12346/query2";
Map<String,String> params = new HashMap<>();
params.put("aaa","111");
params.put("bbb","222");
HttpUtils httpUtils = HttpUtils.getInstance();
httpUtils.post(url,params); 日志打印:
[main][2019-09-21 10:56:20.495] [INFO] [NetworkIntercepter.intercept:38] responseTime= 26, requestUrl= http://localhost:8080/test/12346/query2, params=aaa=111&bbb=222, responseCode= 404, result= {"timestamp":1569034580,"status":404,"error":"Not Found","message":"Not Found","path":"/test/12346/query2"}
[main][2019-09-21 10:56:20.506] [INFO] [NetworkIntercepter.intercept:38] responseTime= 4, requestUrl= http://localhost:8080/test/12346/query2, params=aaa=111&bbb=222, responseCode= 404, result= {"timestamp":1569034580,"status":404,"error":"Not Found","message":"Not Found","path":"/test/12346/query2"}
[main][2019-09-21 10:56:20.512] [INFO] [NetworkIntercepter.intercept:38] responseTime= 4, requestUrl= http://localhost:8080/test/12346/query2, params=aaa=111&bbb=222, responseCode= 404, result= {"timestamp":1569034580,"status":404,"error":"Not Found","message":"Not Found","path":"/test/12346/query2"
重试了2次,共请求3次
2、超时重试
日志打印:
[main][2019-09-21 10:59:30.086] [ERROR] [NetworkIntercepter.intercept:33] timeout
[main][2019-09-21 10:59:30.092] [INFO] [NetworkIntercepter.intercept:38] responseTime= 2009, requestUrl= http://localhost:8080/test/12346/query, params=aaa=111&bbb=222, responseCode= null, result= null
[main][2019-09-21 10:59:32.097] [ERROR] [NetworkIntercepter.intercept:33] timeout
[main][2019-09-21 10:59:32.097] [INFO] [NetworkIntercepter.intercept:38] responseTime= 2004, requestUrl= http://localhost:8080/test/12346/query, params=aaa=111&bbb=222, responseCode= null, result= null
[main][2019-09-21 10:59:34.101] [ERROR] [NetworkIntercepter.intercept:33] timeout
[main][2019-09-21 10:59:34.101] [INFO] [NetworkIntercepter.intercept:38] responseTime= 2002, requestUrl= http://localhost:8080/test/12346/query, params=aaa=111&bbb=222, responseCode= null, result= null
OkHttp3使用教程,实现get、post请求发送,自动重试,打印响应日志。的更多相关文章
- scrapy框架post请求发送,五大核心组件,日志等级,请求传参
一.post请求发送 - 问题:爬虫文件的代码中,我们从来没有手动的对start_urls列表中存储的起始url进行过请求的发送,但是起始url的确是进行了请求的发送,那这是如何实现的呢? - 解答: ...
- 精讲RestTemplate第8篇-请求失败自动重试机制
本文是精讲RestTemplate第8篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲响应式WebClient第6篇-请求失败自动重试机制,强烈建议你看一看
本文是精讲响应式WebClient第6篇,前篇的blog访问地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方 ...
- chrome 浏览器的预提取资源机制导致的一个请求发送两次的问题以及ClientAbortException异常
调查一个 pdf 打印报错: ExceptionConverter: org.apache.catalina.connector.ClientAbortException: java.net.Sock ...
- Web爬去的C#请求发送
public class HttpControler { //post请求发送 private Encoding m_Encoding = Encoding.GetEncoding("gb2 ...
- 用Python做大批量请求发送
大批量请求发送需要考虑的几个因素: 1. 服务器承载能力(网络带宽/硬件配置); 2. 客户端IO情况, 客户端带宽, 硬件配置; 方案: 1. 方案都是相对的; 2. 因为这里我的情况是客户机只有一 ...
- ajax请求发送和页面跳转的冲突
http://blog.csdn.net/allenliu6/article/details/77341538?locationNum=7&fps=1 在A页面中,有一个click事件,点击时 ...
- 利用post请求发送内容进行爬虫
利用post请求发送内容进行爬虫 import requests url = 'http://www.iqianyue.com/mypost' header = {} header['Accept-L ...
- 一个http请求发送到后端的详细过程
我们来看当我们在浏览器输入http://www.mycompany.com:8080/mydir/index.html,幕后所发生的一切. 首先http是一个应用层的协议,在这个层的协议,只是一种通讯 ...
随机推荐
- 【JVM从小白学成大佬】2.Java虚拟机运行时数据区
目录 1.运行时数据区介绍 2.堆(Heap) 是否可能有两个对象共用一段内存的事故? 3.方法区(Method Area) 4.程序计数器(Program Counter Register) 5.虚 ...
- SSH原理讲解与实践
一.简介 SSH全名Secure Socket Shell,安全外壳传输协议.专为远程登录会话和其他网络服务提供安全性的协议 二.加密算法 要了解SSH的原理,就要先知道目前主流的俩种加密算法 2.1 ...
- [ZJOI2011]看电影(组合数学,高精度)
[ZJOI2011]看电影 这题模型转化很巧妙.(神仙题) 对于这种题首先肯定知道答案就是合法方案除以总方案. 总方案显然是\(k^n\). 那么考虑怎么算合法方案. 当\(n>k\)的时候显然 ...
- Mac 打造开发工作环境
近日公司配的dell笔记本越来越难担重任(主要是CPU太差,本人是Java开发,IDE一编译CPU就100%),于是狠下心入手了一台常规顶配Macbook Pro,现记录新本本的调教过程. Homeb ...
- 上个月,我赚了2W外快。。。
前段时间和室友一起给某个公司做了一个管理系统,每个人分2W多.这里和大家分享一下做完项目后一点点感受,想到啥就说点啥. 核心竞争力 两个月就挣了2W块,挣了我爸妈两个人一年的收入,每天还贼辛苦,披星戴 ...
- springboot 整合shiro
参考: https://blog.csdn.net/fuweilian1/article/details/80309192(推荐) https://blog.csdn.net ...
- Java基础之Iterable与Iterator
Java基础之Iterable与Iterator 一.前言: Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的.able结尾的表示 能...样,可以做.... Iterato ...
- 写博客没高质量配图?python爬虫教你绕过限制一键搜索下载图虫创意图片!
目录 前言 分析 理想状态 爬虫实现 其他注意 效果与总结 @(文章目录) 前言 在我们写文章(博客.公众号.自媒体)的时候,常常觉得自己的文章有些老土,这很大程度是因为配图没有选好. 笔者也是遇到相 ...
- 学习笔记之Java队列Queue中offer/add函数,poll/remove函数,peek/element函数的区别
队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. Java中Que ...
- (八)分布式通信----主机Host
上节中有谈到的是通信主机(TransportHost),本节中主机(ServiceHost)负责管理服务的生命周期. 项目中将两个主机拆分开,实现不同的功能: 通信主机:用于启动通信监听端口: 生命周 ...