ufida design-chijianqiang-qcon

64
企业级软件的组件化和动态化开发实践 池建强--@sagacity 用友集团-瑞友科技-IT应用研究院 www.ufida.com www.rayootech.com 1142日星期六

Upload: yiwei-ma

Post on 15-May-2015

706 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Ufida design-chijianqiang-qcon

企业级软件的组件化和动态化开发实践

池建强--@sagacity

用友集团-瑞友科技-IT应用研究院www.ufida.comwww.rayootech.com

11年4月2日星期六

Page 2: Ufida design-chijianqiang-qcon

大纲

‣ 软件开发之殇‣ 组件化与动态化‣ 基于WTP Facet、XDoclet、ANT的组件构建‣ OSGi——兄弟,全靠你了‣ 展望:所有的Java应用都是Bundle

11年4月2日星期六

Page 3: Ufida design-chijianqiang-qcon

现代人类文明运行于软件之上,而软件的构建过程却隐于黑暗里,多少青春的日子耗费在了软件的缺陷上

11年4月2日星期六

Page 4: Ufida design-chijianqiang-qcon

从软件系统诞生之初,程序员们就开始梦想有一天能够像建造桥梁和房屋那样“透明”的构造软件,实现“即插即用”的软件系统

11年4月2日星期六

Page 5: Ufida design-chijianqiang-qcon

但是到目前为止,软件的开发依然让我们倍感挫折,失败的软件项目有增无减,我们还在路上

11年4月2日星期六

Page 6: Ufida design-chijianqiang-qcon

但是到目前为止,软件的开发依然让我们倍感挫折,失败的软件项目有增无减,我们还在路上

11年4月2日星期六

Page 7: Ufida design-chijianqiang-qcon

组件化的技术让我们更加接近真理之门

11年4月2日星期六

Page 8: Ufida design-chijianqiang-qcon

组件化的技术让我们更加接近真理之门

OSGi?

11年4月2日星期六

Page 9: Ufida design-chijianqiang-qcon

组件化与动态化

‣ 组件化‣ 完整的业务逻辑单元‣ 解决某一方面的问题‣ 每个组件可以独立开发‣ 实现组织级复用‣ 按需分配‣ 动态的安装启动停止卸载

‣ 动态化‣ 动态的改变组件的状态‣ 动态的改变数据和数据结构‣ 动态的修改业务流程‣ 动态的调整业务规则‣ 动态的分配资源‣ 动态的计算

11年4月2日星期六

Page 10: Ufida design-chijianqiang-qcon

组件化与动态化

‣ 组件化‣ 完整的业务逻辑单元‣ 解决某一方面的问题‣ 每个组件可以独立开发‣ 实现组织级复用‣ 按需分配‣ 动态的安装启动停止卸载

‣ 动态化‣ 动态的改变组件的状态‣ 动态的改变数据和数据结构‣ 动态的修改业务流程‣ 动态的调整业务规则‣ 动态的分配资源‣ 动态的计算

Component Building

MetadataWorkflowRuleEngine

11年4月2日星期六

Page 11: Ufida design-chijianqiang-qcon

企业级软件开发遇到的挑战

‣ 组织级复用‣ 不是复制粘贴,不是简单的代码、接口或算法的复用

‣ 没人愿意编写重复代码

‣ 复用是永远的痛——200个表的故事

‣ 组件的管理

‣ 组件的独立开发

‣ 组件的依赖关系

‣ 自动构建——机器的活得让机器干

11年4月2日星期六

Page 12: Ufida design-chijianqiang-qcon

我们遇到的...

规则引擎

Main FrameWork

组织权限

业务日志

消息

任务调度

全文检索

报表AJAX

Flex

工作流引擎

数据字典

接口服务管理

ERP业务平台

银企直联平台

电子商务平台

11年4月2日星期六

Page 13: Ufida design-chijianqiang-qcon

我们遇到的...

规则引擎

Main FrameWork

组织权限

业务日志

消息

任务调度

全文检索

报表AJAX

Flex

工作流引擎

数据字典

接口服务管理

ERP业务平台

银企直联平台

电子商务平台

11年4月2日星期六

Page 14: Ufida design-chijianqiang-qcon

我们遇到的...

规则引擎

Main FrameWork

组织权限

业务日志

消息

任务调度

全文检索

报表AJAX

Flex

工作流引擎

数据字典

接口服务管理

ERP业务平台

银企直联平台

电子商务平台Here you are!

11年4月2日星期六

Page 15: Ufida design-chijianqiang-qcon

我们希望的...

组织权限

工作流引擎

数据字典

接口服务管理

ERP业务平台银企直联平台

电子商务平台

规则引擎

业务日志

消息

任务调度

全文检索

报表

AJAXFlex

短信预警

消息 监控

Main FrameWork

GAP-API

11年4月2日星期六

Page 16: Ufida design-chijianqiang-qcon

开发实践

‣ Eclipse WTP Facets

‣ XDoclet

‣ Ant

‣ 为什么当时没有采用OSGi‣ 资源文件的处理

‣ Servlet容器的支持

‣ 持久化、事务

11年4月2日星期六

Page 17: Ufida design-chijianqiang-qcon

Eclipse WTP Facets‣ 提供了优秀的扩展机制‣ 对WTP(Web Tools Platform)平台进行扩展‣ 创建WTP项目时增加自定义的组件‣ 提供组件的依赖关系和多版本管理‣ Facets允许开发人员以组件集成的方式来创建项目,像搭积木一样把各种组件进行组合并完成最终构建,是面向组件开发的一种实现机制

‣ Facets不提供运行时组件生命周期的管理

11年4月2日星期六

Page 18: Ufida design-chijianqiang-qcon

核心的WTP Faceted包括以下内容:

id versions requires conflicts

jst.java 1.3, 1.4, 1.5, 1.6 jst.ear

jst.web 2.2, 2.3, 2.4 jst.java jst.ear, jst.ejb

jst.ear 1.2, 1.3, 1.4, 5.0, 6.0 jst.java

jst.ejb 1.1, 2.0, 2.1, 3.0, 3.1 jst.java jst.ear, jst.java

11年4月2日星期六

Page 19: Ufida design-chijianqiang-qcon

核心的WTP Faceted包括以下内容:

id versions requires conflicts

jst.java 1.3, 1.4, 1.5, 1.6 jst.ear

jst.web 2.2, 2.3, 2.4 jst.java jst.ear, jst.ejb

jst.ear 1.2, 1.3, 1.4, 5.0, 6.0 jst.java

jst.ejb 1.1, 2.0, 2.1, 3.0, 3.1 jst.java jst.ear, jst.java

11年4月2日星期六

Page 20: Ufida design-chijianqiang-qcon

创建一个标准的Dynamic Web Project

11年4月2日星期六

Page 21: Ufida design-chijianqiang-qcon

创建一个标准的Dynamic Web Project

Facets

11年4月2日星期六

Page 22: Ufida design-chijianqiang-qcon

XDoclet & Ant‣ XDoclet:优秀的文本处理和构建工具‣ 资源文件处理、Merge Point

‣ Ant: 历史悠久的构建脚本工具‣ 独立组件构建‣ 整体构建‣ Facets Ant XDoclet

11年4月2日星期六

Page 23: Ufida design-chijianqiang-qcon

组件化开发实践

‣ 各组件独立开发,独立构建(build.xml)‣ 公共资源文件处理-MergePoint(i18n,oid,spring,include)‣ 整体构建(TotalBuild)‣ 基于Facet机制装配组件

11年4月2日星期六

Page 24: Ufida design-chijianqiang-qcon

实际效果

11年4月2日星期六

Page 25: Ufida design-chijianqiang-qcon

实际效果

TotalBuild

11年4月2日星期六

Page 26: Ufida design-chijianqiang-qcon

实际效果

TotalBuild

11年4月2日星期六

Page 27: Ufida design-chijianqiang-qcon

实际效果

TotalBuildFacets

11年4月2日星期六

Page 28: Ufida design-chijianqiang-qcon

开始实践之旅

‣ 各组件独立研发,依赖框架,依赖接口‣ 编写自己的build.xml,实现clean compile jar distribution

‣ 在组件项目的根目录下执行ant

‣ 构建出统一目录结构的Distribution

db merge resource src webModule

11年4月2日星期六

Page 29: Ufida design-chijianqiang-qcon

公共资源文件处理(Merge)‣ 建立公共模板文件,文件后缀设置为xdt‣ applicationContext.xdt------------spring‣ global.xdt---------------------------include global.jsp‣ web.xdt-----------------------------web.xml‣ ......

‣ 设置Merge Point

<XDtMerge:merge file="workflow-hbm.data"></XDtMerge:merge>

11年4月2日星期六

Page 30: Ufida design-chijianqiang-qcon

Merge文件的内容

db merge resource src webModule

<value>gap/wf/persistent/db/bo/GapwfProcessinstance.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfActivityinstance.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfActivityinstancepre.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfRevelantdata.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfWorkitem.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfWorkitemdata.hbm.xml</value> <value>gap/wf/persistent/db/bo/GapwfDynprocessrelation.hbm.xml</value>

11年4月2日星期六

Page 31: Ufida design-chijianqiang-qcon

XDoclet构建‣ 设置XDoclet的classpath

‣ 设置Ant的taskdef

‣ 定义target

<path id="xdoclet.classpath"> <fileset dir="${lib.dir}"> <include name="*.jar"/> </fileset> <pathelement location="classes"/> </path>

<taskdef name="xdoclet" classname="xdoclet.DocletTask" classpathref="xdoclet.classpath" />

<target name="gen-applicationContext.xml"> <xdoclet destdir="${webmodule.dir}/WEB-INF/conf/applicationContext" force='true' mergedir="${merge.dir}"> <fileset dir="${source.dir}" includes="**/*.java" /> <template templateFile="template/applicationContext.xdt" destinationfile="applicationContext.xml" /> </xdoclet> </target>

11年4月2日星期六

Page 32: Ufida design-chijianqiang-qcon

TotalBuild‣ 构建Facets项目所需要的组件内容

<!--调用各个组件的build.xml--> <target name="build"> <ant dir="${gap-api}" antfile="build.xml" target="all" /> <ant dir="${venus-frame}" antfile="build.xml" target="all" /> <ant dir="${venus-page}" antfile="build.xml" target="all" /> <ant dir="${venus-log}" antfile="build.xml" target="all" /> ...... </target> <!--重命名--> <target name="plugin"> <available file="Templates" type="dir" property="Templates.present" /> <antcall target="clean" /> <move todir="Templates/0. 主程序框架"> <fileset dir="${gap-api}/dist" /> <fileset dir="${venus-frame}/dist" /> </move> ...... </target>

11年4月2日星期六

Page 33: Ufida design-chijianqiang-qcon

构建我们自己的Facet‣ 创建基于org.eclipse.ui.newWizards的扩展点‣ 设置category和wizard,实现独立的项目向导

11年4月2日星期六

Page 34: Ufida design-chijianqiang-qcon

核心扩展点‣ org.eclipse.wst.common.project.facet.core.facets‣ <category />——Facet的类别

‣ <project-facet />——Facet的属性描述

‣ <project-facet-version />——Facet的版本处理

‣ <template />——设置必选的Facet

‣ <preset />——预置Facet集合

辅助扩展点——增加图标和向导页面‣ org.eclipse.wst.common.project.facet.ui.images

‣ org.eclipse.wst.common.project.facet.ui.wizard

11年4月2日星期六

Page 35: Ufida design-chijianqiang-qcon

Facet的核心配置

<!--Facet的基础信息配置--> <project-facet id="gap.mainframe">

<label>0. 主程序框架</label> <description>GAP平台的基础框架</description> <category>gap.category</category> </project-facet>

<!--设置Facet的某个版本的相关信息(安装代理类,约束等)--> <project-facet-version facet="gap.mainframe" version="3.7"> <action id="gap.mainframe.install" type="INSTALL"> <delegate class="venus.tools.ide.facet.GAPFacetInstallDelegate"/> </action> <constraint> <requires facet="jst.web" version="[2.4"/> </constraint> </project-facet-version>

11年4月2日星期六

Page 36: Ufida design-chijianqiang-qcon

Facet的两个代理类‣ 实现接口:org.eclipse.wst.common.project.facet.core.IDelegate

‣ GAPFacetInstallDelegate:负责负责所有实体Facet的安装‣ BuildFacetsDelegate:‣ 虚拟Facet,在所有实体Facet安装完成后调用

‣ 负责Facet的装配策略

‣ 创建配置文件、驱动XDoclet进行文件合并、设置classpath

‣ 创建project的nature(.tomcatplugin)

‣ 删除不需要的文件

11年4月2日星期六

Page 37: Ufida design-chijianqiang-qcon

解决了哪些问题

‣ 组件的独立开发‣ 组件的组合与依赖关系‣ 组件版本管理‣ 按需分配‣ 最终实现了组织级别的复用

11年4月2日星期六

Page 38: Ufida design-chijianqiang-qcon

遗留问题

‣ 能装不能拆,无法实现物理隔离‣ 独立jar包的版本冲突‣ 运行时动态的生命周期管理(Install、Update、Remove)‣ Time For:

11年4月2日星期六

Page 39: Ufida design-chijianqiang-qcon

遗留问题

‣ 能装不能拆,无法实现物理隔离‣ 独立jar包的版本冲突‣ 运行时动态的生命周期管理(Install、Update、Remove)‣ Time For:

Time For:

O Gi20woensdag 22 september 2010

11年4月2日星期六

Page 40: Ufida design-chijianqiang-qcon

OSGi‣ 天将降大任‣ 2005,R4.0发布——最好的年代,也是最坏的年代‣ 2010年3月,OSGi企业级规范4.2正式发布‣ 世界是你的,也是我的,归根结底应该是由Bundle构建的‣ 完美的解决方案

11年4月2日星期六

Page 41: Ufida design-chijianqiang-qcon

INSTALLED

RESOLVED

STARTING

ACTIVE

STOPPINGUNINSTALLED

installupdaterefresh

updaterefresh

resolve start

stopuninstalluninstall

stop

11年4月2日星期六

Page 42: Ufida design-chijianqiang-qcon

OSGi 企业级特性‣ 声明式服务(Declarative Services)‣ 框架加载(Framework Launching)‣ Blueprint服务(Blueprint Service)‣ Web应用(Web Application Bundle)‣ 远程服务 日志服务 JPA JTA JDBC......

11年4月2日星期六

Page 43: Ufida design-chijianqiang-qcon

OSGi 企业级特性‣ 声明式服务(Declarative Services)‣ 框架加载(Framework Launching)‣ Blueprint服务(Blueprint Service)‣ Web应用(Web Application Bundle)‣ 远程服务 日志服务 JPA JTA JDBC......

11年4月2日星期六

Page 44: Ufida design-chijianqiang-qcon

声明式服务

‣ Service Component Model

‣ 通过声明的方式实现OSGi服务的发布、查找和绑定‣ 通过xml的方式定义Component和Service

‣ 引用服务和提供服务都以接口的方式定义‣ 允许以纯Java POJO的方式开发组件,不依赖OSGi框架‣ 更容易测试和模拟

11年4月2日星期六

Page 45: Ufida design-chijianqiang-qcon

声明式服务——提供服务和消费服务‣ 在Bundle的Manifest中定义一个或多个组件文件

‣ 在OSGI-INF/目录下编写组件文件

Bundle-ManifestVersion: 2...Service-Component: OSGI-INF/component.xml [, ...]*

<?xml version="1.0" encoding="UTF-8"?> <scr:component name="bookstore-order" xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"> <!--该组件的实现类-->

<implementation class="com.osgi.ds.OrderService"/> <!--提供的服务-->

<service><provide interface="com.osgi.ds.IOrder"/></service> <!--消费的服务-->

<reference interface="com.osgi.ds.ICart" bind="setCart" unbind="unsetCart" policy="dynamic" cardinality="1..1"/> </scr:component>

11年4月2日星期六

Page 46: Ufida design-chijianqiang-qcon

声明式服务——组件的生命周期‣ Enabled——组件的启动‣ Satisfied——满足组件的配置信息‣ Immediate Component——立即激活组件‣ Delayed Component——延迟加载组件‣ Factory Component——工厂组件

11年4月2日星期六

Page 47: Ufida design-chijianqiang-qcon

声明式服务——组件的生命周期‣ Enabled——组件的启动‣ Satisfied——满足组件的配置信息‣ Immediate Component——立即激活组件‣ Delayed Component——延迟加载组件‣ Factory Component——工厂组件

!"#$%"&'($)&%*+,-./'0%1&+&,2&%34%5&'2$/6%378 *,9&%:;<

=&)+,',-$(&%"&'($)&2%">&)$.$),-$/6%%5&'2$/6%:7: ?/0>/6&6-%@$.&%?A)+&

!"#$%&"'%()%*+$%,-.*$/%#("/-*-(".%&0$%"(%,("1$0%*02$3%*+$%#(45("$"*%#(")-120&*-("%6$#(4$.%!"#$%&#'(&)*7%8"%&#*-9&*$/%#(45("$"*%#(")-120&*-("%*+&*%6$#(4$.%2".&*-.)-$/%42.*%6$%/$&#*-9&*$/7%

!!"#$#% &''()*+,(-./'0/1(1,8%#(45("$"*%-.%&"%-44$/-&*$%#(45("$"*%:+$"%-*%42.*%6$%&#*-9&*$/%&.%.(("%&.%-*.%/$5$"/$"#-$.%&0$%

.&*-.)-$/7%!"#$%*+$%#(45("$"*%#(")-120&*-("%6$#(4$.%2".&*-.)-$/3%*+$%#(45("$"*%#(")-120&*-("%

42.*%6$%/$&#*-9&*$/7%;)%&"%-44$/-&*$%#(45("$"*%#(")-120&*-("%-.%.&*-.)-$/%&"/%.5$#-)-$.%&%.$09-#$3%

<=>%42.*%0$1-.*$0%*+$%#(45("$"*%#(")-120&*-("%&.%&%.$09-#$%-"%*+$%.$09-#$%0$1-.*0'%&"/%*+$"%&#*-9&*$%

*+$%#(45("$"*%#(")-120&*-("7%?+$%.$09-#$%50(5$0*-$.%)(0%*+-.%0$1-.*0&*-("%#(".-.*%()%*+$%#(45("$"*%

50(5$0*-$.%&.%/$)-"$/%-"%+),-&.)/0,12),%&)#%("%5&1$ @AB7

?+$%.*&*$%/-&10&4%-.%.+(:"%-"%C-120$%@@D7D7%

3&4!,)/55676 899)*&$%)/:1921")"%/:1"(&4!,$%&1"

!!"#$#2 3(4+5()-./'0/1(1,-8%E$'%&**0-62*$%()%&%/$,&'$/%#(45("$"*%-.%*+$%/$,&'-"1%()%#,&..%,(&/-"1%&"/%(6F$#*%#0$&*-("7%?+$0$)(0$3%

*+$%&#*-9&*-("%()%&%/$,&'$/%#(45("$"*%#(")-120&*-("%/($.%"(*%(##20%2"*-,%*+$0$%-.%&"%&#*2&,%0$G2$.*%

)(0%&%.$09-#$%(6F$#*7%8%#(45("$"*%-.%&%/$,&'$/%#(45("$"*%:+$"%-*%.5$#-)-$.%&%.$09-#$%62*%-*%-.%"(*%&%)&#H

*(0'%#(45("$"*%&"/%/($.%"(*%+&9$%*+$%!""#$!%&# %&**0-62*$%()%*+$%'(")(*#*& %$,$4$"*%.$*%*(%&+,# 7

<=>%42.*%0$1-.*$0%&%.$09-#$%&)*$0%*+$%#(45("$"*%#(")-120&*-("%6$#(4$.%.&*-.)-$/7%?+$%0$1-.*0&*-("%()%

*+-.%.$09-#$%42.*%,((E%*(%(6.$09$0.%()%*+$%.$09-#$%0$1-.*0'%&.%-)%*+$%#(45("$"*I.%62"/,$%&#*2&,,'%0$1-.H

*$0$/%*+-.%.$09-#$7%?+-.%.*0&*$1'%4&E$.%-*%5(..-6,$%*(%0$1-.*$0%.$09-#$.%:-*+(2*%#0$&*-"1%&%#,&..%,(&/$0%

)(0%*+$%62"/,$%&"/%,(&/-"1%#,&..$.3%*+$0$6'%&,,(:-"1%0$/2#*-("%-"%-"-*-&,-J&*-("%*-4$%&"/%&%/$,&'%-"%

4$4(0'%)((*50-"*7

K+$"%<=>%0$1-.*$0.%*+$%.$09-#$%("%6$+&,)%()%&%#(45("$"*%#(")-120&*-("3%-*%42.*%&9(-/%#&2.-"1%&%#,&..%

,(&/%*(%(##20%)0(4%*+$%#(45("$"*L.%62"/,$7%<=>%#&"%$".20$%*+-.%6'%0$1-.*$0-"1%&%-#+.!'#/%'&(+0 %(6F$#*%:-*+%*+$%C0&4$:(0E%)(0%*+&*%.$09-#$7%M'%0$1-.*$0-"1%&%-#+.!'#/%'&(+0 %(6F$#*3%*+$%&#*2&,%.$09-#$%(6F$#*%-.%"(*%"$$/$/%2"*-,%*+$%-#+.!'#/%'&(+0 %-.%#&,,$/%*(%50(9-/$%*+$%.$09-#$%(6F$#*7%?+$%.$09-#$%50(5H$0*-$.%)(0%*+-.%0$1-.*0&*-("%#(".-.*%()%*+$%#(45("$"*%50(5$0*-$.%&.%/$)-"$/%-"%+),-&.)/0,12),%&)#%("%5&1$@AB7

?+$%&#*-9&*-("%()%&%#(45("$"*%#(")-120&*-("%42.*%6$%/$,&'$/%2"*-,%-*.%.$09-#$%-.%0$G2$.*$/7%K+$"%*+$%

.$09-#$%-.%0$G2$.*$/3%-)%*+$%.$09-#$%+&.%*+$%1#+.!'#2%'&(+0 %&**0-62*$%.$*%*(%&+,# 3%<=>%42.*%#0$&*$%&"/%

&#*-9&*$%&%2"-G2$%#(45("$"*%#(")-120&*-("%)(0%$&#+%62"/,$%0$G2$.*-"1%*+$%.$09-#$7%!*+$0:-.$3%<=>%

42.*%&#*-9&*$%&%.-"1,$%#(45("$"*%#(")-120&*-("%:+-#+%-.%2.$/%6'%&,,%62"/,$.%0$G2$.*-"1%*+$%.$09-#$7%

8%#(45("$"*%-".*&"#$%#&"%/$*$04-"$%*+$%62"/,$%-*%:&.%&#*-9&*$/%)(0%6'%#&,,-"1%*+$%3#&41!*35,*$6#78 %4$*+(/%("%*+$%=(45("$"*%=("*$N*7%

?+$%&#*-9&*-("%()%/$,&'$/%#(45("$"*.%-.%/$5-#*$/%-"%&%.*&*$%/-&10&4%-"%C-120$%@@D7O7%P(*-#$%*+&*%42,H

*-5,$%#(45("$"*%#(")-120&*-(".%#&"%6$%#0$&*$/%)0(4%*+$%9:;<-=:9:> %.*&*$%-)%&%/$,&'$/%#(45("$"*%

.5$#-)-$.%1#+.!'#2%'&(+0 %.$*%*(%&+,# 7%

6789:&8;&<3

B&)/0&22,-$2.$&C

+=,*>+,(

)(+=,*>+,(

9.:&?<

B&)/0&2D62,-$2.$&C

$.%CA6,0$)E'&B$6C$69!"#$"%&%'()*+&(!,-.&( /&-.010'*2&(3&12*-&4(3$&-*+*-0'*"%(5&14*"%(676

809&(6:; <3=*(3&12*-&(8.0'+"1#(>&.&04&(?@(5&14*"%(?7A

!"#$%&#'&()*+&#(&,*'$&(&-#./#0#+12314&4$#+14"*,5(0$*14#.&+12&'#545'&-#.&+05'&#$%&(&#0(&#41#21(&#

.54-6&'#5'*4,#*$7#$%&4#89:#'%156-#-&0+$*)0$&#$%0$#+12314&4$#+14"*,5(0$*14;#<%*'#0661='#89:#*236&>

2&4$0$*14'#$1#&0,&(6/#(&+60*2#0+$*)0$&-#+12314&4$#+14"*,5(0$*14';

!"#$%&'(()*+ ,&-./&0'123425&56'1257"#$%.6"25

!!"#$#$ %&'()*+,-)./)010(89:#25'$#(&,*'$&(#0#912314&4$#?0+$1(/#'&()*+&#0'#'114#0'#$%&#823425&56'7.862%/#.&+12&'#'0$*'"*&-;#

<%&#+12314&4$#"0+$1(/#*'#'0$*'"*&-#=%&4#$%&#"1661=*4,#+14-*$*14'#0(&#066#'0$*'"*&-@

A <%&#+12314&4$#*'#&40.6&-;

A B'*4,#$%&#+12314&4$#3(13&($*&'#'3&+*"*&-#./#$%&#+12314&4$#-&'+(*3$*147#066#$%&#+12314&4$C'#(&">

&(&4+&'#0(&#'0$*'"*&-;#D#(&"&(&4+&#*'#'0$*'"*&-#=%&4#$%&#(&"&(&4+&#'3&+*"*&'#13$*1406#+0(-*406*$/#1(#

$%&(&#*'#0$#6&0'$#14&#$0(,&$#'&()*+&#"1(#$%&#(&"&(&4+&

<%&#+12314&4$#"0+$1(/7#%1=&)&(7#-1&'#41$#5'&#04/#1"#$%&#$0(,&$#'&()*+&'#04-#-1&'#41$#.*4-#$1#$%&2;

E4+&#04/#1"#$%&#6*'$&-#+14-*$*14'#0(&#41#614,&(#$(5&7#$%&#+12314&4$#"0+$1(/#.&+12&'#54'0$*'"*&-#04-#

$%&#912314&4$#?0+$1(/#'&()*+&#25'$#.&#54(&,*'$&(&-;#D4/#+12314&4$#+14"*,5(0$*14'#0+$*)0$&-#)*0#

$%&#+12314&4$#"0+$1(/#0(&#540""&+$&-#./#$%&#54(&,*'$(0$*14#1"#$%&#912314&4$#?0+$1(/#'&()*+&7#.5$#

20/#$%&2'&6)&'#.&+12&#54'0$*'"*&-#"1(#$%&#'02&#(&0'14;

<%&#912314&4$#?0+$1(/#'&()*+&#25'$#.&#(&,*'$&(&-#54-&(#$%&#402&#

!"#$!%#& $%'"( &)'$)!*+!,',-$.!*+!,',-/0)-!"1 #=*$%#$%&#"1661=*4,#'&()*+&#3(13&($*&'@

A )!*+!,',-$,0*' #F#<%&#402&#1"#$%&#+12314&4$;

A )!*+!,',-$20)-!"1 #F#<%&#)065&#1"#$%&#20)-!"1 #0$$(*.5$&;

<%&#'&()*+&#3(13&($*&'#1"#$%&#912314&4$#?0+$1(/#'&()*+&#25'$#41$#*4+65-&#$%&#+12314&4$#3(13&($*&';

G&=#+12314&4$#+14"*,5(0$*14'#0(&#+(&0$&-#04-#0+$*)0$&-#=%&4#$%&#,'34,%-0,)' #2&$%1-#1"#$%&#

912314&4$#?0+$1(/#'&()*+&#*'#+066&-;#!"#$%&#+12314&4$#-&'+(*3$*14#'3&+*"*&'#0#'&()*+&7#$%&#+12314&4$#

+14"*,5(0$*14#*'#(&,*'$&(&-#0'#0#'&()*+&#54-&(#$%&#3(1)*-&-#*4$&("0+&';#<%&#'&()*+&#3(13&($*&'#"1(#$%*'#

(&,*'$(0$*14#+14'*'$#1"#$%&#+12314&4$#3(13&($*&'#0'#-&"*4&-#*4#9&%:"8&';%24&%6"&<#14#30,& HIJ;#<%&#'&(>)*+&#(&,*'$(0$*14#25'$#$0K&#360+&#.&"1(&#$%&#+12314&4$#+14"*,5(0$*14#*'#0+$*)0$&-;#8&()*+&#54(&,*'$(0>

$*14#25'$#$0K&#360+&#.&"1(&#$%&#+12314&4$#+14"*,5(0$*14#*'#-&0+$*)0$&-;

2345674%789

B&-"#&440'*4+*&C

B&-"#&4

&'(:;&(1

<1&'(:;&(1

5-67=8

D%40'*4+*&C

>8?7468>89 B&-"#&4

9&'4&12*-&

D%9&'4&12*-& D%40'*4+*&C6

*+(C,%0#*-E1&B*%C*%9

4&12*-&+0-'"1,E(F77%"'G&1H*4&E(6

11年4月2日星期六

Page 48: Ufida design-chijianqiang-qcon

框架加载

‣ R4.2提供了一套标准的API用来启动OSGi容器‣ 各OSGi框架都需要实现——org.osgi.framework.launch.FrameworkFactory

‣ 允许在容器外启停OSGi框架,例如在web容器中通过listener启动OSGi

‣ 示例代码如下:

Class<FrameworkFactory> factoryClass = ServiceLoader.load(FrameworkFactory.class);FrameworkFactory factory = factoryClass.newInstance();Map<Object, Object> conf;......//初始化配置信息Framework framework=factory.newFramework(conf);framework.init();BundleContext bundleContext = framework.getBundleContext();......//安装bundleframework.start();

11年4月2日星期六

Page 49: Ufida design-chijianqiang-qcon

BluePrint服务‣ BluePrint的基础——Spring Dynamic Modules-->Eclipse Gemini

‣ 为OSGi定义了依赖注入(dependency injection)框架‣ 处理OSGi服务的动态性‣ 与POJO协同工作‣ OSGI-INF/blueprint/

<?xml version="1.0" encoding="UTF-8"?><blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> ...</blueprint>

11年4月2日星期六

Page 50: Ufida design-chijianqiang-qcon

BluePrint服务——Bean管理器‣ 创建具有给定参数和属性的 Java 对象的实例‣ 管理对象的生命周期‣ argument, property, scope

‣ 构建方式:className, factoryMethod, factoryComponent

<bean id="order" class="com.osgi.bs.OrderService" init-method="init" destroy-method="destroy"><argument value="1"/><argument value="2"/><property name="Description" value="This is the order"/>

</bean>

!"#$%&#$#'"(% !)*"+(,$-%./$-#,$"(%0+"1,2,1#-,/$%3"(4,/$%567

8#'"%95: ;0<,%0"(=,1"%8)#-2/(>%?")"#4"%:@%3"(4,/$%:69

!"#$%&'(#%$%)*#$+,$-.'/&00)$1,#2$3.'$0+,%#-#',4$,#'5+6#$.78#6%,4$&-2$.%"#'$*0&6#,$9"#'#$&$(#-#'&0$&**0+:

6&%+.-$6./*.-#-%$+-,%&-6#$+,$'#;1+'#2<

!"!#$ %&'()*'('+&,=$7#&-$/&-&(#'$*'.5+2#,$&-$&'7+%'&')$>&5&$.78#6%<$?%$6.-,%'16%,$%"+,$.78#6%$3'./$&$(+5#-$60&,,$.'$3&6:

%.')$&-2$%"#-$6.-3+(1'#,$%"#$.78#6%$7)$+-8#6%+-($+%,$!"#!$"%&$'$9+%"$.%"#'$6./*.-#-%$+-,%&-6#,$.'$

/.'#$(#-#'&0$.78#6%$5&01#,<$

!"#$*'.5+2#2$6./*.-#-%$+-,%&-6#$6&-$7#$&$!"#$%&'(# $.'$&$-#9$.78#6%$6&-$7#$'#%1'-#2$.-$#5#')$+-5.:

6&%+.-$@)*('('+)&A4$%"+,$7#"&5+.'$+,$2#3+-#2$9+%"$%"#$!,()& $&%%'+71%#4$,##$()#!$$.-$*&(# BCD<

!"#$*'.5+2#2$.78#6%$6&-$.*%+.-&00)$7#$-.%+3+#2$9"#-$&00$.3$+%,$*'.*#'%+#,$"&5#$7##-$+-8#6%#24$&-2$

9"#-$%"#$*'.5+2+-($7#&-$/&-&(#'$9+00$7#$2#&6%+5&%#24$,##$*&+$,-.)/$,-0//10)2'$.-$*&(# BCE<

!"!#$#! %&'()-./0.(&(1)2*3!"#$,%'16%1'#$.3$&$-&.# $#0#/#-%$+,F

!"#$ %%&'(')#*+,-"$./'0')1*21"*.3/'45

3&45"$,67689 :$0;,(%"5)%5"$

!"!#$#" 45&'(6!"#$G#%&2&%&$3.'$&$7#&-$/&-&(#'$+,$'#*'#,#-%#2$+-$%"#$$/&.#0&'.1.'. $+-%#'3&6#4$9"+6"$#H%#-2,$

2(3)(#&#'0&'.1.'. <$!&70# CBC<C$.-$*&(# BCI$*'.5+2#,$&-$.5#'5+#9$.3$%"#$'#0&%#2$JGK$2#3+-+%+.-,$

&-2$%"#$/&.#0&'.1.'. $+-%#'3&6#<$!"#$%&70#$.-0)$*'.5+2#,$&$,1//&')4$%"#$,./#%+/#,$,17%0#$+-%#'&6:

%+.-,$7#%9##-$%"#$2+33#'#-%$3#&%1'#,$&'#$2+,61,,#2$+-$0&%#'$,#6%+.-,<

5&'(

',+7/&(1 0,.0&,18

9

<01/$,67686 :$0;,=0;04$",3$0%5"$'

:11,;571&).,)<=&/&(1 >8(1'? %&'()*&1'@'1' A&BC,;01;.(

"1 45 "167 68'* "#$

!"#$+2$.3$&$%.*$0#5#0$/&-&(#'4$/1,%$

7#$1-+;1#$+-$%"#$L01#*'+-%$M.-:

%&+-#'<$=00$+-0+-#2$/&-&(#',$/1,%$

'#%1'-$#9% % $3.'$%"#+'$+2<.,' ":.' "(# 6 6 %.;+

< 6&.$&*.,' ":.' "(#7 6 "#'

N#3+-#,$+3$%"+,$7#&-$+,$0&O+0)$.'$

#&(#'0)$&6%+5&%#2<$?3$-.%$#H*0+6+%0)$

,#%4$%"#$-%9&)*"#' $#0#/#-%P,$5&01#$

3.'$%"#$$1&=.9%'>.,'":.' "(# $&%%'+71%#,$+,$1,#2<$?3$%"+,$+,$&0,.$-.%$

,#%4$%"#$5&01#$+,$&.$&* <$Q##$*0>.,0;?,@04$"$.-$*&(# BCR<

11年4月2日星期六

Page 51: Ufida design-chijianqiang-qcon

BluePrint服务——服务注册<!--服务注册--><service id="orderService" interface="com.osgi.bs.IOrderService" ref="order"> <service-properties> <entry key="order.discount" value="0.8"/> </service-properties></service>

<!--实际代码-->OrderService os = new OrderService(1, 2);os.setDescription( "This is the order" );Hashtable props = new Hashtable();props.put("order.discount", "0.8");bundleContext.registerService(com.osgi.bs.OrderService.class.getName(), os, props);

11年4月2日星期六

Page 52: Ufida design-chijianqiang-qcon

BluePrint服务——服务引用<!--reference方式--><reference id="orderRef" interface="com.osgi.bs.IOrderService" timeout="1000" availability="optional"/><bean id="orderClient" class="..."> <property name="order" ref="orderRef"/></bean>

<!--reference-list方式--><reference-list id="orderRefs" interface="com.osgi.bs.IOrderService" availability="optional"> <reference-listener bind-method="bind" unbind-method="unbind"> <bean class="com.osgi.bs.ReferenceListener"/> </reference-listener></reference-list>

11年4月2日星期六

Page 53: Ufida design-chijianqiang-qcon

BluePrint服务——服务引用<!--reference方式--><reference id="orderRef" interface="com.osgi.bs.IOrderService" timeout="1000" availability="optional"/><bean id="orderClient" class="..."> <property name="order" ref="orderRef"/></bean>

<!--reference-list方式--><reference-list id="orderRefs" interface="com.osgi.bs.IOrderService" availability="optional"> <reference-listener bind-method="bind" unbind-method="unbind"> <bean class="com.osgi.bs.ReferenceListener"/> </reference-listener></reference-list>

List中的对象是动态的,会随着匹配到的服务动态增减。List没有超时属性,而且是只读的。

11年4月2日星期六

Page 54: Ufida design-chijianqiang-qcon

BluePrint服务 VS 声明式服务‣ 通过不同的方式实现组件和服务的管理‣ 声明式服务重点关注快速构建轻量级的组件模型‣ BluePrint服务则面向现有的Java开发者构建富组件模型‣ R4.0发布DS,R4.2发布BS

‣ 目前DS应用更为广泛,BS则前景广阔

11年4月2日星期六

Page 55: Ufida design-chijianqiang-qcon

OSGi与Web应用‣ 在Web应用中引入OSGi的好处:✓ Modularity——改进物理和逻辑结构,易于部署和维护✓ Lifecycle——动态安装|使用|更新|卸载✓ Services——动态解偶和依赖

11年4月2日星期六

Page 56: Ufida design-chijianqiang-qcon

OSGi与Web应用‣ 集成的两种方式:✓ HttpService

✓ Bridged

11年4月2日星期六

Page 57: Ufida design-chijianqiang-qcon

OSGi与Web应用‣ 集成的两种方式:✓ HttpService

✓ Bridged

322 CHAPTER 19 • Server Side

19.1 Servers and OSGi

In Chapter 7, “Client/Server Interaction,” we saw how to set up a simple clientand server system using HTTP, servlets, and OSGi. Subsequent chapters added apluggable web interface and provisioning support to the server. These server set-ups were based on an HTTP server embedded in an OSGi framework with serv-lets as the execution model. This was simple and clean but does not suit all usecases. Enterprise applications, for example, require scalability, performance,high-availability characteristics, and integration with existing infrastructure.Other server programming models operate at a level above servlets and are morelike distributed systems with inter-object communication. Fortunately, theserequirements are not at odds with OSGi.

Broadly speaking, there are three configurations for using OSGi on a server:

Native—One or more OSGi frameworks are run on a server machine. The frameworks interact with one another using remote messaging and mecha-nisms such as OSGi Remote Services and the Eclipse Communications Frame-work (ECF), HTTP, web applications, and other conventional server-side technologies. Solo—One or more OSGi frameworks are run and include HTTP service implementations such as Jetty. As shown in Figure 19-1, server function is exposed as servlets and JSPs and supplied by bundles hooked together by the HTTP service running directly on an OSGi framework. This is the configura-tion we have been using in Toast. Bridged—In the Bridged approach, the coding and exposure model is the same as in Solo, but here the OSGi framework is embedded into a web appli-

Figure 19–1 Solo server-side configuration

OSGi

Java

Servlets

JSPs

HTTP

!"#$$%&'()*+,-../00123%0455006%78%972:;0<28=2&:0>4;05?>?00@A>50#!

11年4月2日星期六

Page 58: Ufida design-chijianqiang-qcon

OSGi与Web应用‣ 集成的两种方式:✓ HttpService

✓ Bridged

322 CHAPTER 19 • Server Side

19.1 Servers and OSGi

In Chapter 7, “Client/Server Interaction,” we saw how to set up a simple clientand server system using HTTP, servlets, and OSGi. Subsequent chapters added apluggable web interface and provisioning support to the server. These server set-ups were based on an HTTP server embedded in an OSGi framework with serv-lets as the execution model. This was simple and clean but does not suit all usecases. Enterprise applications, for example, require scalability, performance,high-availability characteristics, and integration with existing infrastructure.Other server programming models operate at a level above servlets and are morelike distributed systems with inter-object communication. Fortunately, theserequirements are not at odds with OSGi.

Broadly speaking, there are three configurations for using OSGi on a server:

Native—One or more OSGi frameworks are run on a server machine. The frameworks interact with one another using remote messaging and mecha-nisms such as OSGi Remote Services and the Eclipse Communications Frame-work (ECF), HTTP, web applications, and other conventional server-side technologies. Solo—One or more OSGi frameworks are run and include HTTP service implementations such as Jetty. As shown in Figure 19-1, server function is exposed as servlets and JSPs and supplied by bundles hooked together by the HTTP service running directly on an OSGi framework. This is the configura-tion we have been using in Toast. Bridged—In the Bridged approach, the coding and exposure model is the same as in Solo, but here the OSGi framework is embedded into a web appli-

Figure 19–1 Solo server-side configuration

OSGi

Java

Servlets

JSPs

HTTP

!"#$$%&'()*+,-../00123%0455006%78%972:;0<28=2&:0>4;05?>?00@A>50#!

19.2 Embedding the Back End in a Web Application 323

cation and run inside a traditional web application server such as Tomcat or WebSphere. This is shown in Figure 19-2.

In this chapter we focus on the Native and Bridged scenarios for server-sideOSGi. First we change the Toast Back End from using the Solo configuration withJetty running in Equinox to having Equinox and Toast running inside a webapplication on Tomcat—the Bridged approach. Details of how this infrastructureworks are also covered. Finally, we convert Toast to use OSGi Remote Servicesand the ECF to manage the communication between the client and back endemergency monitor components without the use of HTTP servers—a Nativeserver-side architecture.

19.2 Embedding the Back End in a Web Application

Many organizations have existing Java web application servers such as Tomcat,Jetty, or WebSphere. These systems are typically run by the IT team and servebusiness-critical or customer-facing applications. They are secure and managed.With good reason, the IT teams are loath to change from this known infrastructureto running an OSGi framework directly on their servers. They have years of expe-rience with application servers and considerable support infrastructure, load balanc-ing, fail-over, and other technology supporting their needs. Fortunately, the BridgedOSGi server-side story is not “rip and replace” but more of a “co-opt” model.

Figure 19–2 Bridged server-side configuration

Lite HTTP Bridge

Equinox

Application Server

Servlets

JSPs

HTTP

!"#$$%&'()*+,-../00123%0454006%78%972:;0<28=2&:0>4;05?>?00@A>50#!

OSGi Framework

11年4月2日星期六

Page 59: Ufida design-chijianqiang-qcon

第三种武器——WAB‣ WAB——Web Application Bundle1.0(R4.2)‣ 以Bundle形式部署在OSGi框架中,提供Web应用的功能‣ 支持Servlet2.5和JSP2.1

Manifest-Version: 1.0Import-Package: ......Bundle-Version: 1.0Bundle-Name: orderManagerBundle-ClassPath: WEB-INF/lib/commons-logging.jar,WEB-INF/classesWeb-ContextPath: /orderBundle-ManifestVersion: 2Bundle-SymbolicName: com.osgi.bs.order

11年4月2日星期六

Page 60: Ufida design-chijianqiang-qcon

Web Bundle Architecture

Deploy Bundle

JVM

Application Server/OSGi Runtime

Admin Console Bundle

Web ApplicationBundles

Bundles

11年4月2日星期六

Page 61: Ufida design-chijianqiang-qcon

Web Bundle Architecture

Deploy Bundle

JVM

Application Server/OSGi Runtime

Admin Console Bundle

Web ApplicationBundles

Bundles

11年4月2日星期六

Page 62: Ufida design-chijianqiang-qcon

开源实践

‣ Equinox——最成熟的OSGi开源实现,Eclipse的插件基础‣ Gemini (Spring DM)——实现了R4.2中的企业级规范‣ Virgo (Spring DM Server)——基于OSGi的Application Server

‣ Felix——另一个成熟的OSGi开源实现‣ Nuxeo——企业级CMS,实现了部分OSGi规范

11年4月2日星期六

Page 63: Ufida design-chijianqiang-qcon

Questions? Follow me attwitter.com/sagacityt.sina.com.cn/n/池建强

11年4月2日星期六

Page 64: Ufida design-chijianqiang-qcon

杭州站 · 2011年10月20日~22日 www.qconhangzhou.com(6月启动)

QCon北京站官方网站和资料下载 www.qconbeijing.com