Okhttp設置公共參數,以json對象放入@Body請求公共參數的配置方式

當網絡請求都是基於一個URL,所有的接口都是同一個地址,而請求不同接口數據則是通過command字段進行配置,然後所有的請求參數都是需要自己寫一個bean類,再轉成json格式放入請求body裏發給後臺,而不是通過表單form-body發送,所以配置一些公共參數,如sessionId、timestamp等就有點麻煩,每個bean類都要加這些參數,或者寫個基類BaseRequestBean,基類當中配置公共參數,這是一種解決方案,但我不想這麼做,那麼只能通過okhttp配置攔截器設置公共參數;以下進入主題:

攔截器配置步驟
1、攔截器CommonSignParamsInterceptor類繼承於okhttp3.Interceptor類,重寫父類方法intercept
2、自定義一個private HashMap<String,String> getCommanParams()方法,在該方法當中,通過HashMap對象,以鍵值對方式設置公共參數
3、在intercept方法當中獲取請求體,調用getCommanParams方法,重新配置請求體併發送請求

遇到的問題,當公共參數放在請求頭header或者是form-body當中配置可能放便些,如下:

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

        Response response;
        Request originRequest = chain.request();
        Request.Builder newRequest = originRequest.newBuilder();
        RequestBody body = originRequest.body();
        
        //添加請求頭參數,調用addHeader(key,value)方法
        newRequest.addHeader("header-key",
               new JSONObject(getCommonParams()).toString());

        if (body == null) {
            body = EMPTY_BODY;
            newRequest.post(body);
        } else if(body instanceof FormBody){
            //添加表單參數form-body
            FormBody oldBody = (FormBody) body;
            FormBody.Builder newFormBodyBuilder = new FormBody.Builder();
            for (int i = 0; i < oldBody.size(); i++) {
                newFormBodyBuilder.add(oldBody.name(i), oldBody.value(i));
            }
            //添加公共參數
            for (Map.Entry<String, String> entry : getCommonParams().entrySet()) {
                newFormBodyBuilder.add(entry.getKey(), entry.getValue());
            }
            FormBody newFormBody = newFormBodyBuilder.build();
            newRequest.post(newFormBody);
        }
        response = chain.proceed(newRequest.build());

        return response;
    }

通過以上代碼發現,添加請求頭作爲公共參數最簡單,直接調用newRequest.addHeader就行,而添加表單參數也不難,只是簡單的將原請求參數取出放入新的FormBody.Builder對象即可;那麼還有一種情況,就是本文主題,如何將公共參數放入請求體body的json對象當中?

通過閱讀源碼,okhttp3.logging.HttpLoggingInterceptor發現,該攔截器是這樣打印請求內容的,包括header等等請求信息:

      if (!logBody || !hasRequestBody) {
        logger.log("--> END " + request.method());
      } else if (bodyHasUnknownEncoding(request.headers())) {
        logger.log("--> END " + request.method() + " (encoded body omitted)");
      } else {
        Buffer buffer = new Buffer();
        requestBody.writeTo(buffer);

        Charset charset = UTF8;
        MediaType contentType = requestBody.contentType();
        if (contentType != null) {
          charset = contentType.charset(UTF8);
        }

        logger.log("");
        if (isPlaintext(buffer)) {
          logger.log(buffer.readString(charset));
          logger.log("--> END " + request.method()
              + " (" + requestBody.contentLength() + "-byte body)");
        } else {
          logger.log("--> END " + request.method() + " (binary "
              + requestBody.contentLength() + "-byte body omitted)");
        }
      }

通過以上源碼可發現,else裏面,將requestBody通過writeTo方法寫入到buffer當中,再buffer內容讀出,這就可先將原請求體和內容取出,取出之後,才能修改並加公共參數;具體實現代碼跟源碼方式大同小異,代碼如下:

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

        Response response;
        Request originRequest = chain.request();
        Request.Builder newRequest = originRequest.newBuilder();
        RequestBody body = originRequest.body();
        
        //添加請求頭參數,調用addHeader(key,value)方法
        //newRequest.addHeader("header-key",
        //       new JSONObject(getCommonParams()).toString());

        if (body == null) {
            //------------
        } else if(body instanceof FormBody){
            //添加表單參數form-body
        } else if(body instanceof MultipartBody){
            //..........非本文主題
        } else {
            Buffer buffer = new Buffer();
            body.writeTo(buffer);
            Charset charset = Charset.forName("UTF-8");
            MediaType contentType = body.contentType();
            if (contentType != null) {
               charset = contentType.charset(charset);
               if (charset != null) {
               //讀取原請求參數內容
               String requestParams = buffer.readString(charset);
               try {
                   //重新拼湊請求體
                   JSONObject jsonObject = new JSONObject(requestParams);
                   for (Map.Entry<String, String> entry : getCommonParams().entrySet()) {
                       jsonObject.put(entry.getKey(), entry.getValue());
                   }
                   RequestBody newBody = RequestBody.create(body.contentType(), jsonObject.toString());
                   newRequest.post(newBody);
                   } catch (JSONException e) {
                       e.printStackTrace();
                   }
               }
             }
        }
        response = chain.proceed(newRequest.build());

        return response;
    }

文畢,好好學習,天天向上 

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