<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中實現對一個Web Application的各種資源進行管理,并串聯實現整個Servlet框架的類,比如它部分實現了ServletContext接口,并且在其doScope方法中為當前Request的執行提供了相應的環境,如設置servletPath、pathInfo、設置ServletContext到ThreadLocal中。在Jetty中,Servlet的執行流程和框架由ServletHandler實現,Security框架由SecurityHandler完成,而ContextHandler主要用于實現環境的配置,如Request狀態的設置、ClassLoader的配置、ServletContext的實現等。在ContextHandler類中包含了一個Context的內部類,用于實現ServletContext,而ContextHandler中的很多字段和方法也是用于實現ServletContext,不細述。

    ContextHandler實現

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

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

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

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

    ServletContextHandler實現

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

    另外ServletContextHandler還提供了一個Decorator的擴展點,可以向ServletContextHandler注冊多個Decorator,在ServletContextHandler啟動時,它會對每個已注冊的ServletHolder和FilterHolder執行一些額外的“裝飾”邏輯,出了對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擴展點的引入實現了兩種方式對Servlet、Filter、EventListener的配置:Annotation方式(AnnotationDecorator)和Plus方式(PlusDecorator),其中Annotation的方式的配置是Servlet 3.0規范中新加入的特性,而Plus方式則是Jetty提供的配置注入。
    其中AnnotationDecorator的實現采用AnnotationInstrospector,可以向它注冊不同的InstrospectableAnnotationHandler,用以處理不同的Annotation邏輯,從而實現對動態注冊的Servlet、Filter、EventListener,可以使用在它們之上的Annotation來做進一步的配置,以簡化配置本身。在Jetty中實現了以下幾個Annotation的InstrospectableAnnotationHandler:
    @Resource          => ResourceAnnotationHandler: 對類上的@Resource注解,將它作為一種資源綁定到當前Context或Server中,對Field或Method的@Resource注解,創建一個Injection實例放入Context的Attribute中。在PlusDecorator中會對注冊的Injection實例做inject操作。
    @Resources         => ResourcesAnnotationHandler: 對類上的@Resources注解中的每個@Resource注解作為一種資源綁定到當前Context或Server中。
    @RunAs              => RunAsAnnotationHandler: 關聯Servlet上@RunAs注解的值到該ServletHolder中。
    @ServletSecurity => SecurityAnnotationHandler: 為@ServletSecurity注解的Servlet配置DataConstraint、Roles、methodOmission等。
    @PostConstruct    => PostConstructAnnotationHandler: 將有該注解的方法注冊PostConstructCallback回調類,在PlusDecorator中的decorate方法中會調用該callback。
    @PreDestroy        => PreDestroyAnnotationHandler: 將有該注解的方法注冊PreDestroyCallback回調類,在PlusDecorator中的decorate方法中會調用該callback。
    @MultipartConfig  => MultipartConfigAnnotationHandler: 將有該注解的Servlet類注冊配置的MultipartConfig信息。
    @DeclareRoles     => DeclareRolesAnnotationHandler: 向SecurityHandler注冊定義的Role集合。
    而PlusDecorator主要處理使用以上Annotation或PlusDescriptorProcessor注冊的RunAsCollection、InjectionCollection、LifeCycleCallbackCollection的邏輯實現。其中RunAsCollection用于向注冊的對應的ServletHolder注冊RunAsRole信息;InjectionCollection實現從JNDI中查找對應JndiName的實例,并將其設置到Injection中指定的字段或方法中;LifeCycleCallbackCollection用于實現在Servlet、Filter、EventListener創建后或銷毀前調用相應的有@PostConstruct注解或@PreDestroy注解的方法。

    WebAppContext實現

    WebAppContext繼承自ServletContextHandler,主要用于整合對ServletContextHandler的配置、配置WebAppClassLoader、設置war包路徑、設置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方法自定義當前支持的Configuration集合,Jetty默認添加集合有:WebInfConfiguration、WebXmlConfiguration、MetaInfConfiguration、FragmentConfiguration、JettyWebXmlConfiguration,另外Jetty內部默認實現的還有:AnnotationConfiguration、ContainerInitializerConfiguration、EnvConfiguration、PlusConfiguration、TagLigConfiguration等。

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

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

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

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

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

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

    在ContainerInitializerConfiguration會使用AnnotationConfiguration中注冊ContainerInitializer實例列表,構建applicableTypeNames,并調用其ServletContainerInitializer的onStartup方法。

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

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

    PlusConfiguration實現,在preConfigure中,它向WebAppContext添加PlusDecorator;在configure方法中添加PlusDescriptorProcessor。

    在WebAppContex啟動時:

    1. 根據WebAppContext的allowDuplicateFragmentNames屬性設置MetaData實例對應的屬性。

     

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

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

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

    WebAppClassLoader實現

    WebAppClassLoader是Jetty中用于對Servlet規范的ClassLoader的實現,它集成子URLClassLoader。它不會加載任何System Class(使用System ClassLoader加載),對Java2中父ClassLoader優先于子ClassLoader的規則,可以使用WebAppContext的setParentLoadPriority為true來配置。如果沒有配置父ClassLoader,則使用當前的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部分的實現,它對Web Application是不可見的,如果需要使用它們,可以將相應的jar包添加到WEB-INF/lib中。

     

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

     

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

     

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

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

    FeedBack:
    # re: 深入Jetty源碼之ContextHandler
    2014-05-26 11:50 | 手機賺錢網-手機賺錢軟件排行,手機賺錢平臺http://www.9izhuanqian.com
    手機賺錢網-手機賺錢軟件排行,手機賺錢平臺http://www.9izhuanqian.com  回復  更多評論
      
    主站蜘蛛池模板: 99久久免费看国产精品| 超pen个人视频国产免费观看| 亚洲国产日产无码精品| 在线观看成人免费视频| 丝袜足液精子免费视频| 亚洲伊人久久大香线蕉啊| 免费又黄又爽的视频| 最近2019免费中文字幕视频三| 蜜芽亚洲av无码一区二区三区| 亚洲gv白嫩小受在线观看| 浮力影院第一页小视频国产在线观看免费 | 99在线观看视频免费| 亚洲国产精品成人AV在线| 亚洲成AV人片在线观看无| 永久免费bbbbbb视频| 午夜免费福利片观看| 国产成人综合亚洲绿色| 亚洲综合亚洲国产尤物| 亚洲午夜无码片在线观看影院猛 | 久久九九兔免费精品6| 人与动性xxxxx免费| 亚洲综合丁香婷婷六月香| 久久久久亚洲AV无码专区桃色| 亚洲成在人线aⅴ免费毛片| 最近2019中文免费字幕在线观看| 亚洲成a人无码亚洲成www牛牛| 久久久久亚洲av无码专区喷水 | 国产亚洲精品影视在线| 亚洲成A人片在线观看无码不卡| 国产又黄又爽又猛的免费视频播放 | 亚洲国产精品成人网址天堂| 久久久久久久91精品免费观看| 中文在线观看国语高清免费| 亚洲AV无码资源在线观看| 亚洲欧洲国产成人精品| 亚洲成AV人片在线观看无| 国产成人亚洲综合| 国产精品免费视频播放器| 欧美三级在线电影免费| 2020因为爱你带字幕免费观看全集| 中文日本免费高清|