OpenDoc Series':OSGI实战(二)

 由  ValRay 发布

OpenDoc 版权说明

本文档版权归原作者所有。 在免费、且无任何附加条件的前提下,可在网络媒体中自由传播。

如需部分或者全文引用,请事先征求作者意见。 如果本文对您有些许帮助,表达谢意的好方式,是将您发现的问题和文档改进意见及时反馈给作者。当然,倘若有时间和能力,能为技术群体无偿贡献自己的所学为好的回馈。

Open Doc Series 目前包括以下几份文档: Spring 开发指南 Hibernate 开发指南 ibatis2 开发指南 Webwork2 开发指南 持续集成实践之 CruiseControl 请订阅http://groups.google.com/group/redsaga-notify ,以获得新版本及其他Opendoc的release通知,或从http://wiki.redsaga.com获取新更新信息。

二. 体验 OSGI

在这个章节中分别从需求实现以及技术角度两方面来体验 OSGI 带给我们的享受。

2.1. 需求实现

以一个用户登录验证模块来体验下OSGI有什么不同的地方,在下面的描述中会涉及到一些OSGI的专业术语,暂时先不管它,在后续OSGI R4 规范的章节中会仔细介绍。

用户登录验证模块

要求可动态的替换(系统运行期)用户登录验证的方式,如目前需要的有三种验证方式:LDAP 验证、DB 验证以及配置文件验证;同时要求可随时增加新的验证方式(系统运行期),如 CA 验证方式等。

这是常见的一种较为简单的动态修改和改变系统行为的需求,分别来看看传统的实现方式和基于 OSGI 的实现方式。

●传统的实现方式

■动态替换用户登录验证方式的实现

定义用户登录验证的接口,按照需求编写实现此接口的三个类,分别为 LDAP 验证类、DB 验证类以及配置文件验证类。

编写配置文件,格式类似如下:

LDAP=org.riawork.auth.LDAPAuthImpl 
DB=org.riawork.auth.DBAuthImpl 
FILE=org.riawork.auth.FileAuthImpl 
DEFAULT=DB

编写登录验证类,登录验证类读取配置文件,获取目前系统采用的验证方式, 根据验证方式获取对应的验证类,通过 Class.forName().newInstance 的方式获 取到验证类的实例,造型成用户登录验证的接口,调用验证方法完成用户登录验证。

提供登录验证方式的管理端,用户可选择采用何种方式进行登录的验证,当用户选择不同的验证方式时相应的维护配置文件。

经过这样的几步后动态替换用户登录验证方式的需求得以实现了。

■随时增加新的验证方式的实现

这个在采用传统的实现方式的时候就比较麻烦,Java 是编译性质的语言,而不是解释性质的语言,所以在动态加载类方面是要专门处理的,在 Java 中通常采用自定义 ClassLoader 的方法去实现,为了实现能随时增加新的验证方式,也需要采用这样的方法。

编写自定义的 ClassLoader,该 ClassLoader 负责扫描验证类文件夹目录,加载其中所有的类文件,在有新文件放入时,将自动的将其加载到这个自定义的ClassLoader 中。

修改之上的登录验证类,登录验证类读取配置文件,获取目前系统采用的验证方式,根据验证方式获取对应的验证类,这个时候通过自定义的 ClassLoader 来获取验证类的实例。

经过这样的步骤后,随时增加新的验证方式的需求也得以实现了。

可以看出,在采用这样的方式实现一个简单的动态修改和改变系统行为的需求是比较的复杂,需要利用到 Java 的底层特性,从一定程度上来说是有不小的难度和复杂度的,可想而知如果要实现复杂的动态修改和改变系统行为的需求的时候,传统的开发方式是很难胜任的,接下来我们来看看基于 OSGI 会怎么样去实现这样的两个需求呢。

●基于 OSGI 的实现方式

■动态替换用户登录验证方式的实现

在基于 OSGI 时可以采用这样两种方式来实现这个需求:

◆动态替换 Service 的方式 编写登录验证类,该类中拥有 setAuthService(AuthService service)这样的方法,在做验证时通过注入的这个 service 来验证。

编写用户登录验证(AuthService)接口。

编写实现 AuthService 的三个类。 将以上的验证类和用户登录验证接口作为一个Bundle[ Bundle是OSGI中的核心概念,可以看成就是一个jar文件,具体参见后续的OSGI R4 规范。 ]。

将实现 AuthService 的 LDAPAuthServiceImpl、DBAuthServiceImpl 以及 FileAuthServiceImpl 分别作为 Bundle 部署。

将这四个 Bundle 部署到 OSGI 框架中并启动。

用户需要动态替换用户验证方式的时候,只需要通过 OSGI 框架的管理端修改登录验证类 Bundle 中获取 Service 的标识即可,如之前配置的登录验证类 Bundle 中获取 Service 的标识为 DB,用户可修改为 LDAP 或者 FILE,或者用户可以直接修改登录验证类 Bundle 的配置文件,在修改完毕后登录验证的方式就被动态的替换了。

◆Bundle 控制的方式

和动态替换 Service 的方式不同的方法就是在部署和用户使用的时候稍有不同。

部署的时候部署四个 Bundle,但只启动里面用来做验证的那个 Bundle,如目前用户要使用的为 LDAP 验证,就只启动 LDAPBundle。 当用户需要改变验证方式时,可以先停止 LDAPBundle,然后启动DBBundle 或 FileBundle,这样就完成了验证方式的动态替换。

■随时增加新的验证方式的实现

基于 OSGI 实现这个需求就简单了,编写一个实现 AuthService 接口的 Bundle,然后将 Bundle 部署到 OSGI 框架中即完成了,之后通过 OSGI 管理端即可启动这个 Bundle,采用之上的动态替换用户登录验证方式的方法即可在系统中使用这个新增的 Bundle 了。

可以看出,基于OSGI的实现方式要实现这两个需求非常的简单,可能现在你看基于 OSGI的实现方式还有点看不太懂,这没关系,在后续基于OSGI框架(Equinox)的实战章节中会进行详细的讲解,这里主要是让大家体验下OSGI对于动态修改和改变系统行为的支持。

2.2. 技术角度

在搭建系统时,模块的组织方式决定了系统将如何进行开发以及如何进行部署,而模块的复用和扩展则是公司希望通过项目形成的积累,避免重复的投入,同样,分别看看传统的方式和基于 OSGI 的方式。

●传统的方式

■模块的组织 传统的方式下通常采用整个系统作为一个工程或每个模块一个工程的方式,在整个系统作为一个工程的方式下区分模块主要是通过包名的方式来区分,而每个模块一个工程的方式在传统的方式下会很麻烦,主要是在包的引用上,很容易出现模块交叉引用的现象,导致了在开发的时候非常的麻烦,同时也导致了部署的时候非常麻烦,鉴于此,在传统的方式下通常都是采用整个系统一个工程,通过包名来区分模块的方式。

■模块的复用和扩展 在采用整个系统一个工程,通过包名来区分模块的方式自然使得模块的复用变得特别的复杂,在每个模块一个工程的方式则可以让模块的复用比较的简单,由于模块的组织通常来说和系统的基础架构有直接的关联,而由于系统的基础架构没有形成规范,这样就导致有可能因为模块的组织方式不同而无法复用的现象。

模块的扩展在传统的方式通常来讲只能通过修改原有模块的代码来实现。

●基于 OSGI 的方式

■模块的组织

基于 OSGI 的方式下可采用每个模块一个 Bundle 的方式来进行组织,而在 OSGI 框架的支持下不会出现需要引用其他模块 Bundle 的情况,而只需要引用接口就可以了,这就保证了每个模块一个 Bundle 的开发方式并不会很复杂,同时 Bundle 的部署也是非常的简单。

■模块的复用和扩展

在基于 OSGI 的方式下,模块的复用就非常简单了,由于 OSGI 是规范性质的定义,只需要将 Bundle 部署上去即可为系统增加相应的模块。

模块的扩展在 OSGI 标准的规范中也是没有定义的,基本上同样只能采用直接修改原有代码的方式来实现,不过 Equinox 吸取了 Eclipse Extension Points 的设计,使得 Bundle 的扩展变得完全可行。

查看评论