OKHttp使用拦截器(Interceptor)POST与GET方法,统一封装传公共参数

我们在使用retrofit联网开发的过程中,会遇到API每一次请求数据都会带有相同的公共参数。
例如:

  • 用户ID : 1111111
  • 设备唯一ID:132131290
  • 客户端版本号:2.3.0
  • 等一些参数……

然而,我们请求有postget两种方式,我再百度的过程中基本都是用的get请求方式,可能大多都是为了测试方便。一般开发过程中我还是建议用post来请求数据。在这儿我们就多扯一点两者的区别。

GET:GET请求的数据会附再URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间&相连,比如:http://music.163.com/#/song?id=436514312&autoplay=true&market=baiduhd。较深的这部分就是URL的传输数据。

  1. GET方式提交数据最多只能1024字节,因为GET是通过URL提交数据,所以GET提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上线的问题,HTTP协议规范没有对URL长度的限制。这个显示是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。注意这是限制是整个URL长度,而不仅仅是你的参数值数据长度。

POST:POST则是把提交的数据放置在HTTP包的包体中。HTTP协议规范也没有进行大小限制,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

1.POST的安全性要比GET的安全性高。注意:这里所说的安全性和上面GET提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义,比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击。


总结一下,GET就是从服务器中获取/查询资源信息,POST一般用于向服务器提交数据来更新资源信息,再FORM(表单)中,Method默认为“GET”,实质上,GET和POST只是发送机制不同,并不是一个取一个发!

参考原文地址:http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html

根据以上的概述:就知道我们为什么要用POST请求,而不用GET请求。

回归主题,用什么方法来统一实现传公共参数。

实现

如果使用 OkHttp 作为 http request client, 这件事情就变得简单多了。OkHttp 提供了强大的拦截器组件 (Interceptor):

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

OKHttp的拦截器功能之一就是将要发出的请求进行拦截,改造然后再发出。BasicParamsInterceptor 实现了 okhttp3.Interceptor 接口。

  • addParam(String key, String value)

    post 请求,且 body type 为 x-www-form-urlencoded 时,键值对公共参数插入到 body 参数中,其他情况插入到 url query 参数中。

  • addParamsMap(Map paramsMap)

    同上,不过这里用键值对 Map 作为参数批量插入。

  • addHeaderParam(String key, String value)

在 header 中插入键值对参数。

  • addHeaderParamsMap(Map headerParamsMap)

在 header 中插入键值对 Map 集合,批量插入。

  • addHeaderLine(String headerLine)

在 header 中插入 headerLine 字符串,字符串需要符合 -1 != headerLine.indexOf(“:”) 的规则,即可以解析成键值对。

  • addHeaderLinesList(List headerLinesList)

同上,headerLineList: List 为参数,批量插入 headerLine。

  • addQueryParam(String key, String value)

插入键值对参数到 url query 中。

  • addQueryParamsMap(Map queryParamsMap)

插入键值对参数 map 到 url query 中,批量插入。

BasicParamsInterceptor代码:

package com.zy.blogs.blogssample.util;

import android.text.TextUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

/**
 * <p/>
 * 作者:zhouyuan on  2017/1/4 14:16
 * <p/>
 * 邮箱:244370114@qq.com
 * <p/>
 * github地址:  https://github.com/jkyeo/okhttp-basicparamsinterceptor
 */
public class BasicParamsInterceptor implements Interceptor {
    Map<String, String> queryParamsMap = new HashMap<>();
    Map<String, String> paramsMap = new HashMap<>();
    Map<String, String> headerParamsMap = new HashMap<>();
    List<String> headerLinesList = new ArrayList<>();

    private BasicParamsInterceptor() {

    }

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();

        // process header params inject
        if (headerParamsMap != null && headerParamsMap.size() > 0) {
            Set<String> keys = headerParamsMap.keySet();
            for (String headerKey : keys) {
                requestBuilder.addHeader(headerKey, headerParamsMap.get(headerKey)).build();
            }
        }

        Headers.Builder headerBuilder = request.headers().newBuilder();
        if (headerLinesList.size() > 0) {
            for (String line : headerLinesList) {
                headerBuilder.add(line);
            }
            requestBuilder.headers(headerBuilder.build());
        }
        // process header params end


        // process queryParams inject whatever it's GET or POST
        if (queryParamsMap.size() > 0) {
            request = injectParamsIntoUrl(request.url().newBuilder(), requestBuilder, queryParamsMap);
        }

        // process post body inject
        if (paramsMap.size() > 0) {
            if (canInjectIntoBody(request)) {
                FormBody.Builder formBodyBuilder = new FormBody.Builder();
                for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                    formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue());
                }

                RequestBody formBody = formBodyBuilder.build();
                String postBodyString = bodyToString(request.body());
                postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
                requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
            }
        }

        request = requestBuilder.build();
        return chain.proceed(request);
    }

    private boolean canInjectIntoBody(Request request) {
        if (request == null) {
            return false;
        }
        if (!TextUtils.equals(request.method(), "POST")) {
            return false;
        }
        RequestBody body = request.body();
        if (body == null) {
            return false;
        }
        MediaType mediaType = body.contentType();
        if (mediaType == null) {
            return false;
        }
        if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) {
            return false;
        }
        return true;
    }

    // func to inject params into url
    private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map<String, String> paramsMap) {
        if (paramsMap.size() > 0) {
            Iterator iterator = paramsMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());
            }
            requestBuilder.url(httpUrlBuilder.build());
            return requestBuilder.build();
        }

        return null;
    }

    private static 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 "did not work";
        }
    }

    public static class Builder {

        BasicParamsInterceptor interceptor;

        public Builder() {
            interceptor = new BasicParamsInterceptor();
        }

        public Builder addParam(String key, String value) {
            interceptor.paramsMap.put(key, value);
            return this;
        }

        public Builder addParamsMap(Map<String, String> paramsMap) {
            interceptor.paramsMap.putAll(paramsMap);
            return this;
        }

        public Builder addHeaderParam(String key, String value) {
            interceptor.headerParamsMap.put(key, value);
            return this;
        }

        public Builder addHeaderParamsMap(Map<String, String> headerParamsMap) {
            interceptor.headerParamsMap.putAll(headerParamsMap);
            return this;
        }

        public Builder addHeaderLine(String headerLine) {
            int index = headerLine.indexOf(":");
            if (index == -1) {
                throw new IllegalArgumentException("Unexpected header: " + headerLine);
            }
            interceptor.headerLinesList.add(headerLine);
            return this;
        }

        public Builder addHeaderLinesList(List<String> headerLinesList) {
            for (String headerLine : headerLinesList) {
                int index = headerLine.indexOf(":");
                if (index == -1) {
                    throw new IllegalArgumentException("Unexpected header: " + headerLine);
                }
                interceptor.headerLinesList.add(headerLine);
            }
            return this;
        }

        public Builder addQueryParam(String key, String value) {
            interceptor.queryParamsMap.put(key, value);
            return this;
        }

        public Builder addQueryParamsMap(Map<String, String> queryParamsMap) {
            interceptor.queryParamsMap.putAll(queryParamsMap);
            return this;
        }

        public BasicParamsInterceptor build() {
            return interceptor;
        }

    }
}

具体使用方法:

          BasicParamsInterceptor basicParamsInterceptor =
                    new BasicParamsInterceptor.Builder()
                            .addHeaderParam("User-Agent", "xxxxxxxxxxx")
                            .addHeaderParam("Accept", "application/json")
                            .addParam("_t", time)
                            .addParam("_tsp", tsp)
                            .build();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            builder.addInterceptor(basicParamsInterceptor);

OkHttpClient okHttpClient = builder.build();
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(ApiStores.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(okHttpClient)
                    .build();

该文,与原文有出入。

具体原文看:http://www.jkyeo.com/2016/04/18/BasicParamsInterceptor-%E4%B8%BA-OkHttp-%E8%AF%B7%E6%B1%82%E6%B7%BB%E5%8A%A0%E5%85%AC%E5%85%B1%E5%8F%82%E6%95%B0/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值