OSGi是JAVA动态模块化的标准,使用OSGi构建面向模块、可重用、可热插拔服务是大家都想追求的,但实际采用OSGi作为系统主骨骼框架时却发现理想总是那么丰满,现实总那么骨感,究其原因,总结成以下几点:第一、采用OGGi架构对架构师的要求非常高,针对项目需求设计重用性、扩展性、耦合性良好的功能模块划分不是一件容易的事情,特别是项目需求经常变更的时候,简直就是噩梦;第二,OSGi本身只是一个动态模块化标准,缺少对JAVA EE企业级应用特性的完善支持,比如企业级事务、ORM等特性;第三、OSGi不是一个Web App容器,想要在OSGi架构下提供Web服务需要第三方WEB容器支持,有多种方法并且各有优缺点,这是本文重点讨论的话题。
方式一,采用OSGi托管WEB容器,例如,Jetty就提供了针对OSGi的bundle运行环境,这时如果把WEB APP以OSGi Bundle形式部署,就能够实现WEB服务的发布,又可以利用OSGi的动态模块化特性,这是一种推荐的集成方式;方式二,WEB容器托管OSGi容器,这种方式主要针对传统的JAVA WEB应用,但是又想要提供一些额外的可插拔热部署的服务时,可以采用的一种轻量级集成方式;分析两种方式,显而易见,第一种方式更优雅更OSGi,但缺点是完全侵入式,要求整个系统进行模块化架构,第二种方式最大的问题是,WEB容器跟OSGi的Bundle环境如何良好双向复用,它的好处是侵入性小可比较方便的继续利用现有的JAVA EE框架企业级特性。但就像谈恋爱一样,优雅的美丽的不一定是适合的,需要根据实际场景做分析。接下来,我详细介绍一下我在工作环境中使用的第二种集成方式实现。
主要实现原理时,WEB容器启动加载FelixFrameworkLauncher监听器,FelixFrameworkLauncher监听器完成Felix容器的启动并且使用BundleContextHolder托管最最核心的BundleContext,同时设置到ServletContext上下文,通过BundleContex就可以在WEB容器中通过反射调用OSGi对外提供的Bundle服务。
web应用目录结构:
web.xml配置如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>felix.config.properties</param-name> <param-value>/WEB-INF/conf/config.properties</param-value> </context-param> <listener> <listener-class> cn.longstudio.FelixFrameworkLauncher </listener-class> </listener> </web-app>
FelixFrameworkLauncher类的源码如下:
package cn.longstudio; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Properties; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.felix.framework.FrameworkFactory; import org.apache.felix.framework.util.Util; import org.apache.felix.main.AutoProcessor; import org.osgi.framework.BundleContext; import org.osgi.framework.launch.Framework; import cn.longstudio.BundleContextHolder; /** * <p> * Felix容器启动器 * </p> * * @version 1.0 2013-1-9 * @author hewl * */ public class FelixFrameworkLauncher implements ServletContextListener { private static Framework m_fwk = null; public void contextDestroyed(ServletContextEvent event) { try { m_fwk.stop(); m_fwk.waitForStop(0); } catch (Exception ex) { throw new RuntimeException("Could not stop felix framework: " + ex); } } public void contextInitialized(ServletContextEvent event) { try { String configPropsFileValue = event.getServletContext() .getInitParameter("felix.config.properties"); // Read the properties file. Properties configProps = new Properties(); InputStream is = null; try { // Try to load config.properties. is = event.getServletContext().getResourceAsStream(configPropsFileValue); configProps.load(is); is.close(); } catch (Exception ex) { // Try to close input stream if we have one. try { if (is != null) is.close(); } catch (IOException ex2) { // Nothing we can do. } return; } // Perform variable substitution for system properties. for (Enumeration e = configProps.propertyNames(); e.hasMoreElements(); ) { String name = (String) e.nextElement(); configProps.setProperty(name, Util.substVars(configProps.getProperty(name), name, null, configProps)); } m_fwk = getFrameworkFactory().newFramework(configProps); m_fwk.init(); AutoProcessor.process(configProps, m_fwk.getBundleContext()); m_fwk.start(); //set the BundleContext as a servlet context attribute event.getServletContext().setAttribute(BundleContext.class.getName(), m_fwk.getBundleContext()); BundleContextHolder.setBundleContext(m_fwk.getBundleContext()); } catch (Exception ex) { throw new RuntimeException("Could not create felix framework: " + ex); } } private FrameworkFactory getFrameworkFactory() throws Exception { return new FrameworkFactory(); } }
BundleContextHolder的源码如下:
package cn.longstudio; import org.osgi.framework.BundleContext; /** * <p> * OSGI BundleContext存放器 * </p> * * @version 1.0 2013-1-24 * @author hewl * */ public class BundleContextHolder { private static BundleContext bundleContext; public static BundleContext getBundleContext() { return bundleContext; } public static void setBundleContext(BundleContext bundleContext) { BundleContextHolder.bundleContext = bundleContext; } }
config.properties文件内容如下:
# # Framework config properties. # #Felix默认工作路径为当前工作路径,即系统变量user.dir的值 #当使用Web容器接管OSGI时,最好直接设置为绝对路径 Felix.Framework.Path=E:/felix-framework org.osgi.framework.system.packages.extra=javax.servlet;javax.servlet.http;version=2.5 org.osgi.framework.bootdelegation=org.w3c.*,javax.xml.* org.osgi.framework.bundle.parent=framework felix.cache.rootdir=${Felix.Framework.Path} org.osgi.framework.storage.clean=onFirstInit felix.auto.deploy.action=install,start felix.auto.deploy.dir=${Felix.Framework.Path}/bundle felix.log.level=1 manager.root=/felix/console obr.repository.url=http://felix.apache.org/obr/releases.xml
运行情况截图:
示例源码Maven工程请查看附件(Felix发布包请自行解压并配置好对应目录根路径)
相关推荐
然而,对于轻量级的解决方案,Eclipse Gemini Web项目提供了将Tomcat或Jetty集成到OSGi环境的方法,创建了一个OSGi Web Container。 **2.3 开发环境准备** 为了在Eclipse中开发OSGi Web应用,需要安装相应的插件,...
在Web容器中部署OSGi应用,特别是像Tomcat这样的流行Servlet容器,可以提高应用的灵活性、可维护性和可扩展性。本文将详细介绍如何使用桥接技术(如Apache Felix的WebConsole或Pax Web)在Tomcat中部署OSGi程序。 ...
我们的数据库方案也同样存在这样的选择,所谓轻量级的方案,就是船小好掉头,任何时候都可以做一些精细修改,比如更新一个表里面的一个数据。重量级的方案是: 休想!你只能更新整个表。 我们这里的轻量级的方案是指...
### 基于OSGi的轻量级动态化系统研究 #### 1. OSGi服务平台概述 OSGi(Open Service Gateway Initiative)是一种模块化框架,它为Java平台上的应用程序提供了一个灵活、可扩展的环境。OSGi的核心价值在于它的模块...
总结来说,OSGi在Web容器中的部署提供了一种灵活的方式,使得我们可以独立地管理和更新应用的各个部分,同时利用Web容器的强大功能。通过合理配置和使用,可以实现更高效、更稳定的应用部署和管理。
Spring 是一个轻量级的J2EE开发框架,特点是面向接口编程和非侵入式的依赖注入。将 OSGi 和 Spring 结合能充分发挥二者各自的特长,更好地满足企业级应用开发的需求。 在基于 OSGi 和 Spring 的 Web 应用开发中,...
Karaf是Apache软件基金会的一个项目,是一个基于OSGi的轻量级运行时容器,用于部署和管理服务。在Karaf容器中集成Servlet并发布REST接口是一项常见的任务,下面我们将详细讨论这个过程。 首先,我们需要理解OSGi与...
- **Spring框架**:作为Java领域中最受欢迎的轻量级开发框架之一,Spring提供了众多功能来简化企业级应用的开发,包括依赖注入、面向切面编程(AOP)、事务管理等。它强调的是“面向接口编程”而非具体的实现细节,...
标题中的“tomcat嵌入OSGI容器”是指在Apache Tomcat服务器中集成OSGI(Open Service Gateway Initiative)框架,使得Tomcat能够支持模块化的应用程序部署和管理。OSGI是一种Java平台上的服务导向架构,它允许动态地...
例如,Jetty OSGI或者Tomcat OSGI插件允许在OSGI环境中托管Web应用。 3. **Servlet API**: 为了让OSGI支持Web应用,它需要Servlet API的实现,这是Web服务器处理HTTP请求的基础。这些jar文件通常包含`javax.servlet...
Spring框架,自问世以来,便因其轻量级特性、面向接口编程以及依赖注入机制而受到开发者们的青睐。Spring的核心优势在于它能够简化企业级应用的开发过程,提供了一种更为灵活且低耦合的组件模型,使得代码更容易测试...
Web示例工程是使用OSGi技术构建的一个具体应用,通常包括了如何在OSGi环境中部署和运行Web应用程序的实例。 在OSGi框架中,Equinox是Eclipse基金会提供的一个实现,它是OSGi规范的主要实现之一,广泛应用于服务器端...
标题中的“tomcat-osgi.rar_OsgiContentFactory_osgi_osgi tomcat 集成_osgi tom”表明这是一个关于Tomcat服务器与OSGi框架集成的资源包,其中可能包含了如何在Tomcat中使用OsgiContentFactory来管理OSGi服务的内容...
- 结构原理:Web容器注册Struts OSGi监听器,监听器控制Apache Felix Host,Felix Host启动和管理Felix Framework,而Struts OSGi Plugin监听bundle的变化,当检测到Struts bundle时,加载相应的Struts配置。...
此外,通过使用Facet配置,开发者可以对OSGi项目进行细粒度控制,包括对web.xml、persistence.xml和blueprint.xml的集成编辑。 JPA 2.0的引入带来了许多增强,包括领域模型的改进、元模型和API的标准化,以及实体...
3. **Tomcat与OSGi的集成**:集成OSGi到Tomcat主要是为了利用其模块化特性,使得Web应用的部署和更新更加灵活。常见的集成框架有Apache Felix、Equinox等,它们为Tomcat提供了一个可以加载和管理OSGi bundle的环境。...
Mybatis是一个轻量级的持久层框架,它提供了一种灵活的SQL映射机制,减少了JDBC代码的编写。在OSGI中整合Mybatis,我们需要考虑如何管理数据库连接和事务。Mybatis的配置文件可以放在OSGI的bundle中,通过OSGI服务...