亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Tomcat從零開始(十七)——StandardWrapper

系統 1851 0

第十七課: StandardWrapper

課前復習:

?????? 不知道大家是否還有印象,就是在 6 7 節課說的 4 container, 粗略的從大到小來說就是 engine,host,context , wrapper 。當時寫的時候很糾結,因為后面有詳細介紹這 4 個的計劃,所以前面寫的可能不是很詳盡。

?????? 讓我們回憶一下,當一個請求到來的時候,發生了什么。比如什么創建 Request 這里就不說了,之后 connector 會調用與之關聯的容器的 invoke 方法,之后那就肯定會調用 pipeline invoke ,之后一頓 invoke valve 。好,那讓我們回想一下之前寫過的 context wrapper ,總結一個比較詳細的執行過程。

1. ?????? Connector 創建 req resp

2. ?????? 調用 StandardContext invoke ,調用 xxxPipeline invoke 方法

3. ?????? Pipeline 調用了 wrapper invoke 方法

4. ?????? Wrapper 調用 valve invoke 方法

5. ?????? valve 調用了 servlet allocate (這里在以前的課程中講過)

6. ?????? allocate 方法調用 servlet load 方法 ( servlet 需要加載的時候 )

7. ?????? init 方法,之后就是 servlet 處理了。

關于 SingleThreadModel

?????? 這個 SingleThreadModel servlet2.4 以上版本就已經移除了,因為這個東西只能給你的 servlet service 保證同一時刻只有一個進程在訪問,給人一種假象的安全。而且只是給 service 方法給予同步,這顯然是不能完全解決多線程訪問的問題的。其實說這個是為了給下面的 StandardWrapper 做鋪墊。因為我們都知道 StrandardWrapper 是負責加載它所代表的 servlet allocate 一個對象的實例。之后交給 valve 來調用 servlet service 方法。這個 allocate 在使用 不使用 SingleThreadModel 的時候是不同的。好的,我們接下來就說這個 StandardWrapper

StandardWrapper

?????? 這個之前介紹過了,我們這次主要介紹的是 allocate 方法, 我們看下面這一段源碼可以發現,當沒有實現 SingleThreadModel 的時候, allocate 總是返回第一次時候產生的 servlet 實例。而如果實現 SingleThreadModel 接口,那么就開始控制分配的數量,當分配的大于 nInstance 時候,就 load 一個 servlet 實例,當然這個 load 實在 maxInstance 控制之內的。

?????? 代碼如下。

?

          public Servlet allocate() throws ServletException {

        if (debug >= 1)
            log("Allocating an instance");

        // If we are currently unloading this servlet, throw an exception
        if (unloading)
            throw new ServletException
              (sm.getString("standardWrapper.unloading", getName()));

        // If not SingleThreadedModel, return the same instance every time
        if (!singleThreadModel) {

            // Load and initialize our instance if necessary
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        try {
                            instance = loadServlet();
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            throw new ServletException
                                (sm.getString("standardWrapper.allocate"), e);
                        }
                    }
                }
            }

            if (!singleThreadModel) {
                if (debug >= 2)
                    log("  Returning non-STM instance");
                countAllocated++;
                return (instance);
            }

        }

        synchronized (instancePool) {

            while (countAllocated >= nInstances) {
                // Allocate a new instance if possible, or else wait
                if (nInstances < maxInstances) {
                    try {
                        instancePool.push(loadServlet());
                        nInstances++;
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        ;
                    }
                }
            }
            if (debug >= 2)
                log("  Returning allocated STM instance");
            countAllocated++;
            return (Servlet) instancePool.pop();

        }

    }
    

?

Load

?????? 這個沒什么多說的,以前說過了,我們知道 wrapper 接口有一個 load 方法,其實他和 Allocate 里的一樣,都是調用的 LoadServlet 方法。我們來看看它的源碼。

? ? 先看看這一段。

?

              // 這里是說如果不是第一次訪問了,并且不是singleThreadModel
    	//就直接返回  Servlet實例
        if (!singleThreadModel && (instance != null))
            return instance;

	if ((actualClass == null) && (jspFile != null)) {
                Wrapper jspWrapper = (Wrapper)
                    ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
                if (jspWrapper != null) {
                    actualClass = jspWrapper.getServletClass();
                    // Merge init parameters
                    String paramNames[] = jspWrapper.findInitParameters();
                    for (int i = 0; i < paramNames.length; i++) {
                        if (parameters.get(paramNames[i]) == null) {
                            parameters.put
                                (paramNames[i], 
                            jspWrapper.findInitParameter(paramNames[i]));
                        }
                    }
                }
}

    
? ? ?這是Tomcat4 的方法,以后的版本就沒有了。都是直接loadservletclass。之后就是Loader了,回憶一下我們當時講的,是自定義的一個classLoader,需要注意的是,container提供一個特殊的servlet,可以訪問container的內部內容,名稱以org.apache.catalina.起始。之后就是加載servlet,之后就是權限驗證,沒啥說的。在之后就是在init()的前后fire事件。之后用instanceof來確定是否是實現了singleThreadModel的,如果是就放入pool(如果pool為空就創建一個新的)中。剩下就是Return了。

?



ServletConfig

?????? 接下來就是 servletConfig ,這個東西我們回憶一下是在哪里看到這個東西的,想想在 servlet load 的時候,就會調用一個 init 方法,而且他的參數是 ServletConfig config ,那么,我們就需要知道 servlet 是怎么拿到 servletConfig 的,我們看源碼,會發現 StandardWrapper 他實現了 ServletConfig 接口,所以說他把自己傳過去就行了。但是想一個事情,如果這樣可以,那么 servlet 的每一個實現就都可以用 wrapper 之內的方法了, wrapper container 的,所以我們要保證安全,那么就像 req,resp 那樣,用一個 fa?ade 設計模式就行,這個就是隱藏子系統。

?

Filter

?????? 做過 web 開發,大家應該知道 filter 這個東西,那么 filter 是怎么實現的呢,我們想一下之前學的東西,我們應該能想到 ServletWrapperValve 做了這件事情,因為 filter 是跟 service 方法前后后關系。那么我們就可以知道 valve invoke 方法做了什么:

1. ?????? 首先要得到一個 wrapper 的對象, allocate 一個 servlet

2. ?????? 來一系列的 Filter ,調用他們的 doFilter 方法,當然還有 service 方法

3. ?????? 銷毀,這個應該是在 servlet 超時的時候才進行。

剩下就是講解一下 filter chain 了,這個東西其實是一個 ArrayList ,但是注意 filterChain 是一個對象,其中的 filter 是一個該對象之中的一個 arraylist, 所以我們就知道,這個東西其實就是靠 iterator 來實現一個接一個的調用過濾器。所以,本章就結束了,這章其實沒有多少自己寫的東西,基本都是對源代碼的一種分析,希望大家可以多理解,或者下一個 tomcat sourcecode 版本,之后多用斷點 跑一跑就能理解是怎么工作的了。

? ? 最后還是冒充一下大神說說讀代碼的事吧,剛才有人問了問為啥我能讀懂一些,剛開始的時候我也看不懂,其實就是你最開始看的時候不要糾結于所有的語句,至少你能看懂這個方法主要是干啥功能的,大概哪幾個語句能實現就行了,等你慢慢的看完這個,再看完另一個,你就能知道到底那個語句是干什么的了。

?

?

Tomcat從零開始(十七)——StandardWrapper


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 毛茸茸bbw亚洲人 | 久久线看观看精品香蕉国产 | 亚洲欧美日韩久久精品第一区 | 精品久久不卡 | 欧美成人高清 | 日韩欧美亚洲国产精品字幕久久久 | h片在线观看免费 | 成人午夜大片免费7777 | 久久精品国内一区二区三区 | 免费观看一级毛片 | bbw老妇bbwbbwass| 久久视屏这里只有精品6国产 | 香蕉精品在线 | 久久综合偷偷噜噜噜色 | 正在播放久久 | 中文字幕在线观看第二页 | 亚洲精品久久玖玖玖玖 | 日韩大片 | 99国产精品视频免费观看 | 波多野结衣在线一区 | 奇米在线观看视频 | 他也色在线 | 亚洲精品国产第一区第二区国 | 伊人国产在线播放 | 国产亚洲综合色就色 | 色鬼久久爱综合久久鬼色 | 色婷婷色 | 久久中文字幕一区二区 | 亚洲精品久久久久久久久久久网站 | 九色国产在视频线精品视频 | 国产一区二区三区免费在线观看 | 老司机久久精品视频 | 亚洲欧洲国产精品你懂的 | 久久精品免费i 国产 | 国产一区二区三区四区 | 久久久久久免费观看 | 久久一本久综合久久爱 | 久操福利视频 | 老子影院午夜 | 成人区精品一区二区毛片不卡 | 国产日产欧产麻豆精品精品推荐 |