扩展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.jarcom.dinstone.demo.user.file_1.0.0.jarcom.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.在命令行下启动TomcatE:\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] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 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] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Installed ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Installed ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Installed ] [ 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] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Installed ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Installed ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Installed ] [ 1] User File Implement Plug-in (1.0.0)

-> start 40

-> ps -s

START LEVEL 1

ID State Level Symbolic name

[ 0] [Active ] [ 0] org.apache.felix.framework (1.6.0)

[ 25] [Active ] [ 1] org.apache.felix.shell (1.2.0)

[ 26] [Active ] [ 1] org.apache.felix.shell.tui (1.2.0)

[ 27] [Active ] [ 1] org.apache.felix.bundlerepository (1.4.0)

[ 39] [Resolved ] [ 1] com.dinstone.demo.user (1.0.0)

[ 40] [Active ] [ 1] com.dinstone.demo.user.db (1.0.0)

[ 41] [Installed ] [ 1] com.dinstone.demo.user.file (1.0.0)

->

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

2009年8月12日 - Dinstone - Dinstone 的技术博客

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

-> ps

START LEVEL 1

ID State Level Name

[ 0] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Resolved ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Active ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Installed ] [ 1] User File Implement Plug-in (1.0.0)

-> start 41

-> ps

START LEVEL 1

ID State Level Name

[ 0] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Resolved ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Active ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Active ] [ 1] User File Implement Plug-in (1.0.0)

->

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

2009年8月12日 - Dinstone - Dinstone 的技术博客

Step6.现在停止User DB Implement Plug-in服务。

-> ps

START LEVEL 1

ID State Level Name

[ 0] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Resolved ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Active ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Active ] [ 1] User File Implement Plug-in (1.0.0)

-> stop 40

-> ps

START LEVEL 1

ID State Level Name

[ 0] [Active ] [ 0] System Bundle (1.6.0)

[ 25] [Active ] [ 1] Apache Felix Shell Service (1.2.0)

[ 26] [Active ] [ 1] Apache Felix Shell TUI (1.2.0)

[ 27] [Active ] [ 1] Apache Felix Bundle Repository (1.4.0)

[ 39] [Resolved ] [ 1] User Model Interface Plug-in (1.0.0)

[ 40] [Resolved ] [ 1] User DB Implement Plug-in (1.0.0)

[ 41] [Active ] [ 1] User File Implement Plug-in (1.0.0)

->

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

2009年8月12日 - Dinstone - Dinstone 的技术博客

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.源码工程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值