MockNet -- Android網絡接口開發與測試神器

最近寫了一個輕量級的服務器框架 MockNet,可以在 Android 上或者 Java 平臺快速搭建服務器,方便開發和測試網絡接口,不需要服務器知識就可以使用。

寫這個框架的原因

平時寫項目的時候,總會遇到這些情況

  1. 服務器接口還沒有寫好,Android 客戶端只能先做一些界面的開發工作,遇到需要展示數據的地方只能先留著或者用一些假數據填充,服務器接口寫好以后,這些代碼又得刪掉或者再改。
  2. 在調試網絡接口的時候,往往需要后臺客戶端一起配合,有時候會花不少時間確認是服務器還是客戶端的問題,之后聯調也很花時間。
  3. 在沒有網絡但是又需要展示應用功能的時候,只能用一堆 if else 來添加假數據或者數據庫里的數據。代碼寫起來很不方便。

寫這個框架就是想解決這些問題。

  • 首先是網絡接口開發的問題,通過 MockNet 這個庫,無需后臺接口完成就可以進行網絡接口的開發,開發流程要更順暢一點。
  • 其次是網絡接口調試的問題,通過 MockNet 這個庫,在沒有后臺同學的幫助下也可以對 Android 客戶端網絡接口進行調試。
  • 最后是沒有網絡需要展示功能的問題,通過 MockNet 這個庫,沒有網絡一樣可以展示應用的網絡功能。

框架介紹

MockNet 是為了方便客戶端網絡接口的開發和測試而寫的,簡單來說就是在本地啟動服務器用來響應客戶端的網絡請求。但是不需要有服務器開發知識,幾行代碼就可以添加此功能。

代碼上傳到了 github 上,網址: https://github.com/5A59/MockNet

庫下載

Gradle

// 在模塊的 gradle 文件中添加下面的代碼  
compile 'com.zy.mocknet:mocknet:1.0'

Maven

<dependency>
  <groupId>com.zy.mocknet</groupId>
  <artifactId>mocknet</artifactId>
  <version>1.0</version>
  <type>pom</type>
</dependency>

jar包下載

mocknet_1_0_0.jar

框架使用

使用示例

MockNet 使用簡單,步驟如下:

  1. 修改網絡訪問 ip 為本地 ip (127.0.0.1:port 或 本地真實ip:port),因為服務器是在本地搭建的。
  2. 初始化。
    // 創建 MockNet
    MockNet mockNet = MockNet.create();
  3. 添加對請求的處理
    MockNet 中對每一個 request 都會對應一個 response,request 和 response 和起來稱為一個 MockConnection,添加對請求的處理就是添加 MockConnection 實例。
    MockConnection conn = MockConnectionFactory.getInstance()
     .createGeneralConnection("/*", "general connection");
    mockNet.addConnection(conn);
    createGeneralConnection(String, String) 第一個參數是請求 url,例:/test,第二個參數是返回內容。這是最簡單的創建方式,更多的 MockConnection 創建方式可以參看 MockNet介紹 或者 java文檔
  4. 啟動服務
    // 默認使用 8088 端口
    mockNet.start();
    // 使用指定的端口
    mockNet.start(int port);
  5. 關閉服務
    mockNet.stop();

以上就是 MockNet 的使用方法。還可以通過鏈式調用來寫,代碼更簡潔。

MockNet mockNet = MockNet.create()
                .addConnection(MockConnectionFactory.getInstance()
                        .createGeneralConnection("/test", "{'res':'ok'}"))
                .addConnection(MockConnectionFactory.getInstance()
                        .createGeneralConnection("/*", "{'res':'ok'}"))
                .start();

進階使用

上面是 MockNet 的簡單使用,還有更多的擴展用法。

  1. 自定義 MockConnection

    通過 MockConnection.Builder 生成 Builder,并通過 Builder 相關方法構建 MockConnection。Builder 常用的方法可以參看文檔: Builder

  2. 隨機對請求做出響應

    MockNet 內部通過 url 和 method(GET,POST等)來對請求做出區分,在 addConnection 時如果添加了多個相同的 url 和 method 的 MockConnection,會通過 IConnectionSelector 來選擇其中之一進行返回,默認使用 RandomSelector 隨機返回。

    可以通過 實現 IConnectionSelector 接口并通過 MockNet.setSelector() 設置返回規則。

  3. Log 設置

    默認對每個 MockConnection 都會輸出 Log 以幫助調試,如果想關閉 Log,可以在構建 MockConnection 時設置 isLog(false)。

    MockNet 的 Log 輸出是由 Logger 和 Printer 完成的,默認設置了 AndroidPrinter 和 JavaPrinter,如果想自定義 Log,可以實現 Printer 接口,并調用 Logger.init(yourPrinter) 設置,但是要在調用了 MockConnection.create() 之后,否則設置會被覆蓋為默認設置

  4. 自定義 Handler 對請求響應進行處理

    MockNet 中對 Request 和 Response 的處理采用了責任鏈模式(可查看后面的框架介紹),通過添加 Handler 增加處理環節,框架自帶的 Handler 有 BlockHandler,LogHandler,VerifyHeaderHandler,VerifyParamHandler,ConnectionHandler。

    如果想增加自己的處理環節,請實現 Handler 接口,并通過 MockNet.addHandler(Handler h) 來設置。具體實現方法可參照框架默認實現的 Handler 代碼。

  5. 支持 https

    支持 https 可以通過下面代碼來開啟:

    MockNet mockNet = MockNet.create();
    mockNet.start(ServerSocketFactory.createHttpsServerSocket(int port, String jksPath, String storePwd));
  6. 動態處理數據

    為了簡化使用方法和加快開發速度,默認只支持了返回靜態數據,暫時沒有對數據進行動態處理。如果想動態處理請求數據,可以繼承 RequestExecutor 接口并實現 execute 方法。在 execute 方法中對請求進行動態處理,并創建 Reponse 返回。

    之后通過 Server 構造函數構造 Server 對象并傳入實現 RequestExecutor 接口的類對象。

    具體可以參考 MockRequestExecutor 的實現以及 Server 構造函數。

更多使用方法可查看 MockNetjava文檔

框架架構

上面介紹了框架的使用,這里對框架的實現做一些介紹。

先上一張架構圖。

mocknet.png

自己認為整個架構還是不錯的(-_-)。

整體可分為兩層, Server 層和 Application 層。

Server 層

Server 層主要做的工作是 socket 通信和對 Request,Response 的解析。

Server 類主要是對端口的監聽,接受 socket 請求并創建 RequestRunnable 處理請求。

RequestRunnable 創建后會加入到線程池中。RequestRunnable 類中對請求進行解析,并把請求發送到 RequestExecutor 去處理,RequestExecutor 會返回 Response,RequestRunnable 再負責把 Response 寫入到 socket 中。

Application 層

Application 層工作是對 Request 的處理。通過實現 RequestExecutor 接口處理 Request 并返回 Response。

框架中默認實現 RequestRunnable 接口的是 MockRequestExecutor 類,用來返回靜態消息,如果想動態處理請求,需要自己實現 RequestExecutor 接口,框架后續看情況也可能會增加動態處理請求的功能。

MockRequestExecutor 中主要采用責任鏈模式處理請求,每一個 Handler 都是一個處理環節。這個鏈式的實現是之前看過 OkHttp 代碼學到的。這里貼代碼來看一下。

HandlerChain chain = new RealHandlerChain();

public Response execute(Request request) {
    for (Handler h : userHandlers) {
        chain.addHandler(h);
    }

    if (initHandler) {
        chain.addHandler(new BlockHandler());
        chain.addHandler(new VerifyParamHandler());
        chain.addHandler(new VerifyHeaderHandler());
        chain.addHandler(new LogHandler());
        chain.addHandler(new ConnectionHandler());
    }

    return chain.start(request);
}

上面是 MockRequestExecutor 的 execute() 函數的實現,首先將 Handler 加入到 chain 中,之后調用 chain.start() 開始調用 Handler 進行處理。

再看一下 HandlerChain 的 start() 方法實現。

public Response start(Request request) {
    Handler handler = handlers.get(index);
    Response response = handler.handle(request, this, index);
    return response;
}

直接調用了 handler.handle()進行處理,在 Handler 的 handle 方法中需要調用下一個 Handler。

框架默認實現了幾個 Handler:BlockHandler,VerifyParamHandler,VeriffyHeaderHandler,LogHandler,ConnectionHandler。

這些通過名字可以看出功能,這里重點看一下 ConnectionHandler。

ConnectionHandler 是處理鏈調用的終點,負責生成 Response。

ConnectionHandler 的 handle 方法如下:

String method = request.getMethod();
String url = request.getRequestUri();
MockConnection connection =
    ConnectionStore.getInstance().getConnection(method, url);
if (connection == null) {
    return Response.create404Response();
}
Response response = new Response();
// 省略對 Response 的設置
return response;

通過請求的 url 和 method 從 ConnectionStore 中獲取到 MockConnection,之后用 MockConnection 中的響應信息創建并填充 Response。

那 ConnectionStore 中的 MockConnection 是什么時候放進去的呢?就是在我們開始通過 MockNet.addConnection() 添加的。

這樣整個框架就差不多講完了,具體的細節就請查看 代碼 吧。感覺整個框架實現不難,模塊化和擴展性都還不錯(自夸一下)。

其他

如果有什么問題或者想法可以上 github 提 issue,或者可以郵箱交流 zy5a59@outlook.com。

 

項目主頁:http://www.baiduhome.net/lib/view/home/1495805036512

 本文由用戶 kovoxumkigu027 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!