使用 Retrofit + okHttp 网络请求中,动态切换测试服和正式服(BaseUrl)

本文介绍了一种在Retrofit中动态切换BaseUrl的方法,通过自定义OKHttp拦截器,根据开关状态改变请求的主域名,实现在debug版本中快速切换正式服和测试服,提高开发效率。

转载请注明出处:https://blog.youkuaiyun.com/DemoKui/article/details/83115501

项目需求

相信在项目开发中,一般公司都会有自己的开发测试服和生产环境正式服,例如:

  • http://damon.com // 正式服
  • http://test.com // 测试服

而一般情况下正式服和测试服只是前缀不同,后面的接口路径不变,就好比只是 damon 和 test 的差异而已,平时打包时手动注释掉一个就好了,但是经常改完 bug 或者开发完一个功能,我们迫不及待的赶紧打个包去 leader 那儿展示自己的成果,但是,领导不一会儿就说,“这是测试服的,打个正式服的出来”、“这是正式服的,打个测试服的出来”,还有测试妹子也是一样,也会经常提这些没技术含量而又不得不做的操作,那么我是否可以在 debug 版本时留一个只有我们内部人员知道的切换入口,随时随地的切换正式服和测试服呢?

这样一来,我们就不用这么麻烦的不停的打包,好了,需求明确了,就是在 debug 版本中随时切换主域名。

实现思路

据说这个更改 BaseUrl 操作 Api 之前 Retrofit 是存在的,后来删除了,不知道为什么?不管了,自己搞定吧。

在 OKHttp3 中有拦截器 Interceptor,这个拦截器中有一个 Request 类,在这个类中有一个成员变量 HttpUrl,而这个 HttpUrl 就是我们每次请求服务器的地址,那么既然能拿到这个地址,问题就好办了,拿到它之后根据开关切换状态更改这个 HttpUrl ,更改完了之后再把新的地址设置回去,问题就完美解决了。

好了,接下来开始实现吧。

代码实现

我们先定义一个开关


  public static Boolean isTest = true;     // 是否是测试服  默认是测试服

然后自定义拦截器 Interceptor

public class TestInterceptor implements Interceptor {

    public TestInterceptor() {
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();
        // 这里是拦截下来的 url ,注意:这个 url 是全量url,也就是完整的url,并不是单纯的主域名地址。
        String url = request.url().toString();
        if(App.isTest ) {
            // 如果是测试服并且拦截下来的url中还包含正式服,将url前缀替换成测试服的url前缀
            if (url.contains("demon")) {
                url = url.replace("demon", "test");
            }
        }
        // 将新的 url 再设置回去
        request = requestBuilder.url(url).build();
        return chain.proceed(request);
    }
}

然后在 UI 入口处控制这个开关 isTest 的状态值就好了。

感谢:
参考文献:https://blog.youkuaiyun.com/qq_20230661/article/details/69548083

PS: 这种算是很简单的动态配置 BaseUrl 了,其实项目中海油很多这样的需求,只是主域名不仅仅是两个这么简单,比如一个大项目中用户可能是一个单独的主机,购物车又是另一个主机,支付又是另一个主机,等等等等这样的多主机需求,不过还是在拦截器中动心思,以及接口上 @Headers 注解的使用,还没搞懂待研究,有经验的朋友希望多多分享。

=============================================================

2019-12-26 更新

之前写的那个虽说可以解决测试服和正式服的需要,但是满足不了所有场景,最近在迁移公司的 eclipse 项目转 Studio(鬼知道现在才迁移,特么还是我自愿的,公司压一直不愿意重构,老掉牙的项目),在迁移过程中需要更换网络框架,就出现了多台服务的情况,发现之前写的动态切换 BaseUrl 的方法满足不了项目中的需求,于是又开始面向百度编程,发现了一个好文章。

传送门:Retrofit 动态修改BaseUrl

这篇文章写得清晰明了易懂,收藏了。

<think>我们正在回答用户关于在安卓中使用RetrofitOkHttpGson进行网络请求数据解析的问题。根据用户提供的引用资料,我们需要整合一个清晰的教程,包括初始化RetrofitOkHttp、创建API务、发起网络请求以及使用Gson解析数据。步骤分解:1.添加依赖:在build.gradle文件中添加RetrofitOkHttp、GsonRxJava(可选)的依赖。2.创建数据模型:根据API返回的JSON结构创建Java/Kotlin数据类。3.创建API务接口:使用Retrofit注解定义网络请求方法。4.配置RetrofitOkHttp:设置BaseURL、超时时间、拦截器(如日志拦截器)以及Gson转换器。5.发起网络请求:创建API务实例并调用方法,处理响应(可以使用回调、RxJava或协程)。我们将提供一个示例代码,展示如何封装一个网络请求工具类。注意:用户引用中提到了动态配置拦截器,我们也会在示例中体现。示例代码将使用Kotlin编写(目前Android开发的主流语言),但也会提供Java版本的说明。现在开始构建回答。</think>### 安卓 Retrofit + OkHttp + Gson 网络请求与解析教程 在安卓开发中,**Retrofit**(负责 API 封装)、**OkHttp**(负责底层网络请求 **Gson**(负责 JSON 解析)是高效网络请求的黄金组合。以下是完整实现步骤: --- #### 1. 添加依赖 (`build.gradle`) ```gradle dependencies { // Retrofit 核心库 implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Gson 转换器 implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // OkHttp 网络库 implementation 'com.squareup.okhttp3:okhttp:4.10.0' // 日志拦截器(调试用) implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0' } ``` --- #### 2. 创建数据模型(Gson 解析) 假设 API 返回 JSON: ```json { "name": "张三", "age": 25, "email": "zhangsan@example.com" } ``` 对应 Kotlin 数据类: ```kotlin data class User( @SerializedName("name") val name: String, @SerializedName("age") val age: Int, @SerializedName("email") val email: String ) ``` --- #### 3. 配置 Retrofit OkHttp ```kotlin object RetrofitClient { private const val BASE_URL = "https://api.example.com/" // 创建 OkHttp 实例(带日志拦截器) private val okHttpClient = OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().setLevel(Level.BODY)) // 打印请求日志 .connectTimeout(30, TimeUnit.SECONDS) .build() // 构建 Retrofit 实例 val instance: Retrofit by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) // 绑定 OkHttp .addConverterFactory(GsonConverterFactory.create()) // 绑定 Gson .build() } } ``` --- #### 4. 定义 API 务接口 ```kotlin interface ApiService { @GET("user/profile") suspend fun getUserProfile(): User // 直接返回数据模型 @POST("user/update") suspend fun updateUser(@Body user: User): Response<Unit> // 发送对象 } ``` --- #### 5. 发起网络请求使用协程示例) ```kotlin // 创建 API 务实例 val apiService = RetrofitClient.instance.create(ApiService::class.java) // 在协程中发起请求 lifecycleScope.launch { try { val user = apiService.getUserProfile() Log.d("Network", "用户数据: ${user.name}, ${user.age}") // 更新UI:textView.text = user.name } catch (e: Exception) { Log.e("Network", "请求失败: ${e.message}") } } ``` --- #### 关键组件说明 | 组件 | 作用 | |-------------|----------------------------------------------------------------------| | **OkHttp** | 处理底层 HTTP 请求/响应,支持拦截器动态修改请求[^2] | | **Retrofit**| 将 API 接口转换为网络调用,自动生成请求实现[^1] | | **Gson** | 通过 `GsonConverterFactory` 自动序列化 JSON ↔ 对象[^4] | | 日志拦截器 | 调试时输出请求/响应日志(生产环境需移除) | --- #### 高级技巧 1. **统一错误处理**:通过拦截器捕获 HTTP 错误码 ```kotlin okHttpClient.addInterceptor { chain -> val response = chain.proceed(chain.request()) if (!response.isSuccessful) throw HttpException(response) // 抛出统一异常 response } ``` 2. **动态修改请求头**:在拦截器中添加认证信息 ```kotlin okHttpClient.addInterceptor { chain -> val newRequest = chain.request().newBuilder() .addHeader("Authorization", "Bearer $token") .build() chain.proceed(newRequest) } ``` 3. **多 Base URL 管理**:使用 Retrofit 的 `@Url` 注解 ```kotlin @GET suspend fun fetchData(@Url fullUrl: String): Response ``` > **提示**:结合 RxJava 可简化异步操作,使用 `addCallAdapterFactory(RxJava3CallAdapterFactory.create())` 启用 Rx 支持[^3] --- ### 典型架构示意图 ``` [Android App] → [Retrofit 接口调用] → [OkHttp 发送请求] → [务器返回 JSON] → [Gson 自动解析为对象] ``` [^1]: Retrofit 动态配置机制允许运行时修改网络参数 [^2]: OkHttpRetrofit 提供高效网络层支持 [^3]: RxJava 可优化异步请求流程 [^4]: Gson 转换器实现自动数据解析 --- ### 相关问题 1. 如何处理 Retrofit网络请求超时重试机制? 2. 怎样用拦截器实现全局的请求日志记录错误监控? 3. Retrofit 如何支持多种数据格式(如 XML、Protobuf)的解析? 4. 在多模块项目中如何统一管理网络请求配置? 5. 如何用 MockWebServer 测试 Retrofit 网络请求
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值