欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何動(dòng)態(tài)改變Retrofit的base url和rest版本詳解

 更新時(shí)間:2018年09月10日 10:03:39   作者:devwiki  
這篇文章主要給大家介紹了關(guān)于如何動(dòng)態(tài)改變Retrofit的base url和rest版本的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

概述

隨著Google對(duì)HttpClient 摒棄,和Volley的逐漸沒落,OkHttp開始異軍突起,而Retrofit則對(duì)okHttp進(jìn)行了強(qiáng)制依賴。

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

如果看源碼會(huì)發(fā)現(xiàn)其實(shí)質(zhì)上就是對(duì)okHttp的封裝,使用面向接口的方式進(jìn)行網(wǎng)絡(luò)請(qǐng)求,利用動(dòng)態(tài)生成的代理類封裝了網(wǎng)絡(luò)接口請(qǐng)求的底層,

其將請(qǐng)求返回javaBean,對(duì)網(wǎng)絡(luò)認(rèn)證 REST API進(jìn)行了很好對(duì)支持此,使用Retrofit將會(huì)極大的提高我們應(yīng)用的網(wǎng)絡(luò)體驗(yàn)。

REST

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

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

RESTful架構(gòu)都滿足以下規(guī)則:

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

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

(3)客戶端通過四個(gè)HTTP動(dòng)詞,對(duì)服務(wù)器端資源進(jìn)行操作,實(shí)現(xiàn)”表現(xiàn)層狀態(tài)轉(zhuǎn)化”。

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

1. 需求與前提

base url

默認(rèn)base url: https://cloud.devwiki.net

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

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

rest 版本

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

需求點(diǎn)

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

2. 實(shí)現(xiàn)思路

okhttp 可以添加攔截器, 可在發(fā)起訪問前進(jìn)行攔截, 通常我們會(huì)在 攔截器中統(tǒng)一添加 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());
 }
}

同理我們也可以在所有請(qǐng)求中添加統(tǒng)一的uuid 或者 key 進(jìn)行防劫持或者認(rèn)證. 比如:

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

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

3. 實(shí)現(xiàn)過程

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

設(shè)置一個(gè)默認(rèn)的 host 和 rest 版本, 然后在需要更改host和rest 版本的請(qǐng)求接口處添header, 根據(jù)header設(shè)置來變更.

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 + "對(duì)應(yīng)的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);
 }
}

為了能動(dòng)態(tài)設(shè)置host, 我們需要一個(gè)map來存儲(chǔ)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 + "對(duì)應(yīng)的value:"
     + value + "不合法!");
  }
  hostMap.put(name, value);
 } else {
  throw new NoSuchElementException("沒有找到已經(jīng)定義的Host名稱:" + name + ",請(qǐng)先在" +
    "net.devwiki.manager.UrlConstants.Host中定義!");
 }
}
 
//根據(jù)host 獲取值
public String getHost(String name) {
 if (!hostMap.containsKey(name)) {
  throw new NoSuchElementException("沒有找到已經(jīng)定義的Host名稱:" + name + ",請(qǐng)先在" +
    "net.devwiki.manager.UrlConstants.Host中定義!");
 }
 return hostMap.get(name);
}

這樣就可以動(dòng)態(tài)替換host 和 rest版本了.

4.測試運(yùn)行

測試代碼:

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

測試運(yùn)行結(jié)果:

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

結(jié)果按照設(shè)置進(jìn)行了host 和 rest 的變更.

5. 項(xiàng)目代碼

項(xiàng)目代碼地址: Dev-Wiki/OkHttpDemo (本地下載

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Java 時(shí)間格式轉(zhuǎn)換之impleDateFormat與Data API解析與使用

    Java 時(shí)間格式轉(zhuǎn)換之impleDateFormat與Data API解析與使用

    想必大家對(duì) SimpleDateFormat 并不陌生。SimpleDateFormat 是 Java 中一個(gè)非常常用的類,他是以區(qū)域敏感的方式格式化和解析日期的具體類。 它允許格式化 (date -> text)、語法分析 (text -> date)和標(biāo)準(zhǔn)化
    2021-11-11
  • JAVA像SQL一樣對(duì)List對(duì)象集合進(jìn)行排序

    JAVA像SQL一樣對(duì)List對(duì)象集合進(jìn)行排序

    這篇文章主要介紹了JAVA像SQL一樣對(duì)List對(duì)象集合進(jìn)行排序的實(shí)現(xiàn)方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • java迷宮算法的理解(遞歸分割,遞歸回溯,深搜,廣搜)

    java迷宮算法的理解(遞歸分割,遞歸回溯,深搜,廣搜)

    本文主要使用的算法(自動(dòng)生成地圖:遞歸分割法、遞歸回溯法;尋找路徑:深度優(yōu)先、廣度優(yōu)先算法),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2021-06-06
  • Java?異常機(jī)制Exception和自定義異常

    Java?異常機(jī)制Exception和自定義異常

    這篇文章主要介紹了Java?異常機(jī)制Exception+自定義異常,異常分三種檢查性異常、運(yùn)行時(shí)異常、錯(cuò)誤ERROR,下文對(duì)其更多詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-05-05
  • Mybatis-plus 批量插入太慢的問題解決(提升插入性能)

    Mybatis-plus 批量插入太慢的問題解決(提升插入性能)

    公司使用的Mybatis-Plus操作SQL,用過Mybatis-Plus的小伙伴一定知道他有很多API提供給我們使用,但是批量插入大數(shù)據(jù)太慢應(yīng)該怎么解決,本文就詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-11-11
  • Java線程池submit阻塞獲取結(jié)果的實(shí)現(xiàn)原理詳解

    Java線程池submit阻塞獲取結(jié)果的實(shí)現(xiàn)原理詳解

    Java線程池中提交任務(wù)運(yùn)行,通常使用execute()方法就足夠了。那如果想要實(shí)現(xiàn)在主線程中阻塞獲取線程池任務(wù)運(yùn)行的結(jié)果,該怎么辦呢?本文就來和大家一起討論討論
    2022-10-10
  • Java中的字符型文件流FileReader和FileWriter詳細(xì)解讀

    Java中的字符型文件流FileReader和FileWriter詳細(xì)解讀

    這篇文章主要介紹了Java中的字符型文件流FileReader和FileWriter詳細(xì)解讀,與字節(jié)型文件流不同,字節(jié)型文件流讀取和寫入的都是一個(gè)又一個(gè)的字節(jié),而字符型文件流操作的單位是一個(gè)又一個(gè)的字符,字符型流認(rèn)為一個(gè)字母是一個(gè)字符,而一個(gè)漢字也是一個(gè)字符,需要的朋友可以參考下
    2023-10-10
  • 超詳細(xì)解釋Java反射

    超詳細(xì)解釋Java反射

    本文非常詳細(xì)的講解了java反射具體的內(nèi)容以及使用,java反射在現(xiàn)今的使用中很頻繁,希望此文可以幫大家解答疑惑,可以幫助大家理解
    2021-11-11
  • SpringBoot?HikariCP配置項(xiàng)及源碼解析

    SpringBoot?HikariCP配置項(xiàng)及源碼解析

    這篇文章主要為大家介紹了SpringBoot?HikariCP配置項(xiàng)及源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼

    SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼

    本篇文章主要介紹了SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09

最新評(píng)論