需求描述
對一個url地址發起請求后,設置超時時長為3秒,若超時時重試3次后仍然超時視為宕機並返回自定義的code信息。
解決
這是我入職公司的第一個任務,上級說簡單,不過我搞了有兩天了,因為在網上搜的自定義超時重試次數看不懂。。后來還是問強哥,他給了我一篇博客鏈接,然后我才有了思路。
- 發起post請求
OkHttpClient client = new OkHttpClient
.Builder()
.connectTimeout(okhttpTimeOut, TimeUnit.SECONDS) // 設置超時時長,單位秒
.addInterceptor(new OkhttpInterceptor(maxRetry)) //過濾器,設置最大重試次數
.retryOnConnectionFailure(false) //不自動重連
.build();
-
過濾器,通過遞歸達到超時重試的目的
這里需要說明:原本以為超時后直接拿到response可以判斷超時信息,簡簡單單做個循環就好。但是!超時后直接拋出異常 ConnectException,我原來的笨方法就是捕獲這個異常,3次重試就做三層的try catch,代碼寫出來傻傻的。
還好,遞歸可以解決這個問題,本質上沒什么變化,但是用上了遞歸就是爽!
@Slf4j
class OkhttpInterceptor implements Interceptor{
private int maxRentry;// 最大重試次數
public OkhttpInterceptor(int maxRentry){
this.maxRentry=maxRentry;
}
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
/* 遞歸 4次下發請求,如果仍然失敗 則返回 null ,但是 intercept must not return null.
* 返回 null 會報 IllegalStateException 異常
* */
return retry(chain,0);//這個遞歸真的很🐂
}
Response retry(Chain chain,int retryCent){
Request request = chain.request();
Response response = null;
try{
log.info("messageId: "+messageId+" 第"+(retryCent+1)+"次執行下發NEF請求.");
response = chain.proceed(request);
}catch (Exception e){
if ( maxRentry > retryCent ){
return retry(chain,retryCent+1);
}
}finally {
return response;
}
}
}
- 執行請求,捕獲
IllegalStateException異常
try{
response = client.newCall(request).execute();//執行請求
/*如果response可以正常返回,說明能連接上,接着寫業務邏輯即可*/
}catch(IllegalStateException e){
//捕獲異常,intercept must not return null.過濾器不能返回null
e.printStackTrace();
log.info("重試3次后訪問超時.");
resMap.put("code","404");//在這里可以自定義返回信息
return resMap;
}
