play 入口:java
play.server.Server類 bootstrap
主要作2件事情:服務器
1,Play.init; // 初始化,主要是配置的加載,插件的加載等等cookie
2,new Server(); 數據結構
這裏play使用了netty做爲底層通信服務器mvc
//實例化ServerBootstrap 啓動netty服務器(boss線程池、worker線程池)。
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())
boss線程池實際就是Acceptor線程池,負責處理客戶端的TCP鏈接請求app
worker線程池是真正負責I/O讀寫操做的線程組less
play 是如何處理請求的?spa
一、實例化ServerBootstrap 啓動netty服務器(boss線程池、worker線程池),綁定IP、端口
二、指定filter ,也就是PLAY中的HttpServerPipelineFactory,用於處理輸入和輸出報文.net
public class HttpServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { Integer max = Integer.valueOf(Play.configuration.getProperty("play.netty.maxContentLength", "-1")); ChannelPipeline pipeline = pipeline(); PlayHandler playHandler = new PlayHandler(); pipeline.addLast("decoder", new HttpRequestDecoder()); //處理httprequest pipeline.addLast("aggregator", new StreamChunkAggregator(max));//實現http分塊 pipeline.addLast("encoder", new HttpResponseEncoder());//處理http返回 pipeline.addLast("chunkedWriter", playHandler.chunkedWriteHandler);//http分塊 Integer gzip = Integer.valueOf(Play.configuration.getProperty("play.netty.gzip", "0")); if (gzip==1) { pipeline.addLast("compress", new HttpContentCompressor());//壓縮 pipeline.addLast("decompress", new HttpContentDecompressor());//解壓 } pipeline.addLast("handler", playHandler);//參數解析 return pipeline; } }
三、playHandler處理分析 parseRequest:將nettyRequest解析爲play.mvc.http.Request Play.pluginCollection.rawInvocation:執行PLAY插件列表 CorePlugin:處理play內置的功能(狀態):/@kill /@status DBPlugin:處理play內置功能(啓動h2Server):/@db Evolutions:處理play內置功能(檢查數據結構變動):/@evolutions/apply Invoker.invoke(new NettyInvocation(request, response, ... :開始執行代碼 放在線程池中去執行(play.pool) Invoker.java:Run some code in a Play! context Invocation:An Invocation in something to run in a Play! context init():detectChanges 檢測代碼變化,熱部署,僅DEV模式(配置文件變化時重啓) run():捕獲異常,返回500 before(); 執行全部插件beforeInvocation JPAPlugin事務開啓 execute(); after(); 執行全部插件afterInvocation JPAPlugin事務關閉 onSuccess();執行全部插件onInvocationSuccess TempFilePlugin臨時文件刪除 execute():ActionInvoker.invoke 開始調用action四、ActionInvoker.invoke分析 resolve:將request、response、params、Session放入線程變量;根據URL找到action類和方法 解析請求內容,生成action參數 handleBeforeValidations:執行action攔截器 @BeforeValidation @unless @only Play.pluginCollection.beforeActionInvocation: 執行play插件beforeActionInvocation PlayPlugin.beforeActionInvocation: 將錯誤信息加入Validation handleBefores:執行action攔截器 @before @unless @only invokeControllerMethod:執行controllers代碼 inferResult:處理controllers代碼執行後的返回結果 catch (InvocationTargetException ex) :捕獲異常 返回結果的異常(Result):保存cache 其它異常:執行action攔截器 @Catch @unless @only handleAfters(request);:執行action攔截器 @after @unless @only catch (Result result) Play.pluginCollection.onActionInvocationResult(result); : ValidationPlugin.onActionInvocationResult:保存Validation.errors到cookies 保存Session(cookies) result.apply(request, response);:根據result類型設置http code,http head,http body Play.pluginCollection.afterActionInvocation();:暫無實現 handleFinallies:執行action攔截器 @Finally @unless @only