当我们使用OkHttpClient 的时候,增加自定InterCeptor 拦截器的时候需要注意

当我们使用OKHttp 进行网络请求的时候,需要增加自定义的Interceptor,用来进行网络请求公共的操作,如何Log日志,或者网络加密,这里会出现很多问题

以下是配合Retrofit和增加OKhttp的例子:

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);
    }

注意我们这里给OKHttpclient 增加了两个拦截器,分别是httpLogginInerceptor和BasicDataInterceptor,他们两者都是Interceptor,然后复写intercept(Chain chain)方法对我们发出来的网络请求进行拦截

public class BasicDataInterceptor implements Interceptor{
    @Override
        public Response intercept(Chain chain) throws IOException {
      Request originRequest = chain.request();
        //chai中包含了请求相关的所有信息,我们可以在这里进行拦截后的//操作

     return chain.proceed(newRequest);
    }
}

但是…..
我们进行网络请求的时候,可能以不同的协议的形式请求,那么这个时候我们怎么写Intercept 比较合适呢?

例如:在进行Retrofit 请求的时候

public interface HouseApi {

    @POST("v1/user/login")
    @FormUrlEncoded
    Observable<ApiResponse<User>> login(@Field("logincode") String loginCode,
                                        @Field("password") String password);

    @Multipart
    @POST("v1/common/upload")
Observable<ApiResponse<FileResult>>  uploadFile(@PartMap     Map<String, RequestBody> 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<String, String> 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<String, String> dataMap = getAppendDataMap();
        for (String key : dataMap.keySet()) {
            builder.addFormDataPart(key, dataMap.get(key));
        }
        return builder.build();
    }

//每个网络请求必要的加密参数和公告的参数
    private Map<String, String> 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<String, String> 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;
    }


}

猜你喜欢

转载自blog.csdn.net/qianyedoufulao/article/details/79468562