OkHttp通用参数注入的正确姿势

/ 0评 / 13

前言

有时候我们需要为app中的http网络请求添加一些通用参数,比如当前应用版本、某些key值等,一般来说我们都会使用OkHttp的拦截器进行操作,所以下面就简单介绍下如何实现

实现

首先我们得知道参数一般都在哪里。对于GET请求,参数一般是拼接在url的后面,对于POST请求则分为两种。一种是表单提交,一种是参数Body中提交,对于参数在Body中的,我们暂时不考虑,因为判断有点困难。

对于GET请求,我们直接拼接到Url的后面,需要注意的是:我们需要删除同名的参数,不然如果外面也传递了通用参数,那么后台会将此字段的value使用逗号拼接在一起。(类似于version=1.1.1,1.2.2)

private static final Map<String, String> sCommonParams = new HashMap<>();

private Request injectParamsIntoUrl(Request request) {
	Request.Builder requestBuilder = request.newBuilder();
	HttpUrl.Builder httpUrlBuilder = request.url().newBuilder();

	for (Map.Entry<String, String> entry : sCommonParams.entrySet()) {
		httpUrlBuilder.removeAllQueryParameters(entry.getKey());
		httpUrlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
	}

	requestBuilder.url(httpUrlBuilder.build());
	return requestBuilder.build();
}

对于POST请求,我们先加入通用参数,然后将原始请求中的非通用参数添加进去即可。

这里有个小问题:就是如果我们需要将参数进行编码,那么我们需要使用builder.addEncoded("name",""value"),当然,我们也可以从原始请求中获取到编码后的参数formBody.encodedName()/formBody.encodedValue()

@Nullable
private Request injectParamsIntoForm(Request request) {
	RequestBody body = request.body();
	if (body instanceof FormBody) {
		FormBody formBody = (FormBody) body;
		FormBody.Builder builder = new FormBody.Builder();

		//加入通用参数
		for (Map.Entry<String, String> entry : sCommonParams.entrySet()) {
			builder.add(entry.getKey(), entry.getValue());
		}

		//加入非通用参数
		for (int i = 0; i < formBody.size(); i++) {
			if (!sCommonParams.containsKey(formBody.name(i))) {
				builder.add(formBody.name(i), formBody.value(i));
			}
		}
		return request.newBuilder()
				.post(builder.build())
				.build();
	}
	return null;
}

上面我们已经针对GET以及POST都进行了处理,下面贴出全部的代码,当发现POST没有使用Form提交参数时,直接注入到URL的后面

 public static class CommonRequestParameterInterceptor implements Interceptor {

	private static final String TAG = "CommonRequestParameterI";

	private static final Map<String, String> sCommonParams = new HashMap<>();

	public CommonRequestParameterInterceptor() {
		sCommonParams.put("version", String.valueOf(AppApplicationMgr.getVersionCode(ContextUtils.getAppContext())));
		sCommonParams.put("clientOsType", String.valueOf(Contracts.OS_ANDROID));
		sCommonParams.put("sn", BuildConfig.SN);
		sCommonParams.put("deviceId", DeviceUtils.getDeviceId());
		sCommonParams.put("appKey", BuildConfig.APP_KEY);
	}

	@Override
	public Response intercept(Chain chain) throws IOException {
		Request request = chain.request();
		String method = request.method();
		if ("GET".equalsIgnoreCase(method)) {
			//注入到url
			request = injectParamsIntoUrl(request);
		} else if ("POST".equalsIgnoreCase(method)) {
			//注入到body
			Request paramsIntoForm = injectParamsIntoForm(request);
			if (paramsIntoForm != null) {
				request = paramsIntoForm;
			} else {
				//如果body注入不了,则尝试注入url
				request = injectParamsIntoUrl(request);
			}
		}
		return chain.proceed(request);
	}

	private Request injectParamsIntoUrl(Request request) {
		Request.Builder requestBuilder = request.newBuilder();
		HttpUrl.Builder httpUrlBuilder = request.url().newBuilder();

		for (Map.Entry<String, String> entry : sCommonParams.entrySet()) {
			httpUrlBuilder.removeAllQueryParameters(entry.getKey());
			httpUrlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
		}

		requestBuilder.url(httpUrlBuilder.build());
		return requestBuilder.build();
	}

	@Nullable
	private Request injectParamsIntoForm(Request request) {
		RequestBody body = request.body();
		if (body instanceof FormBody) {
			FormBody formBody = (FormBody) body;
			FormBody.Builder builder = new FormBody.Builder();

			//加入通用参数
			for (Map.Entry<String, String> entry : sCommonParams.entrySet()) {
				builder.add(entry.getKey(), entry.getValue());
			}

			//加入非通用参数
			for (int i = 0; i < formBody.size(); i++) {
				if (!sCommonParams.containsKey(formBody.name(i))) {
					builder.add(formBody.name(i), formBody.value(i));
				}
			}
			return request.newBuilder()
					.post(builder.build())
					.build();
		}
		return null;
	}

}

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注