隨筆 - 19, 文章 - 1, 評論 - 21, 引用 - 0
          數據加載中……

          打造一個基于OSGi的Web Application——使用Tomcat原生API來動態管理Web元素:原理

          Tomcat的org.apache.catalina.Context接口提供了動態管理注入到Catalina Web Container中的Web元素的API。在基于OSGi的Web Application中,可以利用這個接口來實現在OSGi容器中動態管理Web元素的目的。為了達到這個目的,我們還需要做一些額外的配置。請注意,以下方法僅適用于Tomcat,并非通用的實現,而且只針對5.5.28版和6.0.24版的Tomcat做過簡單的測試。


          首先我們要做的事情,就是將Tomcat的org.apache.catalina.Context實現類作為Service注入到OSGi容器中去。在OSGi-Web工程的WebContent/META-INF目錄中,增加一個context.xml文件,內容如下:
          1 <?xml version="1.0" encoding="UTF-8"?>
          2 <Context privileged="true"/>
          這樣我們就可以使用org.apache.catalina.ContainerServlet這個接口類了,通過它可以訪問Catalina的內部功能,它有Catalina被類加載器加載,而不是我們的WebApplication類加載器。它的 Setter方法在這個Servlet的新的實例被放進Service時被執行。
          接下來我們寫一個Servlet,這個Servlet將實現ContainerServlet接口,請注意它是怎么工作的:
           1 package org.dbstar.osgi.web.launcher.tomcat;
           2 
           3 import java.util.Properties;
           4 
           5 import javax.servlet.ServletException;
           6 import javax.servlet.UnavailableException;
           7 import javax.servlet.http.HttpServlet;
           8 
           9 import org.apache.catalina.ContainerServlet;
          10 import org.apache.catalina.Context;
          11 import org.apache.catalina.Wrapper;
          12 import org.dbstar.osgi.web.launcher.FrameworkConfigListener;
          13 import org.osgi.framework.BundleContext;
          14 import org.osgi.framework.ServiceRegistration;
          15 import org.osgi.framework.launch.Framework;
          16 
          17 public final class TomcatContextServlet extends HttpServlet implements ContainerServlet {
          18     private static final long serialVersionUID = -3977062987005392657L;
          19 
          20     private Wrapper wrapper;
          21     private Context context;
          22 
          23     private ServiceRegistration registration;
          24 
          25     public Wrapper getWrapper() {
          26         return wrapper;
          27     }
          28 
          29     public void setWrapper(Wrapper wrapper) {
          30         this.wrapper = wrapper;
          31         if (wrapper == null) context = null;
          32         else context = (Context) wrapper.getParent();
          33     }
          34 
          35     @Override
          36     public void init() throws ServletException {
          37         // Ensure that our ContainerServlet properties have been set
          38         if ((wrapper == null|| (context == null)) throw new UnavailableException("Wrapper not set.");
          39 
          40         // Ensure that Framework have been set
          41         Framework framework = FrameworkConfigListener.getFramework();
          42         if (framework == nullthrow new UnavailableException("Framework not set.");
          43 
          44         // 將context注冊為服務
          45         registration = registerContext(framework.getBundleContext(), context);
          46     }
          47 
          48     private static ServiceRegistration registerContext(BundleContext bundleContext, Context context) {
          49         Properties properties = new Properties();
          50         properties.setProperty("DisplayName", context.getDisplayName());
          51         properties.setProperty("ContextPath", context.getPath());
          52         return bundleContext.registerService(Context.class.getName(), context, properties);
          53     }
          54 
          55     @Override
          56     public void destroy() {
          57         if (registration == nullreturn;
          58 
          59         Framework framework = FrameworkConfigListener.getFramework();
          60         if (framework == nullreturn;
          61 
          62         if (framework.getState() == Framework.ACTIVE) registration.unregister();
          63         registration = null;
          64     }
          65 }
          通過ContainerServlet接口提供的setWrapper方法,我們獲得了一個Wrapper實例,這個實例對應于TomcatContextServlet部署到Tomcat中的封裝類,通過其getParent方法我們就可以獲得Servlet所在的Context了。
          接下來在init方法中,我們將獲得的Context實例,通過Framework注冊到OSGi容器中去。在destroy方法中,注銷Context的注冊,這樣形成了一個完整的生命周期。
          然后,將這個TomcatContextServlet部署到web.xml中去:
          1     <!-- register a org.apache.catalina.Context to OSGi Container    -->
          2     <servlet>
          3         <servlet-name>TomcatContextServlet</servlet-name>
          4         <servlet-class>org.dbstar.osgi.web.launcher.tomcat.TomcatContextServlet</servlet-class>
          5         <load-on-startup>1</load-on-startup>
          6     </servlet>
          設置<load-on-startup>使這個Servlet在WebContainer初始化時加載,否則它將沒有加載的機會,因為我們在應用中不會直接使用到這個Servlet。

          最后還有一件事情不要忘記了,我們需要將org.apache.catalina及其相關的package export到OSGi容器中去,這樣才能在OSGi容器中供給bundle來import。參照《打造一個基于OSGi的Web Application——為OSGi容器提供Web Application環境》一文中提到的方式,我們將catalina.jar作為extension Fragment的方式,引入到OSGi容器中去。
          Catalina的MANIFEST.MF:
           1 Manifest-Version: 1.0
           2 Bundle-ManifestVersion: 2
           3 Bundle-Name: Catalina Extension Fragment
           4 Bundle-SymbolicName: org.apache.catalina_extension;singleton:=true
           5 Bundle-Version: 5.5.28
           6 Bundle-Vendor: dbstar
           7 Fragment-Host: system.bundle; extension:=framework
           8 Bundle-RequiredExecutionEnvironment: J2SE-1.5
           9 Export-Package: org.apache.catalina,org.apache.catalina.authenticator,
          10  org.apache.catalina.connector,org.apache.catalina.core,org.apache.cat
          11  alina.deploy,org.apache.catalina.loader,org.apache.catalina.mbeans,or
          12  g.apache.catalina.realm,org.apache.catalina.security,org.apache.catal
          13  ina.session,org.apache.catalina.startup,org.apache.catalina.users,org
          14  .apache.catalina.util,org.apache.catalina.valves

          在接下來的章節中,我會逐一描述如何在基于Tomcat的OSGi容器中,如何實現各種Web元素的動態管理,盡請期待哦:)

          最后提供幾個本章提到的bundle給大家下載,大家就不用自己再起生成一個了。
          org.apache.catalina_extension_5.5.28.jar


          posted on 2010-04-01 12:02 dbstar 閱讀(3102) 評論(0)  編輯  收藏 所屬分類: OSGi

          主站蜘蛛池模板: 呼图壁县| 湖北省| 峨眉山市| 通州市| 基隆市| 大化| 讷河市| 葫芦岛市| 义乌市| 宁安市| 股票| 抚松县| 彩票| 沅陵县| 汾西县| 修文县| 塘沽区| 天柱县| 文成县| 锦屏县| 同心县| 五寨县| 象山县| 唐河县| 达州市| 酒泉市| 山阳县| 元江| 延长县| 出国| 永年县| 绥德县| 炉霍县| 卢氏县| 新密市| 临猗县| 台湾省| 米泉市| 徐闻县| 黑河市| 石门县|