摘要:封裝公共參數(shù)和密碼添加新的參數(shù)新的請求使用了裝飾者模式使用添加。使用模式,暴露以下接口請求,且為時,鍵值對公共參數(shù)插入到參數(shù)中,其他情況插入到參數(shù)中。通過構(gòu)建要上傳的一些基本公共的參數(shù),然后通過符號在的里面其他要提交參數(shù)拼接。
請先閱讀:
Retrofit 動態(tài)參數(shù)(非固定參數(shù)、非必須參數(shù))(Get、Post請求)
在實(shí)際項目中,對于有需要統(tǒng)一進(jìn)行公共參數(shù)添加的網(wǎng)絡(luò)請求,可以使用下面的代碼來實(shí)現(xiàn):
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ctx).setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addQueryParam("publicParams", "1"); } }).setConverter(new BaseConverter()) .build();
在RestAdapter的實(shí)例化對象的時候,為其指定一個RequestInterceptor接口的實(shí)現(xiàn)類即可,在該類中,可以對請求體的相關(guān)參數(shù)進(jìn)行設(shè)置,如addHeader、addQueryParam等。
不過遺憾的是Retrofit2.0已經(jīng)沒有了該類,該怎么做呢?通過Interceptor實(shí)現(xiàn)。
Interceptor是攔截器, 在發(fā)送之前, 添加一些參數(shù), 或者獲取一些信息。
/** * 封裝公共參數(shù)(Key和密碼) **/ public class CommonInterceptor implements Interceptor { private final String mApiKey; private final String mApiSecret; public CommonInterceptor(String apiKey, String apiSecret) { mApiKey = apiKey; mApiSecret = apiSecret; } @Override public Response intercept(Interceptor.Chain chain) throws IOException { String marvelHash = ApiUtils.generateMarvelHash(mApiKey, mApiSecret); Request oldRequest = chain.request(); // 添加新的參數(shù) HttpUrl.Builder authorizedUrlBuilder = oldRequest.url() .newBuilder() .scheme(oldRequest.url().scheme()) .host(oldRequest.url().host()) .addQueryParameter(MarvelService.PARAM_API_KEY, mApiKey) .addQueryParameter(MarvelService.PARAM_TIMESTAMP, ApiUtils.getUnixTimeStamp()) .addQueryParameter(MarvelService.PARAM_HASH, marvelHash); // 新的請求 Request newRequest = oldRequest.newBuilder() .method(oldRequest.method(), oldRequest.body()) .url(authorizedUrlBuilder.build()) .build(); return chain.proceed(newRequest); } }
Okhttp3使用了裝飾者模式, 使用Builder添加Interceptor。
CommonInterceptor commonInterceptor = new CommonInterceptor( "key", "Secret"); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(commonInterceptor) .build(); // 適配器 Retrofit retrofit = new Retrofit.Builder() .baseUrl("url") .addConverterFactory(GsonConverterFactory.create() .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build();
有時候你找到了一條線,就能順著線找到更多。
BasicParamsInterceptor - 為 OkHttp 請求添加公共參數(shù)
背景在 Android Http API 請求開發(fā)中經(jīng)常遇到這樣的需求:每一次請求帶上一個或者多個固定不變的參數(shù),例如:
設(shè)備唯一標(biāo)識:device_id = 7a4391e28f309c21
業(yè)務(wù)唯一標(biāo)識:uid = 2231001
平臺類型:platform = android
客戶端版本號:version_code = 6
…
這些參數(shù)是每一次發(fā)生請求都需要的,我們姑且稱他們?yōu)楣矃?shù)(或者基礎(chǔ)參數(shù))。公共參數(shù)一般以 header line、url query 或者 post body(較少) 這些形式插入請求。
實(shí)現(xiàn)如果使用 OkHttp 作為 http request client, 這件事情就變得簡單多了。OkHttp 提供了強(qiáng)大的攔截器組件 (Interceptor):
Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.
也就是說,OkHttp 的攔截器功能之一就是對將要發(fā)出的請求進(jìn)行攔截、改造然后再發(fā)出。這正是我們想要的。BasicParamsInterceptor 實(shí)現(xiàn)了 okhttp3.Interceptor 接口。
實(shí)現(xiàn) public Response intercept(Chain chain) throws IOException 方法。使用 Builder 模式,暴露以下接口:
addParam(String key, String value)
post 請求,且 body type 為 x-www-form-urlencoded 時,鍵值對公共參數(shù)插入到 body 參數(shù)中,其他情況插入到 url query 參數(shù)中。
addParamsMap(Map paramsMap)
同上,不過這里用鍵值對 Map 作為參數(shù)批量插入。
addHeaderParam(String key, String value)
在 header 中插入鍵值對參數(shù)。
addHeaderParamsMap(Map headerParamsMap)
在 header 中插入鍵值對 Map 集合,批量插入。
addHeaderLine(String headerLine)
在 header 中插入 headerLine 字符串,字符串需要符合 -1 != headerLine.indexOf(“:”) 的規(guī)則,即可以解析成鍵值對。
addHeaderLinesList(List headerLinesList)
同上,headerLineList: List 為參數(shù),批量插入 headerLine。
addQueryParam(String key, String value)
插入鍵值對參數(shù)到 url query 中。
addQueryParamsMap(Map queryParamsMap)
插入鍵值對參數(shù) map 到 url query 中,批量插入。
示例
使用 Buider 模式創(chuàng)建 Interceptor 對象,然后調(diào)用 OkHttp 的 addInterceptor(Interceptor i) 方法將 interceptor 對象添加至 client 中:
BasicParamsInterceptor basicParamsInterceptor = new OkPublicParamsInterceptor.Builder() .addHeaderParam("device_id", DeviceUtils.getDeviceId()) .addParam("uid", UserModel.getInstance().getUid()) .addQueryParam("api_version", "1.1") .build(); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(basicParamsInterceptor) .build();
TODO
自動時間戳公共參數(shù)的支持
動態(tài)參數(shù)的支持(例如登錄后插入服務(wù)器返回的 uid)
源碼
源碼與引用:https://github.com/jkyeo/okht...
basicparamsinterceptor應(yīng)用配置基本提交參數(shù)
我們可以建一個攔截器,這里我舉例加些簡單的系統(tǒng)參數(shù),如下:
class HttpBaseParamsLoggingInterceptor implements Interceptor{ @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder requestBuilder = request.newBuilder(); RequestBody formBody = new FormBody.Builder() .add("userId", "10000") .add("sessionToken", "E34343RDFDRGRT43RFERGFRE") .add("q_version", "1.1") .add("device_id", "android-344365") .add("device_os", "android") .add("device_osversion","6.0") .add("req_timestamp", System.currentTimeMillis() + "") .add("app_name","forums") .add("sign", "md5") .build(); String postBodyString = Utils.bodyToString(request.body()); postBodyString += ((postBodyString.length() > 0) ? "&" : "") + Utils.bodyToString(formBody); request = requestBuilder .post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString)) .build(); return chain.proceed(request); } }
上面Utils類是使用的okio.Buffer里面的工具類。通過RequestBody構(gòu)建要上傳的一些基本公共的參數(shù),然后通過”&”符號在http 的body里面其他要提交參數(shù)拼接。然后再通過requestBuilder重新創(chuàng)建request對象,然后再通過chain.proceed(request)返回Response 。
接下來在創(chuàng)建OkHttpClient對象的時候修改為如下代碼:
mOkHttpClient = new OkHttpClient.Builder() .addInterceptor(interceptor) .addInterceptor(new HttpBaseParamsLoggingInterceptor()) .build();
這樣就添加好了一些基本的公共參數(shù)。
下面我們借助BasicParamsInterceptor實(shí)現(xiàn),代碼如下:
public class BasicParamsInterceptor implements Interceptor { MapqueryParamsMap = new HashMap<>(); Map paramsMap = new HashMap<>(); Map headerParamsMap = new HashMap<>(); List 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 Headers.Builder headerBuilder = request.headers().newBuilder(); if (headerParamsMap.size() > 0) { Iterator iterator = headerParamsMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); headerBuilder.add((String) entry.getKey(), (String) entry.getValue()); } } 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) { injectParamsIntoUrl(request, requestBuilder, queryParamsMap); } // process header params end // process post body inject if (request.method().equals("POST") && request.body().contentType().subtype().equals("x-www-form-urlencoded")) { FormBody.Builder formBodyBuilder = new FormBody.Builder(); if (paramsMap.size() > 0) { Iterator iterator = paramsMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); 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)); } else { // can"t inject into body, then inject into url injectParamsIntoUrl(request, requestBuilder, paramsMap); } request = requestBuilder.build(); return chain.proceed(request); } // func to inject params into url private void injectParamsIntoUrl(Request request, Request.Builder requestBuilder, Map paramsMap) { HttpUrl.Builder httpUrlBuilder = request.url().newBuilder(); 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()); } 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 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 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 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 queryParamsMap) { interceptor.queryParamsMap.putAll(queryParamsMap); return this; } public BasicParamsInterceptor build() { return interceptor; } } }
只要像上面一樣配置就行了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/65011.html
在這里就nodejs如何應(yīng)用swig摸板,總結(jié)一下一些基本的用法。首先當(dāng)然是利用express框架在node后臺上面搭建服務(wù) var express = require(express); var server = express(); server.listen(8080,localhost,(req,res)=>{ console.log(服務(wù)器啟動...); }) 啟動成功之后,...
摘要:語句以分號結(jié)尾狀態(tài)變量狀態(tài)變量是被永久地保存在合約中。中,實(shí)際上是代名詞,一個位的無符號整數(shù)。下面的語句被認(rèn)為是修改狀態(tài)修改狀態(tài)變量。事件事件是合約和區(qū)塊鏈通訊的一種機(jī)制。一旦它被發(fā)出,監(jiān)聽該事件的都將收到通知。 Solidity是以太坊的主要編程語言,它是一種靜態(tài)類型的 JavaScript-esque 語言,是面向合約的、為實(shí)現(xiàn)智能合約而創(chuàng)建的高級編程語言,設(shè)計的目的是能在以太坊虛...
閱讀 3166·2021-11-23 09:51
閱讀 678·2021-10-14 09:43
閱讀 3200·2021-09-06 15:00
閱讀 2403·2019-08-30 15:54
閱讀 2557·2019-08-30 13:58
閱讀 1840·2019-08-29 13:18
閱讀 1372·2019-08-27 10:58
閱讀 506·2019-08-27 10:53