我们在开发的过程中,有时候会遇见需要动态切换URL的这种需求,借此记录一下。
首先贴出代码。
package com.example.administrator.mytestretrofit.http; import android.util.Log; import com.example.mylibrary.app.Constants; import com.example.administrator.mytestretrofit.http.remote.RemoteService; import com.example.mylibrary.http.engine.ExceptionEngine; import com.example.mylibrary.http.engine.RetryWhenNetworkException; import com.example.mylibrary.http.gson.IJson; import com.example.mylibrary.http.interceptor.MoreBaseUrlInterceptor; import com.example.mylibrary.http.subscriber.ProgressSubscriber; import com.example.mylibrary.utils.log.LogUtils; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Func1; import rx.schedulers.Schedulers; /** * http交互处理类 */ public class HttpManager { public static final String TAG = "HttpManager-------"; /*超时设置*/ private static final int DEFAULT_TIMEOUT = 6; private RemoteService httpService; private volatile static HttpManager INSTANCE; //构造方法私有 private HttpManager() { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { LogUtils.d(TAG,message); } }); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient().newBuilder() .connectTimeout(5, TimeUnit.SECONDS) //设置超时时间 10s .readTimeout(5, TimeUnit.SECONDS) //设置读取超时时间 .writeTimeout(5, TimeUnit.SECONDS) //设置写入超时时间 .addInterceptor(httpLoggingInterceptor)//添加一个拦截器 .addInterceptor(new MoreBaseUrlInterceptor()); OkHttpClient okClient = builder.build(); Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(IJson.gson)) // 使用Gson作为数据转换器 .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器 .client(okClient) .baseUrl(Constants.Base.BASE_URL_RELEASE)//获取 最终的base url /*.baseUrl(App.getInstance().getRealUrl())//此处选择 api 的真实网址*/ .build(); httpService = retrofit.create(RemoteService.class); } //获取单例 public static HttpManager getInstance() { if (INSTANCE == null) { synchronized (HttpManager.class) { if (INSTANCE == null) { INSTANCE = new HttpManager(); } } } return INSTANCE; } /** * 处理http请求 * * @param basePar 封装的请求数据 */ public void doHttpDeal(BaseEntity basePar) { //if (basePar.isShowProgress()) ProgressSubscriber subscriber = new ProgressSubscriber(basePar.getListener() , basePar.getContext() , basePar.isShowProgress() , basePar.isCancel() , basePar.isShowError() , basePar.getMsg()); basePar.getObservable(httpService) /*失败后的retry配置*/ .retryWhen(new RetryWhenNetworkException()) /*生命周期管理*/ .compose(basePar.getTransformer()) // .map(new_icon ServerResponseFunc<String>())//拦截服务器返回的错误 .onErrorResumeNext(new HttpResponseFunc<String>()) //HttpResultFunc()为拦截onError事件的拦截器 /*http请求线程*/ .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) /*回调线程*/ .observeOn(AndroidSchedulers.mainThread()) /*结果判断*/ // .map(basePar) .subscribe(subscriber); } private class HttpResponseFunc<T> implements Func1<Throwable, Observable<T>> { @Override public Observable<T> call(Throwable throwable) { Log.e(TAG,"----这是啥异常?--"); throwable.printStackTrace(); return Observable.error(ExceptionEngine.handleException(throwable)); //ExceptionEngine为处理异常的驱动器 } } }
其中的关键在于这行代码的设置:.addInterceptor(new MoreBaseUrlInterceptor());
下面贴出这个类:
package com.example.mylibrary.http.interceptor; import com.example.mylibrary.app.App; import com.example.mylibrary.app.Constants; import com.example.mylibrary.utils.cookie.UserUtils; import java.io.IOException; import java.util.List; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class MoreBaseUrlInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { //获取原始的originalRequest Request originalRequest = chain.request(); //获取老的url HttpUrl oldUrl = originalRequest.url(); //获取originalRequest的创建者builder Request.Builder builder = originalRequest.newBuilder(); //获取头信息的集合如:manage,mdffx List<String> urlnameList = originalRequest.headers("urlname"); if (urlnameList != null && urlnameList.size() > 0) { //删除原有配置中的值,就是namesAndValues集合里的值 builder.removeHeader("urlname"); //获取头信息中配置的value,如:manage或者mdffx String urlname = urlnameList.get(0); HttpUrl baseURL = null; //根据头信息中配置的value,来匹配新的base_url地址 // FIXME: 2019/5/30 此处可以根据实际需求 进行 baseURL的切换 if ("common_base_url_header".equals(urlname)) { baseURL = HttpUrl.parse(Constants.Base.BASE_URL_RELEASE); } else if ("old_php_base_url_header".equals(urlname)) { //baseURL = HttpUrl.parse(App.getInstance().setBaseUrlOldPhp()); } else if ("java".equals(urlname)) { baseURL = HttpUrl.parse(Constants.Base.BASE_URL_RELEASE); } //重建新的HttpUrl,需要重新设置的url部分 HttpUrl newHttpUrl = oldUrl.newBuilder() .scheme(baseURL.scheme())//http协议如:http或者https .host(baseURL.host())//主机地址 .port(baseURL.port())//端口 .build(); String header = originalRequest.header("NoToken"); if (header == null) { builder.addHeader("Cookie", UserUtils.getCokeValue()) .addHeader("Content-Type", "application/x-www-form-urlencoded") .addHeader("X-Requested-With", "XMLHttpRequest"); } //获取处理后的新newRequest Request newRequest = builder.url(newHttpUrl).build(); return chain.proceed(newRequest); } else { return chain.proceed(originalRequest); } } }
代码的关键在于此处,根据不同的tag 对应不同的切换的URL地址。
此处可以贴出,网络请求的类,进行理解使用。
根据上面设置的tag ,在remote类中,添加header 进行区分,亲测有效。
此处为添加请求头,参数。大家可以根据自己的项目需求,灵活使用。