無所不能的攔截器

開發中有沒有遇到類似的情況:
1,服務器大佬在數據請求成功的時候返回的數據和請求失敗的時候返回的數據不一致,並且無法有效溝通,他甚至想打你,如下:
這是成功的數據

{
    "code":200,
    "msg":"OK",
    "data":{}
}

這是失敗的數據

{
    "code":201,
    "msg":"OK",
    "data":[]
}

2,服務器大佬要求所有的參數進行md5加密,當然可以寫個工具類對每個接口都進行加密,但是如果有一天不加密了呢,那就要該很多地方,寫法很low啊.
....
還有很多用到的情況,就不多說,下面看着倆種情況怎們處理

一,處理數據結構不一致問題

首先就看上面的簡單的數據結構,一般情況我們都會對接口請求返回的數據結構進行封裝,如上的data我們請求成功的時候用拿到的是一個大括號(對象),而請求出錯的時候我們拿到的是一箇中括號(對象集合),這樣我們封裝的就衝突了,下面是處理辦法:

 @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        if (response.code() == 200) {
            ResponseBody body = response.body();
            BufferedSource source = body.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
            String string = buffer.clone().readString(Charset.forName("UTF-8"));
            try {
                JSONObject jsonObject = new JSONObject(string);
                int code = jsonObject.getInt("code");
                if (code == ErroCode.OVERPAY) {
                    Response response2 = toOverpay(jsonObject, response);
                    return response2;
                } else if (code == ErroCode.FAIL) {
---------------------------------------------------------------------------------------
                    jsonObject.put("data", new Object());
-------------------------------------------------------------------------------------------
                    String string1 = jsonObject.toString();
                    Buffer buffer1 = response.body().source().buffer();
                    buffer1.clear();
                    buffer1.writeString(string1, Charset.forName("UTF-8"));
                }
                return response;
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return response;
        }

        return response;
    }

其他的地方不用管了,那是一些其他的相關邏輯,如果只處理上面那倆個簡單的數據結構,看虛線中間的哪一行就可以了,就是這麼簡單.

二,參數加密
加密有很多加密的算法,只拿我某個項目中的md5來舉個例子吧,直接看代碼

public class Md5Interceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = null;
        String method = request.method();
        switch (method) {
            case "POST":
                response = postMd5(chain, request);
                break;

            case "GET":
                response = getMd5(chain, request);
                break;
        }
        return response;


    }

    /**
     * get請求url參數加密
     *
     * @param chain
     * @param request
     * @return
     */
    private Response getMd5(Chain chain, Request request) throws IOException {
        Response response;//url
        String actionUrl = null;
        HttpUrl url = request.url();
        Set<String> set = url.queryParameterNames();
        Map<String, String> map = new HashMap<>();
        for (String name : set) {
            if (name.equals("service")) {
                actionUrl =url.queryParameter(name);
            }
            else if (!name.equals("s")) {
                map.put(name, url.queryParameter(name));
            }
        }
        StringBuilder tempParams = new StringBuilder();
        int pos = 0;
        for (String key : map.keySet()) {
            if (pos > 0) {
                tempParams.append("&");
            }
            tempParams.append(String.format("%s=%s", key, URLEncoder.encode(map.get(key), "utf-8")));
            pos++;
        }
        final String requestUrl = String.format("%s%s&%s", Api.baseUrl, actionUrl, tempParams.toString()) + Md5Utils.md5Encryption(actionUrl, map);
        final Request request1 = new Request.Builder().url(requestUrl).build();
        response = chain.proceed(request1);
        return response;

    }

    /**
     * post請求url參數加密
     *
     * @param chain
     * @param request
     * @return
     * @throws IOException
     */
    private Response postMd5(Chain chain, Request request) throws IOException {
        Response response;//url
        String actionUrl = null;
        FormBody body = (FormBody) request.body();
        FormBody.Builder builder = new FormBody.Builder();
        Map<String, String> map = new HashMap<>();
        for (int i = 0; i < body.size(); i++) {
            if (body.name(i).equals("service")) {
                actionUrl = body.value(i);
            } else {
                builder.add(body.name(i), body.value(i));
                map.put(body.name(i), body.value(i));
            }
        }
        RequestBody formBody = builder.build();
        final String requestUrl = String.format("%s%s", Api.baseUrl, actionUrl) + Md5Utils.md5Encryption(actionUrl, map);
        final Request request1 = new Request.Builder().url(requestUrl).post(formBody).build();
        response = chain.proceed(request1);
        return response;
    }
}

這個是某個簡單的攔截器,就是根據get 或者 post 把每個參數取出來進行加密,然後再重新放到response中,加密規則就不說了,每個項目都不一樣.只需注意一下怎們取參數即可.
所以說攔截器是個很牛x的機制,凡是涉及到網絡層面的東西,大部分可以用攔截器去解決,如果有道了什麼接口請求方面的問題,不妨想想攔截器.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章