關於Retrofit2+Okhttp3實現統一新增請求引數和重定向
Android開發中難免會遇到一些比較“不友好”的服務端介面。比如以前遇到的json資料中,某個欄位偶爾為Object,偶爾為List…
最近遇到的一個問題就是:所有請求介面都要增加一個token引數… 並且token引數有可能過期,比如請求某一條介面,如果token失效則在該請求的響應中把新的token帶回來,客戶端就得用新的token再次傳送該請求,類似重定向。
token失效的stateCode為3,新的token在data欄位中返回。如下:
{
"stateCode":3,
"data":"E78kH6",
"errorMsg":null
}
慶幸的是,Okhttp提供了強大的攔截器功能,是一種能夠監控,重寫,重試呼叫的強大機制。
public class TokenInterceptord implements Interceptor {
private final String TAG = "respond";
@Override
public Response intercept(Chain chain) throws IOException {
Request oldRequest = chain.request();
String url = oldRequest.url().toString();
Response response = null;
// 新的請求,新增引數
Request newRequest = addParam(oldRequest);
response = chain.proceed(newRequest);
ResponseBody value = response.body();
byte[] resp = value.bytes();
String json = new String(resp, "UTF-8");
// 判斷stateCode值
try {
JSONObject jsonObject = new JSONObject(json);
int stateCode = jsonObject.optInt("stateCode");
if (stateCode == 3) {
String data = jsonObject.optString("data");
Log.d(TAG, "token失效,新的token:" + data);
DataStorageUtils.saveToken(data);
// token失效,重新執行請求
Request newTokenRequest = addParam(oldRequest);
response = chain.proceed(newTokenRequest);
} else {
// 這裡值得注意。由於前面value.bytes()把響應流讀完並關閉了,所以這裡需要重新生成一個response,否則資料就無法正常解析了
response = response.newBuilder()
.body(ResponseBody.create(null, resp))
.build();
}
} catch (Exception e) {
}
return response;
}
/**
* 新增公共引數
*
* @param oldRequest
* @return
*/
private Request addParam(Request oldRequest) {
HttpUrl.Builder builder = oldRequest.url()
.newBuilder()
.setEncodedQueryParameter("lversion", PackagesUtils.getAppVersionName())
.setEncodedQueryParameter("token", DataStorageUtils.getToken());
Request newRequest = oldRequest.newBuilder()
.method(oldRequest.method(), oldRequest.body())
.url(builder.build())
.build();
return newRequest;
}
}
當然,也可以為請求或響應新增Header。
Request request = oldRequest.newBuilder()
.header("Content-Encoding", "gzip")
.build();
Response response = response.newBuilder()
.header("Content-Encoding", "gzip")
.build();
然後為OkHttp配置一個攔截器。
public static OkHttpClient getOkHttpClient() {
Interceptor interceptor = new TokenInterceptor();
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30 * 1000, TimeUnit.MILLISECONDS)
.readTimeout(30 * 1000, TimeUnit.MILLISECONDS)
.addInterceptor(interceptor)
.addInterceptor(new HttpLoggingInterceptor(new MyLog()).setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
return client;
}
Retrofit 使用 Okhttp作為client
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.client(getOkHttpClient())
.build();
Api api = retrofit.create(Api.class);
相關文章
- Retrofit統一新增post請求的預設引數
- 關於在request請求時,處理請求引數的問題
- Servlet中請求重定向和請求轉發和includeServlet
- 請求重定向和請求轉發的區別
- 跟我一起動手實現Tomcat(三):解析Request請求引數、請求頭、cookieTomcatCookie
- 有趣的請求引數/請求頭
- SpringMVC學習(三)對映請求引數&請求引數SpringMVC
- 漫遊 javax.servlet 請求引數解析(jetty 實現)JavaServletJetty
- SpringMVC重定向傳引數的實現SpringMVC
- 重定向和請求轉發的區別
- postman 請求引數和 Spring Boot Controller 接受引數PostmanSpring BootController
- pytest + yaml 框架 -68.新增全域性請求引數配置verify和headersYAML框架Header
- 請求引數的傳遞
- SpringMVC請求引數解析SpringMVC
- fastapi 請求引數 校驗ASTAPI
- Charles 修改請求(Request)引數
- nginx 中配置請求重定向Nginx
- 關於靜態引數和動態引數
- Postman傳送請求引數是Map格式的請求Postman
- ajax中POST請求與引數(請求體)設定
- Tips_傳送請求時新增一個隨機數引數,讓瀏覽器每次都重新發請求到伺服器隨機瀏覽器伺服器
- Laravel 檔案上傳和獲取請求引數Laravel
- 使用 http-proxy 實現 SAP UI5 請求的代理重定向HTTPUI
- 使用 Promise 實現任務佇列傳送請求,實現最大請求數目限制Promise佇列
- GOLANG Web請求引數驗證GolangWeb
- GET請求的引數丟失
- 什麼是請求引數、表單引數、url引數、header引數、Cookie引數?一文講懂HeaderCookie
- 關於兩次http請求,後一次請求影響前一次請求的問題HTTP
- 請求轉發與URL重定向
- 一個關於Struts傳引數的問題,請高手來看看............
- 如何高效定義和驗證restful請求的引數REST
- 表單請求獲取路由引數路由
- request的請求引數獲取方式
- 漫遊 servlet請求引數 %urldecodeServlet
- java傳送get請求帶引數Java
- charles 打斷點修改請求引數斷點
- HTTP中的重定向和請求轉發的區別HTTP
- 尋找寫程式碼感覺(七)之封裝請求引數和返回引數封裝