<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    上善若水
    In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
    posts - 146,comments - 147,trackbacks - 0

    概述

    ContextHandler繼承自ScopedHandler,它是Jetty中實現(xiàn)對一個Web Application的各種資源進(jìn)行管理,并串聯(lián)實現(xiàn)整個Servlet框架的類,比如它部分實現(xiàn)了ServletContext接口,并且在其doScope方法中為當(dāng)前Request的執(zhí)行提供了相應(yīng)的環(huán)境,如設(shè)置servletPath、pathInfo、設(shè)置ServletContext到ThreadLocal中。在Jetty中,Servlet的執(zhí)行流程和框架由ServletHandler實現(xiàn),Security框架由SecurityHandler完成,而ContextHandler主要用于實現(xiàn)環(huán)境的配置,如Request狀態(tài)的設(shè)置、ClassLoader的配置、ServletContext的實現(xiàn)等。在ContextHandler類中包含了一個Context的內(nèi)部類,用于實現(xiàn)ServletContext,而ContextHandler中的很多字段和方法也是用于實現(xiàn)ServletContext,不細(xì)述。

    ContextHandler實現(xiàn)

    ContextHandler中doStart方法實現(xiàn):
    1. 使用ContextPath或DisplayName初始化logger字段;并設(shè)置當(dāng)前線程的ContextClassLoader為配置的ClassLoader實例;初始化mimeType字段;設(shè)置Context的ThreadLocal變量。
    2. 初始化managedAttributes Map,并生成addBean事件;如果存在ErrorHandler,start它;生成contextInitialized事件。
    3. 初始化availability字段。
    4. 還原Context的ThreadLocal變量和ContextClassLoader回原有實例。

    ContextHandler中doStop方法實現(xiàn):
    1. 設(shè)置availability字段為STOPPED狀態(tài);初始化Context的ThreadLocal變量和ContextClassLoader為當(dāng)前Context實例以及設(shè)置的ClassLoader。
    2. 生成contextDestroyed事件,以及對managedAttributes,觸發(fā)removeBean事件。
    3. 還原Context的ThreadLocal變量和ContextClassLoader回原有實例。

    ContextHandler中doScope方法實現(xiàn):
    1. 對REQUEST、ASYNC的DispatcherType,并且是第一次進(jìn)入該ContextHandler,則如果compactPath為true,compact傳入的path,即把"http://", "http:///"等替換為"/"。
    2. 對當(dāng)前請求做初步檢查以決定是否需要繼續(xù)執(zhí)行該請求(返回false表示不需要繼續(xù)執(zhí)行該請求):
        a. 檢查availability狀態(tài),對UNAVAILABLE,發(fā)送503 Service Unavailable響應(yīng);對STOPPED、SHUTDOWN狀態(tài),或Request的handled字段為true,返回false。
        b. 對設(shè)置了vhosts,檢查請求消息中的ServerName請求頭是否和vhosts中的某個vhost相同或比配,如果不成立,則返回false。
        c. 檢查設(shè)置的connectors數(shù)組,如果當(dāng)前HttpConnection中的Connector.name不包含在這個設(shè)置的connectors數(shù)組中,返回false。
        d. 檢查contextPath,如果target不以這個contextPath開頭或者在target中contextPath之后的字符不是"/",返回false;如果allowNullPathInfo設(shè)置為false,且target不以"/"結(jié)尾,發(fā)送"target + /"的重定向請求,返回false。
        e. 對其他情況,返回true,表示請求可以繼續(xù)處理。
    3. 計算pathInfo以及target為contextPath之后的路徑,并設(shè)置ContextClassLoader為當(dāng)前設(shè)置的ClassLoader。
    4. 保留當(dāng)前Request的contextPath、servletPath、pathInfo信息。
    5. 對任意非INCLUDE的DispatcherType,設(shè)置Request的contextPath、servletPath為null、pathInfo為傳入的target中contextPath之后的路徑。
    6. 執(zhí)行nextScope的邏輯。
    7. 還原當(dāng)前Request的contextPath、servletPath、pathInfo的信息。

    ContextHandler中doHandle方法實現(xiàn):
    1. 對有新更新Context的Request實例,向當(dāng)前Request添加注冊的ServletRequestAttributeListener,如果注冊了ServletRequestListener,生成requestInitialized事件。
    2. 對REQUEST類型的DispatcherType,如果該target為保護(hù)資源(isProctedTarget,如WEB-INF、META-INF目錄下的文件),拋出404 Not Found的HttpException。
    3. 執(zhí)行nextHandle()邏輯。
    4. 如果注冊了ServletRequestListener,生成requestDestroyed事件,并從Request中移除當(dāng)前ContextHandler中添加的ServletRequestAttributeListener實例。

    ServletContextHandler實現(xiàn)

    ServletContextHandler繼承自ContextHandler類,它串連了SessionHandler、SecurityHandler和ServletHandler,在ServletContextHandler的start過程中,它會串連如下Handler:
    ServletContextHandler -....->SessionHandler->SecurityHandler->ServletHandler,由于ServletContextHandler、SessionHandler、ServletHandler都繼承自ScopedHandler,因而他們的執(zhí)行棧將會是:
    |->ServletContextHandler.doScope()
      |-> SessionHandler.doScope()
        |-> ServletHandler.doScope()
          |-> ServletContextHandler.doHandle()
            |-> .....handler.handle()
              |-> SessionHandler.doHandle()
                |-> SecurityHandler.handle()
                  |-> ServletHandler.doHandle()

    另外ServletContextHandler還提供了一個Decorator的擴(kuò)展點,可以向ServletContextHandler注冊多個Decorator,在ServletContextHandler啟動時,它會對每個已注冊的ServletHolder和FilterHolder執(zhí)行一些額外的“裝飾”邏輯,出了對ServletHolder和FilterHolder的裝飾,它還可以裝飾Filter、Servlet、Listener等,以及在銷毀他們時加入一下自定義的邏輯:
        public interface Decorator {
            <T extends Filter> T decorateFilterInstance(T filter) throws ServletException;
            <T extends Servlet> T decorateServletInstance(T servlet) throws ServletException;
            <T extends EventListener> T decorateListenerInstance(T listener) throws ServletException;

            void decorateFilterHolder(FilterHolder filter) throws ServletException;
            void decorateServletHolder(ServletHolder servlet) throws ServletException;
            
            void destroyServletInstance(Servlet s);
            void destroyFilterInstance(Filter f);
            void destroyListenerInstance(EventListener f);
        }

    Decorator擴(kuò)展點的引入實現(xiàn)了兩種方式對Servlet、Filter、EventListener的配置:Annotation方式(AnnotationDecorator)和Plus方式(PlusDecorator),其中Annotation的方式的配置是Servlet 3.0規(guī)范中新加入的特性,而Plus方式則是Jetty提供的配置注入。
    其中AnnotationDecorator的實現(xiàn)采用AnnotationInstrospector,可以向它注冊不同的InstrospectableAnnotationHandler,用以處理不同的Annotation邏輯,從而實現(xiàn)對動態(tài)注冊的Servlet、Filter、EventListener,可以使用在它們之上的Annotation來做進(jìn)一步的配置,以簡化配置本身。在Jetty中實現(xiàn)了以下幾個Annotation的InstrospectableAnnotationHandler:
    @Resource          => ResourceAnnotationHandler: 對類上的@Resource注解,將它作為一種資源綁定到當(dāng)前Context或Server中,對Field或Method的@Resource注解,創(chuàng)建一個Injection實例放入Context的Attribute中。在PlusDecorator中會對注冊的Injection實例做inject操作。
    @Resources         => ResourcesAnnotationHandler: 對類上的@Resources注解中的每個@Resource注解作為一種資源綁定到當(dāng)前Context或Server中。
    @RunAs              => RunAsAnnotationHandler: 關(guān)聯(lián)Servlet上@RunAs注解的值到該ServletHolder中。
    @ServletSecurity => SecurityAnnotationHandler: 為@ServletSecurity注解的Servlet配置DataConstraint、Roles、methodOmission等。
    @PostConstruct    => PostConstructAnnotationHandler: 將有該注解的方法注冊PostConstructCallback回調(diào)類,在PlusDecorator中的decorate方法中會調(diào)用該callback。
    @PreDestroy        => PreDestroyAnnotationHandler: 將有該注解的方法注冊PreDestroyCallback回調(diào)類,在PlusDecorator中的decorate方法中會調(diào)用該callback。
    @MultipartConfig  => MultipartConfigAnnotationHandler: 將有該注解的Servlet類注冊配置的MultipartConfig信息。
    @DeclareRoles     => DeclareRolesAnnotationHandler: 向SecurityHandler注冊定義的Role集合。
    而PlusDecorator主要處理使用以上Annotation或PlusDescriptorProcessor注冊的RunAsCollection、InjectionCollection、LifeCycleCallbackCollection的邏輯實現(xiàn)。其中RunAsCollection用于向注冊的對應(yīng)的ServletHolder注冊RunAsRole信息;InjectionCollection實現(xiàn)從JNDI中查找對應(yīng)JndiName的實例,并將其設(shè)置到Injection中指定的字段或方法中;LifeCycleCallbackCollection用于實現(xiàn)在Servlet、Filter、EventListener創(chuàng)建后或銷毀前調(diào)用相應(yīng)的有@PostConstruct注解或@PreDestroy注解的方法。

    WebAppContext實現(xiàn)

    WebAppContext繼承自ServletContextHandler,主要用于整合對ServletContextHandler的配置、配置WebAppClassLoader、設(shè)置war包路徑、設(shè)置contextWhiteList、保存MetaData信息等。

    對WebAppContext的配置,Jetty使用Configuration接口類抽象這個行為,其接口定義如下(方法名稱都比較直觀):
    public interface Configuration {
        public void preConfigure (WebAppContext context) throws Exception;
        public void configure (WebAppContext context) throws Exception;
        public void postConfigure (WebAppContext context) throws Exception;
        public void deconfigure (WebAppContext context) throws Exception;
        public void destroy (WebAppContext context) throws Exception;
        public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception;
    }
    可以使用setConfigurationClasses或setConfigurations方法自定義當(dāng)前支持的Configuration集合,Jetty默認(rèn)添加集合有:WebInfConfiguration、WebXmlConfiguration、MetaInfConfiguration、FragmentConfiguration、JettyWebXmlConfiguration,另外Jetty內(nèi)部默認(rèn)實現(xiàn)的還有:AnnotationConfiguration、ContainerInitializerConfiguration、EnvConfiguration、PlusConfiguration、TagLigConfiguration等。

    在WebInfConfiguration實現(xiàn)中,在其preConfigure方法中,如果存在WEB-INF/work目錄,先在該目錄下創(chuàng)建一個名為Jetty_<host>_<port>__<resourceBase>_<contextPath>_<virtualhost><base36_hashcode_of_whole_string>的臨時目錄,然后設(shè)置WebAppContext的臨時目錄:
    1. 可以手動設(shè)置。
    2. 可以使用javax.servlet.context.tempdir屬性值設(shè)置。
    3. 可以設(shè)置為${jetty.home}/work/Jetty_<host>_<port>__<resourceBase>_<contextPath>_<virtualhost><base36_hashcode_of_whole_string>
    4. 可以使用屬性org.eclipse.jetty.we
    pasting
    bapp.basetempdir指定的base,然后設(shè)置為${base}/Jetty_<host>_<port>__<resourceBase>_<contextPath>_<virtualhost><base36_hashcode_of_whole_string>
    5. 可以設(shè)置為${java.io.tmpdir}/Jetty_<host>_<port>__<resourceBase>_<contextPath>_<virtualhost><base36_hashcode_of_whole_string>
    6. 所有以上設(shè)置失敗,則使用File.createTempFile("JettyContext", "")的目錄來設(shè)置。
    對于war包,如果配置了extractWAR為true,則將war包解壓到war包所在目錄的war包名的目錄或<tempDir>/webapp目錄下,如果配置了copyWebDir,則將原本配置的BaseResource下的所有內(nèi)容拷貝到<tempDir>/webapp目錄下,使用新的web_app目錄設(shè)置BaseResource目錄;如果配置了copyWebInf為true,則將WEB-INF/lib, WEB-INF/classes的兩個目錄拷貝到<tempDir>/webinf/lib, <tempDir>/webinf/classes目錄下,并更新BaseResource為原來webapp目錄和<tempDir>/webinf兩個目錄的組合;設(shè)置org.eclipse.jetty.server.webapp.ContainerIncludeJarParttern屬性,查找URLClassLoader中URL中對應(yīng)的jar包(即WebAppContext中配置的extraClassPath值),并添加到MetaData的containerJars集合中(如果不設(shè)置,則不會添加任何jar包);使用org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern屬性匹配WEB-INF/lib目錄下的所有jar包,并添加到MetaData的webInfJars集合中(如果不設(shè)置,默認(rèn)添加所有jar包)。
    在其configure()方法實現(xiàn)中,設(shè)置WebAppClassLoader的classPath為WEB-INF/classes, WEB-INF/lib目錄下的所有jar包,并將這些jar包添加到WebAppClassLoader中;并且如果配置了org.eclipse.jetty.resources屬性,則將配置的List<Resource>集合添加到WebAppContext的BaseResource中。

    WebXmlConfiguration的實現(xiàn),在preConfigure中,它向MetaData注冊webdefault.xml文件描述符;web.xml(默認(rèn)為WEB-INF/web.xml)文件描述符;以及override-web.xml文件描述符;在注冊過程中解析它們的absolute-ordering信息,將解析的結(jié)果合并到MetaData的ordering集合中。在configure方法實現(xiàn)中,它向MetaData添加StandardDescriptorProcessor。

    MetaInfConfiguration的實現(xiàn),在preConfigure()方法中,掃描MetaData中在WebInfConfiguration中注冊的所有containerJars和webInfJars 的jar包,將找到的META-INF/web-fragment.xml生成的Resource注冊到org.eclipse.jetty.webFragments屬性中,在FragmentConfiguration中會被進(jìn)一步添加到MetaData中;將META-INF/resources/對應(yīng)的Resource注冊到org.eclipse.jetty.resources屬性中,在WebInfConfiguration的configure方法中會將這些目錄添加到BaseResource集合中;將所有*.tld文件對應(yīng)的Resource注冊到org.eclipse.jetty.tlds屬性中,在TagLibConfiguration中,會對這些注冊TLD文件做進(jìn)一步的處理。

    FragmentConfiguration的實現(xiàn),在其preConfigure方法中,將MetaInfConfiguration中找到的web-fragment.xml文件對應(yīng)的Resource注冊到MetaData中,在注冊中首先解析它的ordering信息;在其configure方法中,它使用ordering中定義的順序邏輯對注冊的jar包進(jìn)行排序。

    JettyWebConfiguration的實現(xiàn),在其configure方法中,依次查找jetty8-web.xml, jetty-web.xml, web-jetty.xml文件,如果有找到任意一個,則使用XmlCofiguration對WebAppContext進(jìn)行配置。XmlConfiguration的實現(xiàn)參考《深入Jetty源碼之XmlConfiguration實現(xiàn)》

    在AnnotationConfiguration的實現(xiàn)中,在其configure()方法中,它首先向WebAppContext中注冊AnnotationDecorator;然后它創(chuàng)建AnnotationParser實例,然后向其注冊WebServletAnnotationHandler、WebFilterAnnotationHandler、WebListenerAnnotationHandler、ClassInheritanceHandler、ContainerInitializerAnnotationHandler,它們都實現(xiàn)了DiscoverableAnnotationHandler(其中ClassInheritanceHandler實現(xiàn)的是ClassHandler接口);最后掃瞄所有ClassPath下jar包、WEB-INF/classes以及WEB-INF/lib中的jar包下的每個類,對于所有注冊為systemClasses,非serverClasses的類,使用ClassInheritanceHandler紀(jì)錄所有類包含的直接子類以及所有接口包含的直接實現(xiàn)類,而WebFilterAnnotationHandler、WebServletAnnotationHandler、WebListenerAnnotationHandler用于注冊相應(yīng)的WebFilterAnnotation、WebServletAnnotation、WebListenerAnnotation,并添加到MetaData中DiscoveredAnnotation集合中,這些DiscoveredAnnotation在MetaData的resolve方法(WebAppContext.startContext()方法中被調(diào)用)調(diào)用時會向WebAppContext注冊對應(yīng)的FilterHolder、ServletHolder、EventListener,而ContainerInitializerAnnotationHandler則會將所有注冊的注解修飾的類添加到注冊的ContainerInitializer的annotatedTypeNames集合中,該集合在ContainerInitializerConfiguration將它自身以及它的所有子類、實現(xiàn)類添加到applicableTypeNames集合中,集合之前注冊的interestedTypes的所有子類、實現(xiàn)類傳遞到ServletContainerInitializer的onStartup()方法中。

    在ContainerInitializerConfiguration會使用AnnotationConfiguration中注冊ContainerInitializer實例列表,構(gòu)建applicableTypeNames,并調(diào)用其ServletContainerInitializer的onStartup方法。

    EnvConfiguration實現(xiàn),在preConfigure方法中使用XmlConfiguration以及WEB-INF/jetty-env.xml文件對WebAppContext進(jìn)行配置,并且綁定JNDI環(huán)境。

    TagLibConfiguration實現(xiàn),在preConfigure方法中向WebAppContext注冊TagLibListener(ServletContextListener),在TagLibListener的contextInitialized方法中,它首先查找所有能找到的web.xml中定義的*.tld文件、WEB-INF/*.tld文件、WEB-INF/tlds/*.tld文件、以及通過WebInfConfiguration在jar包中找到的*.tld文件,將每個tld文件解析成一個TldDescriptor,并且使用TldProcessor對它們進(jìn)行解析成EventListener列表,并注冊到WebAppContext中。

    PlusConfiguration實現(xiàn),在preConfigure中,它向WebAppContext添加PlusDecorator;在configure方法中添加PlusDescriptorProcessor。

    在WebAppContex啟動時:

    1. 根據(jù)WebAppContext的allowDuplicateFragmentNames屬性設(shè)置MetaData實例對應(yīng)的屬性。

     

    2. 調(diào)用preConfigure方法,它加載所有Configuration實例(用戶自定義或默認(rèn)設(shè)置:WebInfConfiguration、WebXmlConfiguration、MetaInfConfiguration、FragmentConfiguration、JettyWebXmlConfiguration);加載系統(tǒng)類規(guī)則集合(即不能被Web Application覆蓋的類,他們必須使用System ClassLoader加載,可以通過Server屬性org.eclipse.jetty.webapp.sysemClasses屬性定義,或者使用默認(rèn)值)以及Server類規(guī)則集合(不能被Web Application加載的類,他們需要使用System ClassLoader加載,可以使用Server屬性org.eclipse.jetty.webapp.serverClasses定義,或者使用默認(rèn)值,這兩個的區(qū)別參考WebAppClassLoader的實現(xiàn)解析);設(shè)置ClassLoader,默認(rèn)為WebAppClassLoader;調(diào)用所有Configuration的preConfigure方法。

    3. 調(diào)用startContext方法,他會調(diào)用Configuration的configure方法,以及MetaData的resolve方法;在MetaData的resolve方法中,他首先設(shè)置WebAppContext的javax.servlet.context.orderedLibs屬性,然后設(shè)置ServletContext的EffectiveMajorVersion和EffectiveMinorVersion,并遍歷通過Configuration注冊的DescriptorProcessor,對webDefaultRoots、webXmlRoot、webOverrideRoots等Descriptor進(jìn)行處理,以讀取Servlet、Filter、Listener等信息的定義,遍歷在Configuration中注冊的DiscoveredAnnotation,對所有找到的WebFilter、WebServlet、WebListener注解類進(jìn)行解析并添加到WeAppContext中,最后對在FragmentConfiguration中注冊的FragmentDescriptor以及DiscoveredAnnotation進(jìn)行相應(yīng)的處理已進(jìn)一步配置WebAppContext。

    4. 調(diào)用postConfiguration方法,即調(diào)用所有注冊的Configuration的postConfigure方法以做一些清理工作。

    WebAppClassLoader實現(xiàn)

    WebAppClassLoader是Jetty中用于對Servlet規(guī)范的ClassLoader的實現(xiàn),它集成子URLClassLoader。它不會加載任何System Class(使用System ClassLoader加載),對Java2中父ClassLoader優(yōu)先于子ClassLoader的規(guī)則,可以使用WebAppContext的setParentLoadPriority為true來配置。如果沒有配置父ClassLoader,則使用當(dāng)前的Thread Context ClassLoader,如果該ClassLoader也為null,則使用加載該類的ClassLoader,如果它還為null,則使用SystemClassLoader作為其父ClassLoader。

     

    在加載類時,WebAppClassLoader有SystemClass和ServerClass的類別,SystemClass是指在Web Application中可見的,但是他們不能被Web Application中的類(WEB-INF/classes,WEB-INF/lib中的類)覆蓋的類,而ServerClass是指這些類是Server部分的實現(xiàn),它對Web Application是不可見的,如果需要使用它們,可以將相應(yīng)的jar包添加到WEB-INF/lib中。

     

    WebAppClassLoader默認(rèn)支持.zip,.jar為擴(kuò)展名的文件中查找class定義,可以使用org.eclipse.jetty.webapp.WebAppClassLoader.extensions系統(tǒng)屬性添加更多的擴(kuò)展名文件支持(以“,”或“;”分隔)。WebAppClassLoader也會添加WebAppContext中的ExtraClassPath到其ClassPath中(以“,”或“;”分隔),即添加URL。

     

    在WebInfConfiguration的configure方法中,他會默認(rèn)的將所有WEB-INF/lib下的jar包以及WEB-INF/classes目錄添加到WebAppClassLoader的ClassPath中,即添加URL。

     

    在其loadClass的實現(xiàn)中,如果某class既是SystemClass又是ServerClass,則返回null;如果不是ServerClass,且是父ClassLoader優(yōu)先或者是SystemClass,則使用父ClassLoader加載,然后再使用當(dāng)前ClassLoader加載;在getResources和getResource的實現(xiàn)中,對于ServerClass它只能從當(dāng)前ClassLoader中查找,對SystemClass它只能從父ClassLoader中查找。

    posted on 2014-05-24 22:17 DLevin 閱讀(4186) 評論(1)  編輯  收藏 所屬分類: Jetty

    FeedBack:
    # re: 深入Jetty源碼之ContextHandler
    2014-05-26 11:50 | 手機(jī)賺錢網(wǎng)-手機(jī)賺錢軟件排行,手機(jī)賺錢平臺http://www.9izhuanqian.com
    手機(jī)賺錢網(wǎng)-手機(jī)賺錢軟件排行,手機(jī)賺錢平臺http://www.9izhuanqian.com  回復(fù)  更多評論
      
    主站蜘蛛池模板: 成年女人喷潮毛片免费播放| 亚洲av永久无码精品表情包| 亚洲精品国产日韩| 97在线观看永久免费视频| 97se亚洲综合在线| 1000部无遮挡拍拍拍免费视频观看| 亚洲综合视频在线| 成人午夜免费福利视频| 亚洲乱码中文论理电影| 性做久久久久久久免费看| 亚洲成在人线aⅴ免费毛片| 成人国产mv免费视频| 免费手机在线看片| 亚洲精品无码专区在线在线播放| 9久久免费国产精品特黄| 亚洲AV第一页国产精品| xx视频在线永久免费观看| 亚洲一区二区三区在线网站| 在线观看免费宅男视频| 污网站免费在线观看| 国产亚洲成av片在线观看| 最近的中文字幕大全免费8| 亚洲不卡1卡2卡三卡2021麻豆| 成人毛片18女人毛片免费96| 美女扒开屁股让男人桶爽免费| 久久亚洲精品无码观看不卡| 在线观看片免费人成视频无码| 亚洲欧洲日本精品| 国产小视频免费观看| 免费观看一区二区三区| 国产精品亚洲精品观看不卡| 日韩亚洲精品福利| 99久久免费精品视频| 亚洲欧美日韩久久精品| 国产亚洲精品激情都市| 五月婷婷综合免费| 成人在线免费视频| 亚洲成人网在线播放| 亚洲综合国产精品第一页 | yy一级毛片免费视频| 亚洲第一页在线视频|