亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

如何動態改變Retrofit的base url和rest版本詳解

2024-07-14 08:42:18
字體:
來源:轉載
供稿:網友

概述

隨著Google對HttpClient 摒棄,和Volley的逐漸沒落,OkHttp開始異軍突起,而Retrofit則對okHttp進行了強制依賴。

Retrofit是由Square公司出品的針對于Android和Java的類型安全的Http客戶端,

如果看源碼會發現其實質上就是對okHttp的封裝,使用面向接口的方式進行網絡請求,利用動態生成的代理類封裝了網絡接口請求的底層,

其將請求返回javaBean,對網絡認證 REST API進行了很好對支持此,使用Retrofit將會極大的提高我們應用的網絡體驗。

REST

既然是RESTful架構,那么我們就來看一下什么是REST吧。 

REST(REpresentational State Transfer)是一組架構約束條件和原則。 

RESTful架構都滿足以下規則: 

(1)每一個URI代表一種資源; 

(2)客戶端和服務器之間,傳遞這種資源的某種表現層; 

(3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現”表現層狀態轉化”。

下面話不多說了,來開始本文的正文吧

1. 需求與前提

base url

默認base url: https://cloud.devwiki.net

測試版 url : https://dev.devwiki.net

私有云版本url: https://private.devwiki.net

rest 版本

  • /rest/v1/
  • /rest/v2/
  • /rest/v3/

需求點

  • 大部分接口使用 cloud host, 部分接口使用 private host
  • 大部分接口使用 rest/v3 版本, 部分接口使用 v2, v1版本.
  • 每個host 都有可能存在 rest v1, v2, v3的接口

2. 實現思路

okhttp 可以添加攔截器, 可在發起訪問前進行攔截, 通常我們會在 攔截器中統一添加 header, 比如:

class HeaderInterceptor implements Interceptor {  private static final String ENCODING_GZIP = "gzip"; private static final String CONTENT_TYPE_JSON = "application/json;charset=UTF-8"; private static final String HEADER_CONTENT_TYPE = "Content-Type"; private static final String HEADER_ACCEPT_TYPE = "application/json"; private static final String HEADER_CONTENT_ENCODING = "Content-Encoding"; private final static String CHARSET = "UTF-8";  @Override public Response intercept(Chain chain) throws IOException {  Request originRequest = chain.request();  Request.Builder newBuilder = originRequest.newBuilder();  newBuilder.addHeader("Accept", HEADER_ACCEPT_TYPE);  newBuilder.addHeader("Accept-Charset", CHARSET);  newBuilder.addHeader("Accept-Encoding", ENCODING_GZIP);  newBuilder.addHeader("Accept-Language", Locale.getDefault().toString().replace("_", "-"));  newBuilder.addHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);  return chain.proceed(newBuilder.build()); }}

同理我們也可以在所有請求中添加統一的uuid 或者 key 進行防劫持或者認證. 比如:

Request originRequest = chain.request();if (paramsMap != null) { HttpUrl originUrl = originRequest.url(); HttpUrl.Builder newBuilder = originUrl.newBuilder(); for (String key : paramsMap.keySet()) {  newBuilder.addEncodedQueryParameter(key, paramsMap.get(key)); } HttpUrl newUrl = newBuilder.build(); Request newRequest = originRequest.newBuilder().url(newUrl).build(); return chain.proceed(newRequest);}return chain.proceed(originRequest);

那么, 同樣我們可以再攔截器中進行host 和 path的替換, 那么怎么替換呢?

3. 實現過程

3.1 定義host 類型和 rest 版本

host類型:

interface HostName { String CLOUD = "CLOUD"; String PRIVATE = "PRIVATE"; String DEV = "DEV";} interface HostValue { String CLOUD = "https://www.baidu.com"; String PRIVATE = "https://private.bidu.com"; String DEV = "https://dev.baidu.com";}

rest 版本:

interface RestVersionCode { String EMPTY = "EMPTY"; String V1 = "V1"; String V2 = "V2"; String PRIVATE = "PRIVATE";} /** * path 前綴值 */interface RestVersionValue { String EMPTY = ""; String V1 = "rest/v1"; String V2 = "rest/v2"; String PRIVATE = "rest/private";}

設置一個默認的 host 和 rest 版本, 然后在需要更改host和rest 版本的請求接口處添header, 根據header設置來變更.

interface BaiduApiService {  @GET("s") Observable<Response<Object>> search(@Query("wd")String wd);  @GET("s") @Headers({UrlConstants.Header.REST_VERSION_V1}) Observable<Response<Object>> searchChangePath(@Query("wd")String wd);  @GET("s") @Headers({UrlConstants.Header.HOST_DEV}) Observable<Response<Object>> searchChangeHost(@Query("wd")String wd);  @Headers({UrlConstants.Header.HOST_PRIVATE, UrlConstants.Header.REST_VERSION_PRIVATE}) @GET("s") Observable<Response<Object>> searchChangeHostPath(@Query("wd")String wd);}

header 的可選值:

interface Header { String SPLIT_COLON = ":"; String HOST = "HostName"; String HOST_CLOUD = HOST + SPLIT_COLON + HostName.CLOUD; String HOST_PRIVATE = HOST + SPLIT_COLON + HostName.PRIVATE; String HOST_DEV = HOST + SPLIT_COLON + HostName.DEV; String REST_VERSION = "RestVersion"; String REST_VERSION_V1 = REST_VERSION + SPLIT_COLON + RestVersionCode.V1; String REST_VERSION_V2 = REST_VERSION + SPLIT_COLON + RestVersionCode.V2; String REST_VERSION_PRIVATE = REST_VERSION + SPLIT_COLON + RestVersionCode.PRIVATE; String REST_VERSION_EMPTY = REST_VERSION + SPLIT_COLON + RestVersionCode.EMPTY;}

然后是解析:

class RequestInterceptor implements Interceptor {  @Override public Response intercept(Chain chain) throws IOException {  Request originRequest = chain.request();  HttpUrl originUrl = originRequest.url();  HttpUrl.Builder newBuilder;   String hostType = originRequest.header(UrlConstants.Header.HOST);  System.out.println("hostType:" + hostType);  if (hostType != null && hostType.length() > 0) {   String hostValue = UrlManager.getInstance().getHost(hostType);   HttpUrl temp = HttpUrl.parse(hostValue);   if (temp == null) {    throw new IllegalArgumentException(hostType + "對應的host地址不合法:" + hostValue);   }   newBuilder = temp.newBuilder();  } else {   newBuilder = new HttpUrl.Builder()     .scheme(originUrl.scheme())     .host(originUrl.host())     .port(originUrl.port());  }  String restVersion = originRequest.header(UrlConstants.Header.REST_VERSION);  System.out.println("restVersion:" + restVersion);  if (restVersion == null) {   restVersion = UrlConstants.RestVersionCode.V2;  }  String restValue = UrlManager.getInstance().getRest(restVersion);  if (restValue.contains("/")) {   String[] paths = restValue.split("/");   for (String path : paths) {    newBuilder.addEncodedPathSegment(path);   }  } else {   newBuilder.addEncodedPathSegment(restValue);  }  for (int i = 0; i < originUrl.pathSegments().size(); i++) {   newBuilder.addEncodedPathSegment(originUrl.encodedPathSegments().get(i));  }   newBuilder.encodedPassword(originUrl.encodedPassword())    .encodedUsername(originUrl.encodedUsername())    .encodedQuery(originUrl.encodedQuery())    .encodedFragment(originUrl.encodedFragment());   HttpUrl newUrl = newBuilder.build();  System.out.println("newUrl:" + newUrl.toString());  Request newRequest = originRequest.newBuilder().url(newUrl).build();  return chain.proceed(newRequest); }}

為了能動態設置host, 我們需要一個map來存儲host 類型和值.

private Map<String, String> hostMap;private Map<String, String> restMap; private UrlManager() { hostMap = new HashMap<>(16); for (UrlConstants.Host host : UrlConstants.Host.values()) {  hostMap.put(host.getName(), host.getValue()); } restMap = new HashMap<>(); for (UrlConstants.Rest rest : UrlConstants.Rest.values()) {  restMap.put(rest.getVersion(), rest.getValue()); }} //更新host 的值public void setHost(String name, String value) { if (hostMap.containsKey(name)) {  HttpUrl httpUrl = HttpUrl.parse(value);  if (httpUrl == null) {   throw new IllegalArgumentException("要存入的Host " + name + "對應的value:"     + value + "不合法!");  }  hostMap.put(name, value); } else {  throw new NoSuchElementException("沒有找到已經定義的Host名稱:" + name + ",請先在" +    "net.devwiki.manager.UrlConstants.Host中定義!"); }} //根據host 獲取值public String getHost(String name) { if (!hostMap.containsKey(name)) {  throw new NoSuchElementException("沒有找到已經定義的Host名稱:" + name + ",請先在" +    "net.devwiki.manager.UrlConstants.Host中定義!"); } return hostMap.get(name);}

這樣就可以動態替換host 和 rest版本了.

4.測試運行

測試代碼:

private static void testRequest() { BaiduRest rest = new BaiduRest();  testDefault(rest);  testChangeHost(rest);  testChangePath(rest);  testChangeHostPath(rest);}

測試運行結果:

ostType:null
restVersion:null
newUrl:https://www.baidu.com/rest/v2/s?wd=123
九月 07, 2018 11:36:58 上午 okhttp3.internal.platform.Platform log
信息: --> GET https://www.baidu.com/rest/v2/s?wd=123 http/1.1
九月 07, 2018 11:36:58 上午 okhttp3.internal.platform.Platform log
信息: <-- 302 Found https://www.baidu.com/rest/v2/s?wd=123 (83ms, 154-byte body)
九月 07, 2018 11:36:58 上午 okhttp3.internal.platform.Platform log
信息: --> GET http://www.baidu.com/s?wd=123&tn=SE_PSStatistics_p1d9m0nf http/1.1
九月 07, 2018 11:36:58 上午 okhttp3.internal.platform.Platform log
信息: <-- 200 OK http://www.baidu.com/s?wd=123&tn=SE_PSStatistics_p1d9m0nf (46ms, unknown-length body)
hostType:DEV
restVersion:null
newUrl:https://dev.baidu.com/rest/v2/s?wd=123
九月 07, 2018 11:36:58 上午 okhttp3.internal.platform.Platform log
信息: --> GET https://dev.baidu.com/rest/v2/s?wd=123 http/1.1
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: <-- 302 Found https://dev.baidu.com/rest/v2/s?wd=123 (154ms, 154-byte body)
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: --> GET http://developer.baidu.com/error.html http/1.1
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: <-- 301 Moved Permanently http://developer.baidu.com/error.html (18ms, 73-byte body)
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: --> GET https://developer.baidu.com/error.html http/1.1
hostType:null
restVersion:V1
newUrl:https://www.baidu.com/rest/v1/s?wd=123
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: <-- 200 OK https://developer.baidu.com/error.html (157ms, unknown-length body)
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: --> GET https://www.baidu.com/rest/v1/s?wd=123 http/1.1
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: <-- 302 Found https://www.baidu.com/rest/v1/s?wd=123 (46ms, 154-byte body)
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: --> GET http://www.baidu.com/s?wd=123&tn=SE_PSStatistics_p1d9m0nf http/1.1
九月 07, 2018 11:36:59 上午 okhttp3.internal.platform.Platform log
信息: <-- 200 OK http://www.baidu.com/s?wd=123&tn=SE_PSStatistics_p1d9m0nf (54ms, unknown-length body)
hostType:PRIVATE
restVersion:PRIVATE
newUrl:https://private.bidu.com/rest/private/s?wd=123

結果按照設置進行了host 和 rest 的變更.

5. 項目代碼

項目代碼地址: Dev-Wiki/OkHttpDemo

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线精品免播放器视频| 日本一区二区在线免费播放| 日韩美女在线看| 国产亚洲精品91在线| 国内精品视频久久| 久久久久久久久久久久av| 黑人欧美xxxx| 欧美激情精品久久久久久黑人| 奇米四色中文综合久久| 精品久久久一区二区| 国产男女猛烈无遮挡91| 国产一区二区三区丝袜| 色悠悠久久88| 国产精品久久久久久久久久久久久久| 992tv成人免费影院| 国产午夜精品全部视频在线播放| 国产精品一区二区三区在线播放| 岛国av午夜精品| 国产黑人绿帽在线第一区| 国产在线98福利播放视频| 中文字幕自拍vr一区二区三区| 亚洲三级 欧美三级| 久久亚洲精品一区| 欧美超级乱淫片喷水| 亚洲人成在线观看网站高清| 欧美激情精品久久久久久大尺度| 亚洲大胆人体av| 成人免费大片黄在线播放| 日韩在线免费av| 中文字幕在线观看亚洲| 日韩av免费在线看| 亚洲视频精品在线| 亚洲精选中文字幕| 国产在线视频2019最新视频| 91理论片午午论夜理片久久| 亚洲另类图片色| 在线亚洲午夜片av大片| 亚洲91精品在线| 国产亚洲一区二区精品| 狠狠久久五月精品中文字幕| 91手机视频在线观看| 2021久久精品国产99国产精品| 欧美一级大片在线免费观看| 欧美丰满老妇厨房牲生活| 国产成人短视频| 国产成人自拍视频在线观看| 久久精品视频在线播放| 国产成人精品视频| 91亚洲精华国产精华| 日韩av一区在线| 亚洲乱码国产乱码精品精天堂| 精品偷拍一区二区三区在线看| 午夜精品久久17c| 91精品久久久久久久久| 久久偷看各类女兵18女厕嘘嘘| 国产精品国产三级国产专播精品人| 亚洲欧美日韩在线一区| 国产午夜精品美女视频明星a级| 91视频国产精品| 日韩在线视频免费观看高清中文| 欧美激情成人在线视频| 国产精品久久二区| 国产在线观看精品一区二区三区| 91av在线播放| 久久视频免费在线播放| 国产中文日韩欧美| 日韩欧美一区二区在线| 国产日产久久高清欧美一区| 亚洲丝袜av一区| 成人网在线视频| 91av中文字幕| 欧美极品美女视频网站在线观看免费| 91精品视频在线播放| 欧美重口另类videos人妖| 最近2019年好看中文字幕视频| 国产精品免费福利| 欧美成人精品一区二区| 视频在线观看一区二区| 亚洲欧美另类中文字幕| 97超碰国产精品女人人人爽| 日本久久久久久| 国产精品第七十二页| 亚洲成人精品视频在线观看| 亚洲精品综合久久中文字幕| 国产日韩欧美电影在线观看| 久久久久久久999精品视频| 亚洲精品综合精品自拍| 久久国产精品久久久| 亚洲一区二区免费| 黑人狂躁日本妞一区二区三区| 久久免费少妇高潮久久精品99| 国产91在线高潮白浆在线观看| 亚洲欧美制服综合另类| 亚洲在线免费视频| 日本最新高清不卡中文字幕| 国产精品综合不卡av| 中文字幕精品久久| 精品毛片三在线观看| 欧美一级电影免费在线观看| 中文字幕日韩高清| 欧美日韩高清区| 久热精品视频在线免费观看| 国内精品小视频在线观看| 在线观看中文字幕亚洲| 久久久久亚洲精品成人网小说| 成人xvideos免费视频| 亚洲天堂av网| 国产91成人在在线播放| 日韩美女视频免费在线观看| 国产精品一区av| 国产日本欧美一区| 91精品国产综合久久香蕉922| 亚洲国产欧美在线成人app| 色综合久久悠悠| 中文字幕亚洲欧美日韩在线不卡| 91香蕉国产在线观看| 精品亚洲国产成av人片传媒| 91精品久久久久久久久不口人| 国模私拍视频一区| 亚洲网站在线观看| 在线观看国产欧美| 热久久免费国产视频| 久久久女人电视剧免费播放下载| 欧美在线视频一区| 日韩一中文字幕| 亚洲激情在线视频| 91精品国产91久久久久久最新| 亚洲第一av在线| 91老司机精品视频| 在线丨暗呦小u女国产精品| 欧美亚洲第一区| 国产亚洲视频在线观看| 久久久久北条麻妃免费看| 一个人看的www欧美| 国产精品欧美风情| 日韩中文字幕在线免费观看| 日韩最新中文字幕电影免费看| 亚洲视频axxx| 青青久久av北条麻妃黑人| 色综合久久久888| 成人久久久久久久| 亚洲aaaaaa| 成人免费福利在线| 国产成人av网址| 成人激情在线观看| 精品国内产的精品视频在线观看| 日韩久久免费电影| 久久成人综合视频| 国产午夜精品一区理论片飘花| 亚洲性av在线| 欧美成在线观看| 精品国产区一区二区三区在线观看| 中文字幕久热精品视频在线| 亚洲a区在线视频| 国产99久久久欧美黑人| 日韩女优人人人人射在线视频| 91成品人片a无限观看| 久久久国产精品一区| 午夜精品久久久久久久99黑人| 亚洲欧美日韩另类| 91精品国产电影| 伊人久久综合97精品| 久久香蕉国产线看观看网| 欧美一级淫片aaaaaaa视频|