Kotlin实现Retrofit 动态修改 BaseUrl(通过拦截器的方式动态修改baseUrl)

本文介绍了如何在Kotlin项目中使用Retrofit通过拦截器动态改变HTTP请求的baseUrl,通过截取并替换URL中的协议、服务器地址和端口号,实现实时配置。

工作中记录一下Kotlin动态切换URL的这种需求
这里解决动态修改baseUrl的方法是:在设置请求头的拦截器里面,动态获取了接口地址,例如:http://127.0.0.1:8000,然后将该url进行字符串截取获取http协议,ip服务器地址,以及端口号。
获取请求的url然后将拿到的http协议,服务器地址和端口号进行重新设置并返回,达到动态修改baseUrl的目的

package com.smart.sanitation.net

import com.smart.sanitation.MainApplication
import com.smart.sanitation.config.globalData
import com.smart.sanitation.net.gson.MGson
import com.smart.sanitation.net.utils.LogUtils
import com.smart.sanitation.ui.home.common.DictionaryConstant
import okhttp3.*
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

var ip = ""
/**
 * 接口请求工厂
 */
object ApiFactory {

    // 日志拦截器
    private val mLoggingInterceptor: Interceptor by lazy { LoggingInterceptor() }

    // 请求头添加session
    private val mHeadersInterceptor: Interceptor by lazy { HeadersInterceptor() }

    // OkHttpClient客户端
    private val mClient: OkHttpClient by lazy { newClient() }

    /**
     * 创建API Service接口实例
     */
    fun <T> createService(baseUrl: String, clazz: Class<T>): T =
        Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(mClient)
            .addConverterFactory(GsonConverterFactory.create(MGson.getInstance()))
            .build().create(clazz)

    /**
     * OkHttpClient客户端
     */
    private fun newClient(): OkHttpClient = OkHttpClient.Builder().apply {
        connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时
        readTimeout(30, TimeUnit.SECONDS)// 读取时间:10s超时
        writeTimeout(30, TimeUnit.SECONDS)// 写入时间:10s超时
        addInterceptor(mHeadersInterceptor)
        if (MainApplication.isDebugMode) addInterceptor(mLoggingInterceptor)// 仅debug模式启用日志过滤器
    }.build()

    /**
     * 设置请求头
     */
    private class HeadersInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            val original: Request = chain.request()
            val requestBuilder: Request.Builder = original.newBuilder()
                .addHeader("Authorization", globalData.token)
                .addHeader("isToken", globalData.isToken.toString())
                .addHeader("TENANT-ID", globalData.tenantId)
            val request: Request = requestBuilder.build()
            //这里if我是用于默认url不需要更改baseUrl的判断,不需要此业务可去除,不影响
            if (DictionaryConstant.isLogin && ip != DictionaryConstant.selectIpServer) {
                val lastIndexOf = DictionaryConstant.selectIpServer.lastIndexOf(":")
                val indexOf = DictionaryConstant.selectIpServer.indexOf("://")
                val http = DictionaryConstant.selectIpServer.substring(0, 4)
                val ip = DictionaryConstant.selectIpServer.substring(indexOf + 3, lastIndexOf)
                val port = DictionaryConstant.selectIpServer.substring(lastIndexOf + 1)
                //重建新的HttpUrl,修改需要修改的url部分
                val newHttpUrl = original.url
                    .newBuilder()
                    .scheme(http)//更换http协议如:http或者https
                    .host(ip)//更换主机地址
                    .port(port.toInt())//更换端口
                    .build()
                DictionaryConstant.isLogin = false
                //返回处理后的新newRequest
                return chain.proceed(requestBuilder.url(newHttpUrl).build());
            }

            return chain.proceed(request)
        }
    }



    /**
     * 日志拦截器
     */
    private class LoggingInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            val builder = StringBuilder()
            val startTime = System.nanoTime()
            val response: Response = with(chain.request()) {
                builder.append(method + "\n")
                builder.append("Sending request\n$url")
                if (method == "POST") {
                    builder.append("?")
                    when (val body = body) {
                        is FormBody -> {
                            for (j in 0 until body.size) {
                                builder.append(body.name(j) + "=" + body.value(j))
                                if (j != body.size - 1) {
                                    builder.append("&")
                                }
                            }
                        }
                        is MultipartBody -> {}
                    }
                }
                builder.append("\n").append(headers)
                LogUtils.v(builder.toString())
                chain.proceed(this)
            }
            builder.clear()
            builder.append("Received response in " + (System.nanoTime() - startTime) / 1e6 + "ms\n")
            builder.append("code" + response.code + "\n")
            LogUtils.v(builder.toString())
            return response
        }
    }
}

这里关键性代码,核心代码只需要这一部分即可:

 //重建新的HttpUrl,需要修改的url部分
                val newHttpUrl = original.url
                    .newBuilder()
                    .scheme(http)//更换http协议如:http或者https
                    .host(ip)//更换主机地址
                    .port(port.toInt())//更换端口
                    .build()
                DictionaryConstant.isLogin = false
                //返回处理后的新newRequest
                return chain.proceed(requestBuilder.url(newHttpUrl).build());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值