wolong 发表于 2017-1-29 06:09:38

扩展Tomcat支持OSGi应用服务(3)

4.测试
  
通过以上的实现,我们将OSGi平台集成到了Tomcat中,并且明确了web应用如何使用OSGi服务。下面就来创建一个测试的例子,看看OSGi编程模式对web应用开发的影响,同时也测试一下集成的效果。

4.1 创建并发布OSGi服务
  Step1.创建插件工程com.dinstone.demo.user,选择standard OSGi framework。创建接口:


  package com.dinstone.demo.user;
  
  publicinterface IUserService {
  
public String getUserName(String id);
  }


  Step2.创建插件工程com.dinstone.demo.user.db,创建类UserServiceImpl实现IUserService接口。


  package com.dinstone.demo.user.db;
  imp<wbr>ort java.util.logging.Logger;</wbr>
  imp<wbr>ort com.dinstone.demo.user.IUserService;</wbr>
  
  public class UserServiceImpl implements IUserService {
  
   private static Logger log = Logger.getLogger(UserServiceImpl.class
   .getName());
  
   @Override
   public String getUserName(String id) {
   log.info("get user name from db");
   return "db" + id;
   }
  }


  
  Step3.向OSGi平台发布IUserService服务。创建Activator注册服务对象。


  package com.dinstone.demo.user.db;
  
  imp<wbr>ort java.util.Properties;</wbr>
  
  imp<wbr>ort org.osgi.framework.BundleActivator;</wbr>
  imp<wbr>ort org.osgi.framework.BundleContext;</wbr>
  imp<wbr>ort org.osgi.framework.ServiceRegistration;</wbr>
  
  imp<wbr>ort com.dinstone.demo.user.IUserService;</wbr>
  
  public class Activator implements BundleActivator {
  
   private ServiceRegistration serviceReg;
  
   /*
   * (non-Javadoc)
   *
   * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
   */
   public void start(BundleContext context) throws Exception {
   Properties p = new Properties();
   serviceReg = context.registerService(IUserService.class.getName(),
   new UserServiceImpl(), p);
   }
  
   /*
   * (non-Javadoc)
   *
   * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
   */
   public void stop(BundleContext context) throws Exception {
   serviceReg.unregister();
   }
  
  }


  
  Step4.
创建插件工程com.dinstone.demo.user.file,创建类UserServiceImpl实现IUserService接口。


  package com.dinstone.demo.user.file;
  
  imp<wbr>ort java.util.logging.Logger;</wbr>
  
  imp<wbr>ort com.dinstone.demo.user.IUserService;</wbr>
  
  public class UserServiceImpl implements IUserService {
  
   private static Logger log = Logger.getLogger(UserServiceImpl.class
   .getName());
  
   @Override
   public String getUserName(String id) {
   log.info("get user name from file");
   return "file" + id;
   }
  }


  
  Step5.向OSGi平台发布IUserService服务。创建Activator注册服务对象。


  package com.dinstone.demo.user.file;
  
  imp<wbr>ort java.util.Properties;</wbr>
  
  imp<wbr>ort org.osgi.framework.BundleActivator;</wbr>
  imp<wbr>ort org.osgi.framework.BundleContext;</wbr>
  imp<wbr>ort org.osgi.framework.ServiceRegistration;</wbr>
  
  imp<wbr>ort com.dinstone.demo.user.IUserService;</wbr>
  
  public class Activator implements BundleActivator {
  
   private ServiceRegistration serviceReg;
  
   /*
   * (non-Javadoc)
   *
   * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
   */
   public void start(BundleContext context) throws Exception {
   Properties p = new Properties();
   serviceReg = context.registerService(IUserService.class.getName(),
   new UserServiceImpl(), p);
   }
  
   /*
   * (non-Javadoc)
   *
   * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
   */
   public void stop(BundleContext context) throws Exception {
   serviceReg.unregister();
   }
  }


  

4.2 创建Web应用
  Step1.创建动态web工程webDemo,并新建类:UserServiceFacade。


  package com.dinsotne.web.demo;
  
  imp<wbr>ort com.dinsotne.web.osgi.OsgiServiceFacade;</wbr>
  imp<wbr>ort com.dinstone.demo.user.IUserService;</wbr>
  
  public class UserServiceFacade {
  
   public static String getUserName(String id) {
   try {
   IUserService service = OsgiServiceFacade.getOsgiService(
   "osgi/services", IUserService.class, IUserService.class
   .getName());
  
   return service.getUserName(id);
   } catch (IllegalArgumentException e) {
   e.printStackTrace();
   e.printStackTrace();
   }
  
   return null;
   }
  }


  
  Step2.创建index.jsp页面。


  <%@
page language="java"
contentType="text/html; charset=utf-8"
  
pageEncoding="ISO-8859-1"%>
  <!DOCTYPE
html PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  <%@page
imp<wbr>ort</wbr>="com.dinsotne.web.demo.UserServiceFacade"%>
  <html>
  <head>
  <meta
http-equiv="Content-Type"
content="text/html; charset=utf-8">
  <title>Insert title here</title>
  </head>
  <body>
  User Name is
  <%=UserServiceFacade.getUserName("001")
%>
  
  </body>
  </html>


  
  Step3.修改web.xml文件,添加红色部分。


  <?xml
version="1.0"
encoding="UTF-8"?>
  <web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  
xmlns="http://java.sun.com/xml/ns/javaee"
  
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  
id="WebApp_ID"
version="2.5">
  
<display-name>webDemo</display-name>
  
<welcome-file-list>
  
<welcome-file>index.html</welcome-file>
  
<welcome-file>index.htm</welcome-file>
  
<welcome-file>index.jsp</welcome-file>
  
<welcome-file>default.html</welcome-file>
  
<welcome-file>default.htm</welcome-file>
  
<welcome-file>default.jsp</welcome-file>
  
</welcome-file-list>
   <resource-env-ref>
  
<description>osgi service</description>
  
<resource-env-ref-name>osgi/services</resource-env-ref-name>
  
<resource-env-ref-type>
  
com.dinstone.osgi.OsgiServices
  
</resource-env-ref-type>
   </resource-env-ref>
  </web-app>


  
  说明:
  1.
由于UserServiceFacade依赖IUserService类,故需要将com.dinstone.demo.user_1.0.0.jar(参见4.3)添加到lib中。
  2.
由于UserServiceFacade依赖OsgiServiceFacade类,故将com.dinsotne.web.osgi_1.12.0.jar(参见3.4说明)添加到lib中。
  

4.3 发布OSGi Bundle
  Step1.依次从插件工程导出插件包:com.dinstone.demo.user_1.0.0.jar,com.dinstone.demo.user.file_1.0.0.jar,com.dinstone.demo.user.db_1.0.0.jar。
  Step2.将以上的插件放于${Tomcat_Home}\osgi\felix\bundle目录下。
  

4.4 发布web应用
  Step1.导出web应用webDemo.war。
  Step2.将webDemo.war放于${Tomcat_Home}\webapps目录下。
  

4.5 启动Tomcat并安装OSGi Bundle
  Step1.在命令行下启动Tomcat。E:\Cluster\apache-tomcat-6.0.18为我的${Tomcat_Home}。


  E:\Cluster\apache-tomcat-6.0.18>bin\startup.bat
  Using CATALINA_BASE: E:\Cluster\apache-tomcat-6.0.18
  Using CATALINA_HOME: E:\Cluster\apache-tomcat-6.0.18
  Using CATALINA_TMPDIR: E:\Cluster\apache-tomcat-6.0.18\temp
  Using JRE_HOME: C:\Program Files\Java\jdk1.6.0_10
  2009-8-12 13:21:39 com.dinstone.tomcat.osgi.OsgiLifecycleListener lifecycleEvent
  信息: The osgi content is initialized. Using osgi content:felix
  2009-8-12 13:21:39 org.apache.coyote.http11.Http11Protocol init
  信息: Initializing Coyote HTTP/1.1 on http-8080
  2009-8-12 13:21:40 org.apache.coyote.http11.Http11Protocol init
  信息: Initializing Coyote HTTP/1.1 on http-8443
  2009-8-12 13:21:40 org.apache.catalina.startup.Catalina load
  信息: Initialization processed in 1748 ms
  2009-8-12 13:21:41 com.dinstone.tomcat.osgi.OsgiLifecycleListener lifecycleEvent
  信息: Starting osgi service.
  2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start
  信息: *********************************
  2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start
  信息: catalina home is E:\Cluster\apache-tomcat-6.0.18
  2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start
  信息: osgi home is E:\Cluster\apache-tomcat-6.0.18\osgi\felix
  2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start
  信息: ******user.dir is E:\Cluster\apache-tomcat-6.0.18
  
  Welcome to Felix.
  =================
  
  -> 2009-8-12 13:21:42 org.apache.catalina.core.StandardService start
  信息: Starting service Catalina
  2009-8-12 13:21:42 org.apache.catalina.core.StandardEngine start
  信息: Starting Servlet Engine: Apache Tomcat/6.0.18
  2009-8-12 13:21:42 org.apache.catalina.loader.WebappLoader start
  信息: Dual registration of jndi stream handler: factory already defined
  2009-8-12 13:21:44 org.apache.coyote.http11.Http11Protocol start
  信息: Starting Coyote HTTP/1.1 on http-8080
  2009-8-12 13:21:44 org.apache.coyote.http11.Http11Protocol start
  信息: Starting Coyote HTTP/1.1 on http-8443
  2009-8-12 13:21:44 org.apache.jk.common.ChannelSocket init
  信息: JK: ajp13 listening on /0.0.0.0:8009
  2009-8-12 13:21:44 org.apache.jk.server.JkMain start
  信息: Jk running ID=0 time=0/47 config=null
  2009-8-12 13:21:44 org.apache.catalina.startup.Catalina start
  信息: Server startup in 3882 ms
  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  ->


  
  Step2.安装bundle。


  -> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user_1.0.0.jar
  Bundle ID: 39
  -> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user.db_1.0.0.jar
  Bundle ID: 40
  -> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user.file_1.0.0.jar
  Bundle ID: 41
  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  ->


  Step3.访问web应用,http://localhost:8080/webDemo/。由于没有启动OSGi服务,故出现500异常页面,错误原因是没有找到服务。


  root cause


com.dinsotne.web.osgi.IllegalServiceException: Cann't find out osgi service:com.dinstone.demo.user.IUserService
com.dinsotne.web.osgi.OsgiServiceInvocationHandler.invoke(OsgiServiceInvocationHandler.java:30)
$Proxy0.getUserName(Unknown Source)
com.dinsotne.web.demo.UserServiceFacade.getUserName(UserServiceFacade.java:14)
org.apache.jsp.index_jsp._jspService(index_jsp.java:64)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)


  
  Step4.启动User DB Implement Plug-in服务,激活User模块的DB实现。


  ->ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  -> start 40
  -> ps -s
  START LEVEL 1
   ID State Level Symbolic name
  [ 0] [ 0] org.apache.felix.framework (1.6.0)
  [ 25] [ 1] org.apache.felix.shell (1.2.0)
  [ 26] [ 1] org.apache.felix.shell.tui (1.2.0)
  [ 27] [ 1] org.apache.felix.bundlerepository (1.4.0)
  [ 39] [ 1] com.dinstone.demo.user (1.0.0)
  [ 40] [ 1] com.dinstone.demo.user.db (1.0.0)
  [ 41] [ 1] com.dinstone.demo.user.file (1.0.0)
  ->


  访问http://localhost:8080/webDemo/。页面显示:
  
  
  
  Step5.
启动User File Implement Plug-in服务,激活User模块的File实现。


  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  -> start 41
  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  ->


  
  访问http://localhost:8080/webDemo/。页面显示:
  
  
  
  Step6.现在停止User DB Implement Plug-in服务。


  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  -> stop 40
  -> ps
  START LEVEL 1
   ID State Level Name
  [ 0] [ 0] System Bundle (1.6.0)
  [ 25] [ 1] Apache Felix Shell Service (1.2.0)
  [ 26] [ 1] Apache Felix Shell TUI (1.2.0)
  [ 27] [ 1] Apache Felix Bundle Repository (1.4.0)
  [ 39] [ 1] User Model Interface Plug-in (1.0.0)
  [ 40] [ 1] User DB Implement Plug-in (1.0.0)
  [ 41] [ 1] User File Implement Plug-in (1.0.0)
  ->


  
  访问http://localhost:8080/webDemo/。页面显示:
  
  
  

4.6 停止Tomcat服务器
  重新打开一个命令行窗口,切换到${Tomcat_Home}\bin目录下。执行:


  E:\Cluster\apache-tomcat-6.0.18\bin>shutdown.bat


  Tomcat服务器关闭。

5结论
  
通过以上的测试,我们发现以上的实现基本符合最初的设想:
  l
OSGi的集成对Tomcat几乎是透明的。
  l
OSGi的所有优点。
  l
Web表现和业务逻辑的完全分离。
  l 基于模块化服务的编程模型。
  
  同时,我们也发现了一些问题:
  l
Web层没有支持模块化、可热插拔的编程模型。
  l
OSGi层的服务日志跟web层的日志分离增加了维护的难度。
  l 该集成方式没有经严格测试,虽然已经有产品应用了。

附录:

1.测试Demo
  …

2.源码工程
  …
页: [1]
查看完整版本: 扩展Tomcat支持OSGi应用服务(3)