okHttp3教程,實現5種請求發送、自動重試、日誌打印

1、建立線程安全的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是由於若是請求中出現異常,也能進行重試,好比超時,後面會有例子。java

 

網絡攔截器,打印請求、響應時間、響應狀態碼,響應內容

 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 }

 

 

2、GET請求

一、帶參數的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     }

測試:json

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"}

 二、不帶參數的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"}


3、POST請求

一、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"}    

二、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     }

 

測試:app

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));

打印日誌:ide

[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"}post

 

三、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"}

 4、網絡攔截器

一、404重試

測試:ui

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"this


重試了2次,共請求3次

二、超時重試

日誌打印:

[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

相關文章
相關標籤/搜索