本次 Cicada 已經更新到了 v1.0.3。 主要是解決了兩個 issue,#9(Boss線程數好像設置有誤 ) #8(怎麼返回純字元串內容不要JSON格式?)。 ...
前言
本次 Cicada 已經更新到了 v1.0.3
。
主要是解決了兩個 issue,#9(Boss線程數好像設置有誤 ) #8(怎麼返回純字元串內容不要JSON格式?)。
所以本次的主要更新為:
- Cicada 採用合理的線程分配來處理接入請求線程以及 IO 線程。
- 支持多種響應方式(以前只有 json,現在支持 text)。
- 為了滿足上者引入了
context
。 - 優雅停機。
其中我覺得最核心也最有用的就是這個 Context
,併為此重構了大部分代碼。
多種響應方式
在起初 Cicada
預設只能響應 json
,這一點確實不夠靈活。加上後續也打算支持模板解析,所以不如直接在 API 中加入可讓用戶自行選擇不同的響應方式。
因此調整後的 API 如下。
想要輸出
text/plain
時。
@CicadaAction("textAction")
public class TextAction implements WorkAction {
@Override
public void execute(CicadaContext context, Param param) throws Exception {
String url = context.request().getUrl();
String method = context.request().getMethod();
context.text("hello world url=" + url + " method=" + method);
}
}
而響應輸出
application/json
時只需要把需要響應的對象寫入到json()
方法中.
因此原有的業務 action 中也加入了一個上下文的參數:
/**
* abstract execute method
* @param context current context
* @param param request params
* @throws Exception throw exception
*/
void execute(CicadaContext context ,Param param) throws Exception;
下麵就來看看這個 Context
是如何完成的。
Cicada Context
先看看有了這個上下文之後可以做什麼。
比如有些場景下我們需要拿到本次請求中的頭信息,這時就可以通過這個 Context
對象直接獲取。
當然不止是頭信息:
- 獲取請求頭。
- 設置響應頭。
- 設置
cookie
。 - 獲取請求
URL
。 - 獲取請求的
method
(get/post)等。
其實通過這些特點可以看出這些信息其實都和一次 請求、響應
密切相關,並且各個請求之間的信息應互不影響。
這樣的特性是不是非常熟悉,沒錯那就是 ThreadLocal
,它可以將每個線程的信息存儲起來互不影響。
ThreadLocal 的原理本次不做過多分析,只談它在 Cicada 中的應用。
CicadaContext.class
先來看看 CicadaContext
這個類的主要成員變數以及方法。
成員變數是兩個介面 CicadaRequest、CicadaResponse
,名稱就能看出肯定是存放請求和響應數據的。
HttpDispatcher.class
想要存放本次請求的上下文自然是在真正請求分發的地方 HttpDispatcher
。
這裡改的較大的就是兩個紅框處,第一部分是做上下文初始化及賦值。
第二部分自然就是卸載上下文。
先看初始化。
CicadaRequest cicadaRequest = CicadaHttpRequest.init(defaultHttpRequest) ;
首先是將 request 初始化:
CicadaHttpRequest
自然是實現了 CicadaRequest
介面:
這裡只保存了請求的 URL、method 等信息,後續要加的請求頭也存放在此處即可。
Response
也是同理的。
這兩個具體的實現類都私有化了構造函數,防止外部破壞了整體性。
接著將當前請求的上下文保存到了 CicadaContext
中。
CicadaContext.setContext(new CicadaContext(cicadaRequest,cicadaResponse));
而這個函數本質使用的則是 ThreadLocal
來存放 CicadaContext
。
public static void setContext(CicadaContext context){
ThreadLocalHolder.setCicadaContext(context) ;
}
private static final ThreadLocal<CicadaContext> CICADA_CONTEXT= new ThreadLocal() ;
/**
* set cicada context
* @param context current context
*/
public static void setCicadaContext(CicadaContext context){
CICADA_CONTEXT.set(context) ;
}
處理業務及響應
接著就是處理業務,調用不同的 API 做不同響應。
拿 context.text()
來說:
其實就是設置了對應的響應方式、以及把響應內容寫入了 CicadaResponse
的 httpContent
中。
業務處理完後調用 responseContent()
進行響應:
responseContent(ctx,CicadaContext.getResponse().getHttpContent());
其實就是在上下文中拿到的響應方式及響應內容返回給客戶端。
卸載上下文
最後有點非常重要,那就是 卸載上下文。
如果這裡不做處理,之後隨著請求的增多,ThreadLocal
里存放的數據也越來越多,最終肯定會導致記憶體溢出。
所以 CicadaContext.removeContext()
就是為了及時刪除當前上下文。
優雅停機
最後還新增了一個停機的方法。
其實也就是利用 Hook
函數實現的。
由於目前 Cicada
開的線程,占用的資源都不是特別多,所以只是關閉了 Netty 所使用的線程。
如果後續新增了自身的線程等資源,那也可以全部放到這裡來進行釋放。
總結
Cicada
已經更新了 4 個版本,雛形都有了。
後續會重點實現模板解析和註解請求路由完成,把 MVC
中的 view
完成就差不多了。
還沒有瞭解的朋友可以點擊下麵鏈接進入主頁瞭解下