`

SpringDM笔记12-Spring DM’s web Extender运行机制

 
阅读更多

   SpringDM把一个WAR作为一个Bundle, 其实是将对WAR的处理交给当前OSGi环境中的WEB容器去处理的,即:

WEB Application的创建和线程的管理委托给了WEB容器。 那么SpringDMV是如何决定一个Bundle是要委托给

WEB容得的呢?实现这个功能主要是通过Spring的:Extender 机制:

   如果一个安装的Bundle是以.war作为扩展名的,他将自动触发SpringDM's Web extender将对该Bundle的处

理委托给underlying的WEB 容器。

1.Structure of Spring DM web OSGi components

   SpringDM Web Extender 部署bundle至内嵌的Web容器需要的条件:

   ■ The bundle location (filename) ends with .war
   ■ The bundle contains a WEB-INF directory

   目录结构:

   my-web-bundle
        META-INF/
            MANIFEST.MF
        WEB-INF/
            web.xml

   When a bundle is detected as a web bundle, the web extender will trigger its deployment
   to the web container,
letting the latter handle everything.

   Bundle Context Path :

   (1) SpringDM Web Bundle算法计算:

   The default behavior of the Spring DM web extender, with respect to the definition of context  

   paths, is dictated by a context path strategy, the default being the DefaultContextPathStrategy

   class (in the org.springframework.osgi.web.deployer.support package). This default strategy
   bases its decision first on the presence of the Web-ContextPath header, and then, if the header

   isn’t present, on the location of the bundle, by removing the trailing .war or .jar (just like in our

   example). After that it falls back on some of the other bundle metadata (name, symbolic name, or

   identity) if it can’t use the bundle location.

   (2)明确定义:

   Web-ContextPath: mycontext

2. Classloading in web bundles

2.1 Traditional,Standerd Web Application ClassPath's Structure

    ■ WEB-INF/classes directory—Contains application classes (web controllers, such as servlets). 

       They’re under their .class file form (not packaged) and organized following the traditional

       tree-like structure of Java packages.
    ■ WEB-INF/lib directory—Contains third-party libraries, packaged as JAR files.

2.2 OSGi Web Bundle Class Loading

    When you deploy a web application using the Spring DM web extender,OSGi-specific classloading

    mechanisms take precedence. Remember that before being a web application, your application
    was also an OSGi bundle; as such, its classpath is the OSGi classpath. It benefits from everything

    OSGi provides for handling classloading (class visibility, versioning, reloading, and so on).

    (1)The web application will be able to load classes from the following locations:

    ■ Its bundle space (classes in the JAR or WAR and classes from all the associated bundle 

       fragments)
    ■ Classes from the packages imported with the Import-Package header
    ■ All the exported classes from bundles appearing in the Require-Bundle header

    (2)实现将SpringDM Web Bundle做成标准的WAR:

    The Bundle-Classpath header, which indicates to the OSGi platform where to find classes and

    resources in the bundle. This header defaults to ".", meaning the root of the bundle. You can

    override this default value and set it to the traditional locations of classes and libraries in WARs

    (you should not forget to include the default location):
    Bundle-Classpath: .,WEB-INF/classes,WEB-INF/lib/libA.jar,WEB-INF/lib/libB.jar

3. OSGi-aware Spring web container

    WAR Bundle 如何访问其他Bundle中的类?

    SpringDM总是努力尝试去创建一OSGi上下文:OgiBundleXmlApplicationContext,这个Context包括

    Spring Artifacts, 以及注册、消费的服务。而在WAR Bundle中,线程的管理被委托给了WEB容器,如果这个

    Context不明确指定对其他Bundel而言是不可见的。

    SpringDM解决这个问题是通过一个特殊的Context:OsgiBundleXmlWebApplicationContext,该Context

    与某个Bundel的Context关联,而该Context常常配置在web.xml文件中。见下面配置。

    In standard Spring-based web applications, the Spring container is started and stopped by the   

    web container itself, usually through a dedicated servlet listener, the ContextLoaderListener.

 

    The ContextLoaderListener  is part of the web module of the Spring Framework. You declare it in

    the web.xml file of your web application, and in it you can set the location of your Spring  

    configuration files and, more importantly in our case, the implementation of ApplicationContext

    you want to use. Spring DM comes with a specific application context implementation,

    OsgiBundleXmlWebApplicationContext , which can communicate with the OSGi platform even

    though its instances are created by a web container.

    Configuring a web application to use the OSGi web application context:

    <web-app (...)>
    (...)
         <context-param>

            <!-- ContextLoaderListener 根据该参数判定是哪一种类型的Web应用上下文,这个参数默认是:

            XmlWebApplicationContext,现在改成SOGi应用上下文,这样WAR Bundle则可以访问其它Bundle.       

            -->
            <param-name>contextClass</param-name>

            <param-value>

                 org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
            </param-value>
        </contxt-param>
        <context-param>

                <!--- 这个值默认为WEB-INF/applicationContext.xml,现在为自定义--->
                <param-name>contextConfigLocation</param-name>
                <param-value>
                     WEB-INF/applicationContext.xml,
                     WEB-INF/applicationContext-osgi.xml
               </param-value>
        </context-param>

       
        <listener>
             <listener-class>
                 org.springframework.web.context.ContextLoaderListener
             </listener-class>
        </listener>

 

        <servlet>
               <servlet-name>PBWDP</servlet-name>
                    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                    <load-on-startup>1</load-on-startup>
                    <init-param>
                           <param-name>contextClass</param-name>
                           <param-value>org.springframework.osgi.web.context.support

                                        .OsgiBundleXmlWebApplicationContext

                           </param-value>
                     </init-param>

         </servlet>

 

         <servlet-mapping>
                   <servlet-name>PBWDP</servlet-name>
                   <url-pattern>/APP/*</url-pattern>

          </servlet-mapping>
        (...)
     </web-app>

     注意:If you use the ContextLoaderListener and the OsgiBundleXmlWebApplicationContext in

     your web applications, you must include their respective packages in the Import-Package header

     of your web bundle manifest.

4. Spring DM web deployer

    SpringDM提供了一个用于指定Web上下文发布路径的Header:Web-ContextPath ,默认下该值为:

    http://localhost:8080/BundleName/

    可自己定制该值,如: 

    Web-ContextPath: HelloWorld

    访问路径为:http://localhost:8080/的HelloWorld/

 

    The Spring DM web extender is implemented as a synchronous bundle listener,which is registered

    by the activator of the bundle. The bundle listener doesn’t itself handle the deployment of web

    bundles; it delegates this perilous task to a WAR deployer.(TomcatWarDeplouer,JettyWarDeployer)

 

    Even though the activator of the web extender bundle coordinates and performs some of the  

    work (scanning of incoming bundles, thread management for deployment and undeployment), the

    WAR deployer is in charge of truly deploying (or undeploying) web applications to the embedded

    web container. Through the WarDeployer interface, Spring DM abstracts the action of deploying

    and undeploying WAR files, allowing a separation of concerns,because WarDeployer  

    implementations just handle the deployment process for their web container, whereas the web

    extender sticks to its primary goal: listening for bundles starting or stopping.

 

    Spring DM provides two implementations of WarDeployer: one for Apache Tomcat (the default)

    and one for Jetty .

 

    WAR deployers interact directly with the underlying web container instance when the web 

    extender hands them a WAR bundle. They can manage their own instance of the web container,
    but the usual way is to look it up in the OSGi service registry. By “instance of web container,”
    we mean an instance of the core class of the web container—org.apache.catalina.Service for    

    Tomcat and org.mortbay.jetty.Server for Jetty.

5. 切换不同的Web容器

    默认下,SpringDM将WAR委托给一个Tomcat实例,要切换成其他的Web容器,需要spring-osig-web

    -extendr.jar, 当该JAR启动时,它将是这定位一个Tomcat实例,如果找不带将产生下面的异常:

 

    Exception in thread "WebExtender-Init"`java.lang.NoClassDefFoundError:

    org/apache/CatalinaLoader

 

    如果找到一个Tomcat实例并且所有的依赖被Resolved,SpringDM将试着获取已经注册了得一个服务:

    org.apache.catalina.Service, 如果找不到该服务,将产生下面异常:

 

    org.springframework.osgi.OsgiException: Cannot create Tomcat deployer

 

    根据上述理解,SpingDM使用不同的Web容器时需要考虑下面两个问题:

    (1) Override SpringDM默认的extender value,而使用另一个Web容器;

    (2) 由一个服务注册Bundle去启动OSGi Web 容器;

    解决第一个问题可以使用OSGi 的Fragment来实现, 而解决第二个问题需要新开发一个启动Web容器的Bundle,

    Tomcat和Jetty容器依赖于自己的配置文件(server.xml、jetty.xml)来制定Web容器的端口,SSL证书等信息;

    因此该Bundle需包括启动Web容器的配置文件及将该Web容器注册为服务的一系列功能。 开发该Bundel可参考

    Tomcat与jetty的实现:catalina.start.osgi-1.0.0.jar和jetty.start.osgi-1.0.0.jar。 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics