封裝Volley使Volley的每個請求都自動儲存和傳送Cookie

王世暉發表於2016-05-09

思路很簡單,每次請求獲取到伺服器返回的response就解析頭部獲取cookie並儲存,傳送請求的時候就從本地讀取cookie新增到頭部傳送給伺服器

第一步,解析http response頭部的cookie並儲存,自定義一個Request並重寫其parseNetworkResponse方法

/**
 * 解析資料,儲存Cookie
 * @param response
 * @return
 */
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
    try {
        JSONObject jsonObject;
        /*將response構造成JSONObject返回給呼叫者*/
        if (response.data.length != 0) {
            String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            jsonObject = new JSONObject(jsonString);
        } else {
            jsonObject = new JSONObject();
        }
        /*獲取資料頭*/
        mHeader = response.headers.toString();
        /*通過正規表示式提取Cookie(JSESSIONID)*/
        Pattern pattern = Pattern.compile("Set-Cookie=.*?;");
        Matcher matcher = pattern.matcher(mHeader);
        if (matcher.find()) {
            cookieFromResp = matcher.group();
            /*獲取資料頭中鍵為Set-Cookie的值即獲取Cookie*/
            cookieFromResp = cookieFromResp.substring(11, cookieFromResp.length() - 1);
            DLog.v("Cookie: " + cookieFromResp);
        }
        /*將Cookie儲存到本地,下次請求資料的時候再把本地儲存的Cookie傳送給伺服器*/
        if(!TextUtils.isEmpty(cookieFromResp)){
            CookieUtils.saveSessionID(App.getContext(),cookieFromResp);
        }
        return Response.success(jsonObject,
                HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JSONException je) {
        return Response.error(new ParseError(je));
    }
}
第二步,傳送請求的時候,從本地讀取Cookie,新增到http request的頭部,傳送給伺服器,重寫getHeaders()即可

/**
 * 設定header,自動傳送本地儲存的Cookie
 * @return
 * @throws AuthFailureError
 */
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    headerMap.put("Accept", "application/json");
    headerMap.put("Content-Type", "application/json; charset=UTF-8");
    String cookie=CookieUtils.loadSessionID(App.getContext());
    DLog.d(cookie);
    /*將本地儲存的Cookie傳送給伺服器*/
    if(!TextUtils.isEmpty(cookie)){
        headerMap.put("Cookie", CookieUtils.loadSessionID(App.getContext()));
    }
    return headerMap;
}
經過上邊兩個方法的重寫就已經實現了Cookie的自動儲存和自動傳送

經過封裝的完整的Request程式碼如下:


public class JsonObjectRequest extends JsonRequest<JSONObject > {
    private String mHeader;
    private String cookieFromResp = "";
    Map<String, String> headerMap = new HashMap<>();

    public JsonObjectRequest(int method, String url,
                             JSONObject jsonRequest,
                             Response.Listener<JSONObject> listener,
                             Response.ErrorListener errorListener) {
        super(  method,
                url,
                (jsonRequest == null) ? null : jsonRequest.toString(),
                listener,
                errorListener);
    }

    public JsonObjectRequest(String url,
                             JSONObject jsonRequest,
                             Response.Listener<JSONObject> listener,
                             Response.ErrorListener errorListener) {
        this(  jsonRequest == null ? Request.Method.GET : Request.Method.POST,
                url,
                jsonRequest,
                listener,
                errorListener);
    }

    /**
     * 解析資料,儲存Cookie
     * @param response
     * @return
     */
    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            JSONObject jsonObject;
            /*將response構造成JSONObject返回給呼叫者*/
            if (response.data.length != 0) {
                String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
                jsonObject = new JSONObject(jsonString);
            } else {
                jsonObject = new JSONObject();
            }
            /*獲取資料頭*/
            mHeader = response.headers.toString();
            /*通過正規表示式提取Cookie(JSESSIONID)*/
            Pattern pattern = Pattern.compile("Set-Cookie=.*?;");
            Matcher matcher = pattern.matcher(mHeader);
            if (matcher.find()) {
                cookieFromResp = matcher.group();
                /*獲取資料頭中鍵為Set-Cookie的值即獲取Cookie*/
                cookieFromResp = cookieFromResp.substring(11, cookieFromResp.length() - 1);
                DLog.v("Cookie: " + cookieFromResp);
            }
            /*將Cookie儲存到本地,下次請求資料的時候再把本地儲存的Cookie傳送給伺服器*/
            if(!TextUtils.isEmpty(cookieFromResp)){
                CookieUtils.saveSessionID(App.getContext(),cookieFromResp);
            }
            return Response.success(jsonObject,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    /**
     * 設定超時
     * @return
     */
    @Override
    public RetryPolicy getRetryPolicy() {
        RetryPolicy retryPolicy= new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        return retryPolicy;
    }

    /**
     * 設定header,自動傳送本地儲存的Cookie
     * @return
     * @throws AuthFailureError
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        headerMap.put("Accept", "application/json");
        headerMap.put("Content-Type", "application/json; charset=UTF-8");
        String cookie=CookieUtils.loadSessionID(App.getContext());
        DLog.d(cookie);
        /*將本地儲存的Cookie傳送給伺服器*/
        if(!TextUtils.isEmpty(cookie)){
            headerMap.put("Cookie", CookieUtils.loadSessionID(App.getContext()));
        }
        return headerMap;
    }
    //將Cookie加入資料頭
    public void setCookie(String cookie) {
        headerMap.put("Cookie", cookie);
    }
}


相關文章