在实际开发中经常会遇到多个BaseUrl的问题,一般的处理方式是创建多个retrofit实例,那有没有办法进行动态的切换BaseUrl ?能不能使用Interceptor来解决这个问题? 答案是可以的。
看代码:
**
* change baseUrl by api header setting
*/
public class MultiDomainInterceptor implemants Intercaptor {
private static final String TAG = "MultiDomainInterceptor";
@Override
public Response intercept(Chain chain) throws IOException {
if (isIntercept(chain)) {
return chain.proceed(processRequest(chain.request()));
}else {
return chain.proceed(chain.request());
}
}
/**
* @param request {@link Request}
* @return {@link Request}
*/
public Request processRequest(@NonNull Request request) {
if (request.headers(BASE_URL).size() > 0) {
String baseUrl = getBaseUrlFromHeaders(request);
LogUtil.d(TAG, request);
if (!TextUtils.isEmpty(baseUrl)) {
Request.Builder requestBuilder = request.newBuilder();
requestBuilder.removeHeader(BASE_URL);
HttpUrl domainUrl = HttpUrl.parse(baseUrl);
HttpUrl.Builder builder = request.url().newBuilder();
HttpUrl parsedHttpUrl = builder
.scheme(domainUrl.scheme())
.host(domainUrl.host())
.port(domainUrl.port())
.build();
requestBuilder.url(parsedHttpUrl);
Request parsedRequest;
if (request.tag() != null) {
parsedRequest = requestBuilder.tag(null).build();
} else {
parsedRequest = requestBuilder.build();
}
return parsedRequest;
}
}
return request;
}
/**
* get BaseUrl from header
*
* @param request
* @return
*/
private String getBaseUrlFromHeaders(Request request) {
List<String> headers = request.headers(BASE_URL);
if (headers == null || headers.size() == 0)
return null;
if (headers.size() > 1)
throw new IllegalArgumentException("Only one BaseUrl in the headers");
return request.header(BASE_URL);
}
private boolean isIntercept(Chain chain) throws IOException{
return true;
}
}
这里核心的代码主要是在processRequest 里面,这里面主要处理的url, tag,header的处理,下面说一下url 和 tag的处理过程,header比较简单:
url里面保存了request的地址信息, 而tag的处理可以看Request中的注释:
/**
* Attaches {@code tag} to the request. It can be used later to cancel the request. If the tag
* is unspecified or null, the request is canceled by using the request itself as the tag.
*/
public Builder tag(Object tag) {
this.tag = tag;
return this;
}
因此上面代码中将转换后的tag赋值为空, 这种设置可能有问题,但是验证时正常,有了解的朋友麻烦指正
下面看一下处理前后的request对象的区别:
处理前
{
"headers": {
"namesAndValues": ["base_url", "http://localhost:8080"]
},
"method": "GET",
"url": {
"host": "xxxxxxxxx.com",
"password": "",
"pathSegments": ["person", "list"],
"port": 80,
"scheme": "http",
"url": "http://xxxxxxxxx.com/person/list",
"username": ""
}
}
处理后
{
"headers": {
"namesAndValues": []
},
"method": "GET",
"url": {
"host": "localhost:8080",
"password": "",
"pathSegments": ["person", "list"],
"port": 8080,
"scheme": "http",
"url": "http://localhost:8080/person/list",
"username": ""
}
}
网友评论