HouseApi provideHouseApi() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new BasicDataInterceptor())
.addInterceptor(httpLoggingInterceptor)
.build();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Workflow.class, new WorkflowDeserializer())
.create();
return new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(Constants.URLS.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(HouseApi.class);
}
public class BasicDataInterceptor implements Interceptor{
@Override
public Response intercept(Chain chain) throws IOException {
Request originRequest = chain.request();
//chai中包含了请求相关的所有信息,我们可以在这里进行拦截后的//操作
return chain.proceed(newRequest);
}
}
但是…..
我们进行网络请求的时候,可能以不同的协议的形式请求,那么这个时候我们怎么写Intercept 比较合适呢?
public interface HouseApi {
@POST("v1/user/login")
@FormUrlEncoded
Observable> login(@Field("logincode") String loginCode,
@Field("password") String password);
@Multipart
@POST("v1/common/upload")
Observable> uploadFile(@PartMap Map params,
@Part MultipartBody.Part file);
}
这里的@Multipart 和@FormUrlEncoded 分别指定是MediaType 以”multipart”和”application/x-www-form-urlencoded”的网络协议进行request :
这个时候我们的需要根据不同的MediaType 协议进行拦截的处理
public class BasicDataInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originRequest = chain.request();
String mediaType = null;
try {
mediaType = originRequestBody.contentType().toString();
} catch (NullPointerException ignore) {
}
if (mediaType.startsWith("application/x-www-form-urlencoded")) {
//......
} else if (mediaType.startsWith("multipart/")) {
//......
} else {
return chain.proceed(originRequest);
}
//........
Request newRequest = builder
.post(RequestBody.create(MediaType.parse(mediaType), newBodyByteArray))
.build();
return chain.proceed(newRequest);
}
}
上述使用省略号的部分,就是根据不同情况和”application/x-www-form-urlencoded”与”multipart”的具体协议的定义,组装成合法的协议然后传输出去
以下是详细的BasicDataInterceptor 的内容:
public class BasicDataInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originRequest = chain.request();
if (!"POST".equals(originRequest.method())) {
return chain.proceed(originRequest);
}
RequestBody originRequestBody = originRequest.body();
String mediaType = null;
try {
mediaType = originRequestBody.contentType().toString();
} catch (NullPointerException ignore) {
}
if (mediaType == null) {
return chain.proceed(originRequest);
}
String appendBodyString;
if (mediaType.startsWith("application/x-www-form-urlencoded")) {
// handle form url
RequestBody appendRequestBody = getUrlencodedRequestBody();
appendBodyString = bodyToString(appendRequestBody) + "&";
} else if (mediaType.startsWith("multipart/")) {
//
MultipartBody multipartBody = (MultipartBody) originRequestBody;
String boundary = multipartBody.boundary();
MultipartBody appendRequestBody = getMultipartRequestBody();
appendBodyString = bodyToString(appendRequestBody);
appendBodyString = appendBodyString.replace(appendRequestBody.boundary(), boundary);
// 删除最后一行
appendBodyString = appendBodyString.substring(0, appendBodyString.length() - 1);
appendBodyString = appendBodyString.substring(0, appendBodyString.lastIndexOf('\n') + 1);
} else {
return chain.proceed(originRequest);
}
Request.Builder builder = originRequest.newBuilder();
byte[] newBodyByteArray = mergeRequestBody(originRequestBody, appendBodyString);
Request newRequest = builder
.post(RequestBody.create(MediaType.parse(mediaType), newBodyByteArray))
.build();
return chain.proceed(newRequest);
}
//应该注意网络传输的是二进制流,这里必然使用byte[]
public byte[] mergeRequestBody(RequestBody originRequestBody, String appendBodyString) {
final Buffer buffer = new Buffer();
try {
buffer.writeUtf8(appendBodyString);
originRequestBody.writeTo(buffer);
} catch (IOException e) {
e.printStackTrace();
}
return buffer.readByteArray();
}
private String bodyToString(final RequestBody request) {
try {
final RequestBody copy = request;
final Buffer buffer = new Buffer();
if (copy != null)
copy.writeTo(buffer);
else
return "";
return buffer.readUtf8();
} catch (final IOException e) {
return null;
}
}
private RequestBody getUrlencodedRequestBody() {
FormBody.Builder builder = new FormBody.Builder();
Map dataMap = getAppendDataMap();
for (String key : dataMap.keySet()) {
builder.add(key, dataMap.get(key));
}
return builder.build();
}
private MultipartBody getMultipartRequestBody() {
MultipartBody.Builder builder = new MultipartBody.Builder();
Map dataMap = getAppendDataMap();
for (String key : dataMap.keySet()) {
builder.addFormDataPart(key, dataMap.get(key));
}
return builder.build();
}
//每个网络请求必要的加密参数和公告的参数
private Map getAppendDataMap() {
ParameterEncryption paramsterEncryption = new ParameterEncryption();
String deviceModel = DeviceUtils.getModel();
// String deviceid = DeviceUtils.getDeviceID(); // TODO
int romType = DeviceUtils.getRomType();
String sysVersion = DeviceUtils.getSysVersion();
String verdor = DeviceUtils.getManufacturer();
String appversion = DeviceUtils.getVersionName();
Map dataMap = new HashMap<>();
dataMap.put("model", deviceModel);
//dataMap.put("deviceid", deviceid);
dataMap.put("romtype", romType + "");
dataMap.put("sysverion", sysVersion);
dataMap.put("vendor", verdor);
dataMap.put("appversion", appversion);
dataMap.put("sign", paramsterEncryption.sign);
dataMap.put("appkey", paramsterEncryption.app_key);
dataMap.put("timestamp", paramsterEncryption.timestamp);
return dataMap;
}
}