okhttp3重试拦截
一、创建线程安全的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();
}
}
重试拦截器:
1 import okhttp3.Interceptor; 2 import okhttp3.Request; 3 import okhttp3.Response; 4 5 import java.io.IOException; 6 7 8 public class RetryIntercepter implements Interceptor{ 9 public int maxRetryCount; 10 private int count = 0; 11 public RetryIntercepter(int maxRetryCount) { 12 this.maxRetryCount = maxRetryCount; 13 } 14 15 @Override 16 public Response intercept(Chain chain) throws IOException { 17 18 return retry(chain); 19 } 20 21 public Response retry(Chain chain){ 22 Response response = null; 23 Request request = chain.request(); 24 try { 25 response = chain.proceed(request); 26 while (!response.isSuccessful() && count < maxRetryCount) { 27 count++; 28 response = retry(chain); 29 } 30 } 31 catch (Exception e){ 32 while (count < maxRetryCount){ 33 count++; 34 response = retry(chain); 35 } 36 } 37 return response; 38 } 39 }
注意:两处while是因为如果请求中出现异常,也能进行重试,比如超时,后面会有例子。
网络拦截器,打印请求、响应时间、响应状态码,响应内容
1 import okhttp3.*; 2 import okio.Buffer; 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 6 import java.io.IOException; 7 import java.nio.charset.Charset; 8 9 10 public class NetworkIntercepter implements Interceptor{ 11 private static Logger LOGGER = LoggerFactory.getLogger(NetworkIntercepter.class); 12 @Override 13 public Response intercept(Interceptor.Chain chain) { 14 long start = System.currentTimeMillis(); 15 Response response=null; 16 String responseBody = null; 17 String responseCode = null; 18 String url = null; 19 String requestBody = null; 20 try { 21 Request request = chain.request(); 22 url = request.url().toString(); 23 requestBody = getRequestBody(request); 24 response = chain.proceed(request); 25 responseBody = response.body().string(); 26 responseCode = String.valueOf(response.code()); 27 MediaType mediaType = response.body().contentType(); 28 response = response.newBuilder().body(ResponseBody.create(mediaType,responseBody)).build(); 29 } 30 catch (Exception e){ 31 LOGGER.error(e.getMessage()); 32 } 33 finally { 34 long end = System.currentTimeMillis(); 35 String duration = String.valueOf(end - start); 36 LOGGER.info("responseTime= {}, requestUrl= {}, params={}, responseCode= {}, result= {}", 37 duration, url,requestBody,responseCode,responseBody); 38 } 39 40 return response; 41 } 42 43 private String getRequestBody(Request request) { 44 String requestContent = ""; 45 if (request == null) { 46 return requestContent; 47 } 48 RequestBody requestBody = request.body(); 49 if (requestBody == null) { 50 return requestContent; 51 } 52 try { 53 Buffer buffer = new Buffer(); 54 requestBody.writeTo(buffer); 55 Charset charset = Charset.forName("utf-8"); 56 requestContent = buffer.readString(charset); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 return requestContent; 61 } 62 }
二、GET请求
1、带参数的get请求
1 /* 2 * 发送待url参数的get 3 */ 4 public String get(String url,Map<String,String> pathParams){ 5 HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); 6 for(String key:pathParams.keySet()){ 7 builder.addQueryParameter(key,pathParams.get(key) ); 8 } 9 Request request = new Request.Builder() 10 .url(builder.build().toString()) 11 .build(); 12 return execute(request); 13 } 14 15 private String execute(Request request){ 16 String responseBody=null; 17 try { 18 Response response = okHttpClient.newCall(request).execute(); 19 responseBody = response.body().string(); 20 } catch (IOException |NullPointerException e) { 21 e.printStackTrace(); 22 } 23 return responseBody; 24 }
测试:
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
1 /* 2 * post发送带url参数的json 3 */ 4 public String post(String url, Map<String,String> pathParams, String body){ 5 RequestBody requestBody = RequestBody. 6 create(MediaType.parse("application/json;charset=utf-8"), body); 7 HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); 8 for(String key:pathParams.keySet()){ 9 builder.addQueryParameter(key,pathParams.get(key) ); 10 } 11 Request request = new Request.Builder() 12 .post(requestBody) 13 .url(builder.build().toString()) 14 .build(); 15 return execute(request); 16 }
测试:
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
1 /* 2 * post发送json 3 */ 4 public String post(String url,String body){ 5 Map<String,String> pathParams = new HashMap<>(); 6 return post(url,pathParams ,body ); 7 }
测试:
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发送表单
1 /* 2 * post发送表单 3 */ 4 public String post(String url, Map<String,String> pathParams){ 5 FormBody.Builder formBodyBuilder = new FormBody.Builder(); 6 HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); 7 for(String key:pathParams.keySet()){ 8 formBodyBuilder.add(key,pathParams.get(key) ); 9 } 10 RequestBody requestBody = formBodyBuilder.build(); 11 Request request = new Request.Builder() 12 .post(requestBody) 13 .url(builder.build().toString()) 14 .build(); 15 return execute(request); 16 }
测试:
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