我们在开发的过程中,有时候会遇见需要动态切换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 进行区分,亲测有效。
此处为添加请求头,参数。大家可以根据自己的项目需求,灵活使用。