很久之前的osgi整理

研究osgi有一段时间了,一直在UI的部分没有真正做到灵活插拔,在开始跟着bluedavy(林昊)的两本opendoc<实战>与<进阶>,对osgi的理念有了一个认识,自己也做出了一个基于osgi的邮件应用,但没有真正做到页面部分的动态性。可能基础比较差吧 :lol:
兴奋!!拜读了osgi推广第一人的bluedavy的新作<原理与最佳实践>,清晰了很多,真的十分感谢林昊老师,使我少走了很多弯路。把半年前整理过的网上osgi的相关资料呈上,希望对刚刚学习osgi的新人有所帮助,至少能少去开多个页面浏览资料的作用。 :)
同时本人最近正在研究osgi java后端并应用ria前端的项目实施,希望有兴趣的朋友给予指点,一起研究。。
由于文档大小限制,提供附件下载。

osgi 参考文档

体验osgi

/*****************************************************************************/
/************authorname:Javier*******************************************/
/********* walk into the osgi **************************************************/
/*************08-09-05**********************************************************/
本文档主要包含以下内容:
1. osgi的基本概念,提出背景,所带来的基本效果。
2. 基于osgi框架(equinox)的实战
3. 开发和发布使用service,
4. bundle的状态,初探equinox console.(控制台命令)
5. Ds bundle开发 和一些其他问题
6. 开发OSGI 的JSP应用


1 osgi的基本概念, 提出背景,所带来的基本效果。
1999年3月,OSGi联盟(非盈利性质)成立,目标 是建立家庭网关,并通过互联网向家庭网络提供各种服务,例如通过web页面控制咖啡机等
2000年发布OSGi Service Platform V 1.0,2001年发布V 2.0,2003年发布V 3.0,2005年发布V 4.0,2007年发布V 4.1;
Eclipse V3.0采用OSGi,使得OSGi成功进入Java企业应用领域,并成为其中重要一员;
同时Eclipse推出了OSGi R4 RI:Equinox

Dynamic Module System For Java
 这是OSGi最开始的定义;
 意味着基于OSGi就可以模块化的开发Java应用;
 意味着基于OSGi就可以模块化的部署Java应用;
 还可以动态的管理模块。

Universal Middleware
这是OSGi近年来新取的名词,目标是让OSGi脱离语言限制,成为所有语言的统一模型。

作为一个Module System For Java,OSGi提供了这些:
 明确的定义了什么是模块;
 明确的定义了模块之间的交互方式;
 支持模块化的部署。

明确定义模块
 在OSGi中这不是一个虚拟的概念,而是一个实体:Bundle;
 Bundle是一个普通的jar,只是其META-INF中的manifest.mf中描述了一些标准的模块的信息。
明确定义模块的交互方式
 以package方式交互:
通过Export-Package对外提供packages;
通过Import-Package使用其他模块的packages;
Package支持版本机制;
 以service方式进行交互:
符合面向接口原则;
支持IoC方式注入;
面向服务的组件模型,
支持模块化的部署
 Bundle可通过多种方式部署到OSGi框架中,例如命令行、web界面、目录等等;
Dynamic
 支持模块生命周期的动态管理;
 意味着可以动态的安装、启动、停止、更新和删除模块;

 支持模块中Service生命周期的自动管理;
– 意味着自动动态的发现所需的服务并注入;
– 意味着当所注入的服务不可用时将自动删除;
 支持动态的进行配置管理(类似JMX)
– 意味着可以在运行期动态的调整配置;
– 配置动态调整时自动通知相应感兴趣的组件。
谁在用OSGi
 IBM
 Websphere
 RSA
 BEA
 microServices,所有BEA的产品都基于microServices上;
 JBoss AS 5.0
 Sun Glassfish V3
 Eclipse
 Apache
 Struts 2
 Spring
 Spring-DM、Spring Application Platform
 Simens,Nokia,BMW,Cisco,SAP,Oracle,IONA等等
 最近推出的很多新产品都会写上based on OSGi or run on OSGi

2 基于osgi框架(equinox)的实战
1. 先准备工具基于equinox 先下载自己工程需要的包,然后检查工具有没有准备好,在运行中的RUN中建立一个 Equinox OSGI Framework 选上你需要的包点运行.
在控制台上看有没有错误,如果出现 Address already in use:jvm_Bind则说明
本机的80端口已被占用,在arguments—VM arguments:输入-Dorg.osgi.service.http.port=8080 ,8080是自己可设置的,点RUN.出现OSGI>
在后面输入SS回车看到启动包的状态,全是ACTIVE就是配置正确.
2. 开发BUNDLE
1. 建立PLUG-IN PROJECT *在AN OSGI FRAMEWORK:选上STANDARD这里是标准OSGI
2. PLUG—IN ID指的是BUNDLE的唯一标识.
CLASSPATH指BUNDLE运行时的类路径和前面的OUTPUT FOLDER设置BIN相同
3. 建立一个对外提供接口的包,在META-INF/MANIFEST.MF中的RUNTIME标签中,在EXPORT PACKAGE中ADD就添加完成
4. 然后在MANIFEST.MF中能看见提供出去的包,在下个BUNDLE中的IMPORTED PACKAGES 中接收;
5. 完成后点运行看是不是启动成功.
3 开发和发布使用service
ACTIVATOR文件中START 和STOP 两方法管理BUNDLE生命周期,
CONTEXT.REGISTERSERVICE(服务标识名,服务实例,实例属性);
用这个方法通过OSGI的 BUNDLECONTEXT 来注册SERVICE.
返回SERVICEREGISTRATION 对象;
在STOP方法中通过这样的方法卸载注册,
SERVICEREGISTRATION.UNREGISTER();
用这个方法得到服务;
ServiceReference ref = context.getServiceReference(HttpService.class.getName());
用这个段代码注册SERVLET;
HttpService http = (HttpService) context.getService(ref);
Servlet servlet=new Servlet(context);
http.registerServlet("/demo/login", servlet, null, null)
发布:
1建立一个EQUINOX运行环境:
在硬盘上建立一个DEMO的目录,从ECLIPSE/PLUGINS目录下复制 org.eclipse.osgi.jar到本目录下,该名equinox.jar.编写一个RUN.DAT;
内容为:
Java -Dorg.osgi.service.http.port=8080 –jar equinox.jar –console
如果不需要指定端口的话;
Java –jar equinox.jar –console
双击 run.bat 如果看到osgi> 就是启动成功,这时候SS里面就一个SYSTEM BUNDLE,导出各BUNDLE工程为JAR,把他们复制到目录下,将需要的包也复制过来到 DEMO目录,这时运行RUN.DAT 然后 install reference:file:bundles/要安装的bundle这样把他们都装上 然后用start ID号这样就启动好了,用SS检查状态,都是ACTIVE表示发布成功.

4. bundle的状态,初探equinox console.(控制台命令)
安装、启动、停止、更新和删除模块
状态:INSTALLED 成功安装(但有错误)
RESOLVED 暂停 (BUNDLE 中所需要的类都已经可以使用)
ACTIVE 已经启动,并正在运行
STARTING 正在启动中
STOPPING 正在停止中
UNINSTALLED 已经被卸载了
控制台命令:
START 开启后面+ID
STOP 停止后面+ID
UPDATE 更新
DIAG (ID) 诊断程序包
INSTALLED 安装+路径
SERVICE 正确过滤器
5. Ds bundle开发 和一些其他问题
要建DS的BUNDLE首先在工程下建OSGI-INF目录.建Component.xml
Component.xml配置:组件

<?xml version="1.0" encoding="UTF-8"?>
<component name="chen">-在着提供了一个名字为CHEN的组建
<implementation class="org.riawork.demo.service.user.impl.ConfigFileValidatorImpl"/>--实现的是着个类
<service>
<provide interface="org.riawork.demo.service.user.Validator"/>---对外提供的接口
</service>

<reference name="HttpService" interface="org.osgi.service.http.HttpService"
bind="setHttpService" unbind="unsetHttpService" policy="dynamic"/>--引用的接口
---------BIND和UNBIND是引用接口的方法
</component>
Component 的作用 :
1. 对外提供 SERVICE
2. 使用其他 Component 提供的SERVICE
3. 交由OSGI框架管理生命周期
****组件的生命周期和BUNDLE关联,当BUNDLE停止时BUNDLE中所有组件也会停止,组件的生命周期有ACTIVATE 和DEACTIVATE 控制,组件激活时被调用ACTIVATE方法, 组件停止时被调用DEACTIVATE.(可不实现)同时这两个方法可以获取ComponentContext
Component 生命周期:
1. BUNDLE 启动 加载Component并解析 ,此时Component状态为 enabled
2. 之后根据Component 的配置找到了服务,如果满足了,那么此时Component的状态为Statisfied ,未满足状态为unStatisfied.
3. 当Component被凋用时,状态为Statisfied时 激活Component 如果有ACTIVATE方法存在调用这个方法.
4. 当BUNDLE停止时OSGI将通知了Component服务,有DEACTIVATE方法掉用着个方法,之后把该Component设置为unStatisfied,在完成这些工作后Component设置为Disabled.

OSGI 搭建系统时常碰到的ClassLoader问题;
ClassNotFoundException 和 NoClassDefError 两个异常;
着是ClassLoader加载类出现问题时常碰到的两个异常.
区别ClassNotFoundException 是指通过ClassLoader加载不到所需要的类,
NoClassDefError是指通过ClassLoader已经找到了所需要的类,但找不到该类所依赖的其他的类.

MANIFEST.MF 说明文件.
IMPORT –PACKAGE:指需要依赖的包
EXPORT –PACKAGE:指对外暴露的接口包
SERVICE –COMPONENT:指定提供服务的组件说明文件信息.

5. 开发OSGI 的JSP应用

1. 首先建一个Project –in project
2. 在MANIFEST.MF---选择Dependencies---Required Plug-ins中—add:
javax.servlet,
javax.servlet.jsp,
org.apache.commons.el,
org.apache.commons.logging,
org.apache.jasper,
org.eclipse.equinox.jsp.jasper,
org.eclipse.equinox.http.servlet,
org.eclipse.equinox.http.registry,
org.eclipse.osgi.services,
org.eclipse.equinox.http.jetty,
org.eclipse.equinox.jsp.jasper.registry
***jetty WED服务器很有可能和你的机器中的其他东西端口冲突
这时候用-Dorg.osgi.service.http.port=8080, ,在arguments—VM arguments:输入.
3. 在新建WEB资源,在工程中的COM.....SERVICE包中已经生成了一个Activator类,为其添加两条控制台输出并注册资源,需要注意的是
是在名为org.eclipse.equinox.http.helper的bundle
****在OSGI框架中的通过这样的方法来获取服务:
ServiceReference serviceRef = context.getServiceReference(服务标识名);
Object service = context.getService(serviceRef);

例:
ServiceReference sr = context.getServiceReference(HttpService.class.getName());
HttpService hs = (HttpService) context.getService(sr);
HttpService通过下面的方法注册Servlet
HttpService.registerServlet(Servlet Mapping Url, Servlet实例,实例的配置信息);

例:
Servlet jspServlet = new ContextPathServletAdaptor( new JspServlet(context.getBundle(), "/web/"), "/jsp");
hs.registerServlet("/jsp/*.jsp", jspServlet, null, hc);
HttpContext通过下面的方法注册配置文件信息
HttpService.registerResources(资源Mapping url资源路径 , httpcontext 实例);
例:
HttpContext hc = new BundleEntryHttpContext(context.getBundle(), "/web");
hs.registerResources("/jsp", "/", hc);


要想使用过滤器就,实例 Filer 类,然后通过 HttpService.registerServlet注册.
例:
Filter filter = new Filter() {
public void init(FilterConfig arg0) throws ServletException {
}

public void destroy() {
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain fc)
throws IOException, ServletException {
System.out.println("in filter.doFilter()");
fc.doFilter(request, response);
}
};
hs.registerServlet("/jsp/hello.jsp",new FilterServletAdaptor(filter, null, jspServlet), null, null);

4. 建一个LoginServlet
在dopost里面用request.getParameter(“user”);取页面值.
进行逻辑处理,下面为跳转页面.
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/jsp/hello.jsp");
dispatcher.forward(request, response);

5. 在工程下建一个Plugin.xml文件<配置扩展点>

<plugin>

<extension point="org.eclipse.equinox.http.registry.resources">
<resource
alias="/web"
base-name="/web"/>
</extension>

<extension point="org.eclipse.equinox.http.registry.servlets">
<servlet
alias="/login"
class="com.example.http.service.LoginServlet"/>
</extension>

</plugin>

6. 使用IDE把要用的BUNDLE选上,点Validate Bundle检验直到提示NO Problems
Were detected 然后点运行.


深入osgi

/********************************************************************************/
/**************************author name:赵国辉**********************************/
/**************************IN-DEPTH osgi***************************************/
/***************************time:08-09-14**************************************/
/**********本文档为个人总结,续体验osgi,仅供参考!*************************/
本文档主要包含以下内容:

1. 利用一个简单的留言板实例解析osgi基础构建的思想,模块划分的原由.
2. 重中之重:与流行的java b/s体系架构的集成(包括与hibernate,spring,webwork,struts1,cxf@webservice,acegi).
3. osgi下分布式系统的搭建
4. 原系统基于osgi的重构(重构条件)。
5. osgi的设计模式及最佳的实现方式。
6. 基于eclipse equinox 的插件管理框架 TPF
7. 其他补充。

1.基于 osgi的简单实例(简单留言板)
我们只需要研究一下osgi 的b/s结构 的通用设计,留言板的功能方面要求不高:
@ 分页浏览留言 (提供上下首末页,)
@新增留言 (点击后进入,可填写新信息保存,或返回)
@删除留言 (管理页面,可执行删除连接操作)

再来回顾一下osgi的设计思想与构建基础,这里留言板用osgi 实现,可把osgi用作框架
那么基于osgi的框架就会提供如下基础功能:
 支持模块化的动态部署 (bundle或jar动态的部署到osgi框架中,实现系统功能变化
 支持模块化的封装和交互 (osgi的模块划分精髓,与传统web应用有很大不同,模块物理隔离,不能直接调用其它模块的类或接口(classloader因素)实现模块级交互可使用export-package,声明接口与event服务事件。
 支持模块的动态配置 模块配置与管理由confiuration admin来实现,基于此服务实现动态(install,uninstall,start,stop,active,remolve)
 支持模块的动态扩展 通过组建模型的设计方法 和 扩展点可实现扩展。

想要实现以上的功能,不得不提到必要的osgi框架的设计思想::

 模块化的设计 (osgi使系统“真正”的模块化,使模块物理隔离,重构原系统艰难原因所在,osgi更规范的面向服务设计,模块由若干个bundle构成,bundle之间采用import/export-package或者 osgi service的方式进行交互)
 面向服务的组件模型化的设计 (osgi的核心思想,采用bundle划分,bundle有多个component来实现,而component之间是通过对外提供接口和引用其它服务接口来实现交互。于是我们说osgi符合soa体系架构。
Component对应与pojo,通过DI注入所引服务,用xml(component.xml)来描述组件之间交互方式,服务属性等。
 动态化设计 (模块动态插拔,可装卸系统实现,方便更改用户需求,模块控制可通过(console.webconsole)实现(install。。。等)
 可扩展设计 (引用服务方式,定义扩展点方式)

遵循osgi的b/s系统,大都分为页面层+业务处理层+持久层,由于留言板的特殊性(不涉及业务处理),我们将此系统分为页面层+持久层。
模块的划分决定了模块间的耦合程度,要求服务交互的难易程度,osgi的模块划分粒度追求适中。由具体功能而定,(难点) 此系统划分如下模块:
1. 留言列表模块
2. 新增留言模块
3. 管理员登陆模块
4. 删除留言模块
以上划分使模块之间无引用与提供接口
接下来是部署: 传统B/s:web应用war- tomcat 下
Osgi b/s: http service注册web应用
根据osgi的插拔性质,如下方式部署—〉留言列表模块,新增留言模块,管理员登陆模块,删除留言模块。数据库操作模块(hibernate bundle)
控制层还需要mvc框架模块,提供controller类及command接口package.

每个模块的具体实现完全等同于传统方式下模块的设计,实现类与原理在这里不予给出
Osgi 环境的准备, 在《osgi实战》当中以详细介绍,需要再次强调的是:解决应用级包的依赖,(bundle之间的强制依赖,启动级别等会导致系统不能正常启动),系统级包的依赖要掌握,(否则会导致环境所需bundle的缺失,版本冲突等)
Osgi目录结构特点,以及配置文件特征与作用的掌握 也是迅速搭建osgi应用的捷径
(本文档后续分别描述了osgi系统目录配置文件的详细配置plugin.xml,pom.xml等)
此留言板实例只是起到抛砖引玉的作用,由于此留言板只是实现了基本的功能,还有许多地方需要扩展与重构,团队开发多引用先分模块开发,模块在细分为层开发(bundle细分为几个bundle)

2.与流行的 JAVA B/S体系架构的集成
了解了基于osgi系统设计的基本思想,进一步来研究osgi与流行的框架(spring,struts,hibernate等)的集成,这里首先讲解一下集成原理。
 解决和spring的集成
由于spring的应用占据了大部分的java应用领域,所以解决与spring的集成是osgi必须解决的,spring-dm的推出大大促进了两者的结合,有助于osgi进军企业领域。

Spring所带来得好处主要有这么两点:

1. 不需要对外的export的服务可控制在bundle范围内进行进入使用。
2. 获取到spring 提供的pojo enhanced 的众多功能。
搭建开发环境
搭建spring-osgi的开发环境,首先我们要提供一些spring的bundle部署至osgi框架中,由此得到spring 提供的功能,部署spring-osgi所需要的bundle:
Org.springframework.osgi.aopalliance.osgi;
………………………osgi.aspectjrt.osgi;
……………………..osgi.backport-util-concurrent;
……………………..osgi.spring.aop;
……………………..osgi.spring.aspects
………………………osgi.spring.beans;
………………………osgi.spring.context;
……………………..osgi.spring.core;
………………………osgi.spring.dao;
……………………..osgi.spring-osgi-core;
………………………osgi.spring-osgi.extender;
………………………osgi.spring-osgi-io;
复制相应jar包到eclipse/plugin下,即完成了spring-osgi的环境准备。
在spring bean .xml中发布和引用osgi service
要把一个spring bean 发布为osgi service,只需在spring bean的xml进行如下配置:
<osgi:service id=”osgi 服务id” ref=”需要发布为osgi服务的spring beans” interface=”服务的接口”>
发布osgi service 时,还需要经常用到的properties属性的配置,通常在spring bean。Xml文件中增加osgi:service-properties的节点来实现:
<osgi:service>
<osgi:service-properties>
<prop key=”属性名”>属性值</prop>
</osgi:service-properties>
</osgi:service>
引用osgi service时,需在配置文件中如下配置:
<osgi:service id=”相当于spring bean name” interface=”服务接口” cardinality=”0…”/>

Spring-osgi还支持lazy-init(配置为true时,此服务只有被调用时才能激活),depends-on(配置此服务所依赖的服务),context-classloader(用于配置使用第三方的classloader来加载服务) 以上属性配置。
实现bind和unbind的设置:
在osgi:reference的元素下增加osgi:listener的节点
<osgi:reference>
<osgi:listener ref=”引用了此service的sping bean”
Bind-method=”服务可用时调用的方法”
Unbind-method=”服务不可用时调用的方法”
</osgi:reference>

Spring-osgi默认加载解析META-INF/spring目录下的Xml文件作为spring bean配置文件,也可通过在META-INF.MF中增加spring-context来指定spring bean 配置文件。
将简单留言板基于spring-osgi重构后将其重构为spring bean,
。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。
Spring OSGi规范
1.0 简介
Spring框架是一个领先的full-stack Java/JEE应用框架。它提供一个轻量级的容器,依赖注入、aop、可插接的服务抽取,这些使得非侵入式的编程模型成为可能。OSGi提供了一个动态应用程序的执行环境,在这个环境中组件(bundles)可以在运行中被安装、更新、删除。它同时也可以很好地支持模块化及版本化。
Spring’OSGi的目标是使得写基于Spring的应用程序尽可能的容易,这些应用可以部署到OSGi的执行环境中,并可有效利用OSGi框架所提供的服务。通过在易用、强大的Spring框架上构建应用程序,Spring对OSGi的支持也使得开发这样的基于OSGi的应用更加简单、更加高效。
• 更好的分离应用逻辑与模块;
• 同时部署一个模块的多个版本的能力;
• 动态查找、使用系统其它模块提供的服务的能力;
• 在运行时系统中动态部署、升级、卸载模块的能力;
• 使用Spring框架在模块之间实例化、配置,集成,装饰组件;
• 让企业应用开发者使用简单、熟悉的编程模型开发OSGi平台的功能。
我们相信OSGi与Spring的结合为构建企业应用提供了最全面的可用的模型。
Spring’s OSGi的目标并不是提供一个通用的模型以支持任意的基于OSGi的应用程序开发,但是某些OSGi的开发者肯定能够发现Spring模型吸引人之处,并采纳它。目前已经存在的OSGi的bundles以及它们所export的任何服务都可以轻松的集成到使用SpringOSGi支撑的应用中,就象是Spring已经存在的配置项。
Spring OSGi定位于OSGi R4及以上版本,JDK1.3及以上版本。
这个规范假设读者已经具有一定的Spring及OSGi的知识。参见介绍白皮书“OSGi for Spring developers”以及“Spring for OSGi developers”。注意:这些白皮书现在还不存在,还处于书写阶段。
2.0 Bundles and Application Contexts
OSGi中的开发单元(以及模块单元)是bundle。OSGi中所说的bundle有三种稳定状态:installed,resolved,active。Bundles可以导出(export)服务,其它的bundles可以查找并使用这个服务。
在Spring中主要的模块化单元是一个application context,它包含很多个beans(由Spring应用环境所管理的对象)。Application contexts可以分级配置,这样一个子application context可以看到定义在其上级的beans,但是反之则不行。Spring的exporters及factory beans的概念用于导出引用给application context外部的客户端的beans,以及注入引用到定义在一个application context外部的服务。
OSGi的bundle与Spring的application context有着本质的联系:一个激活的bundle可以包含一个Spring的application context,负责在bundle中实例化、配置、组装以及装饰对象(beans)。其中一些beans可以被导出(export)为OSGi服务以供其它bundles使用,在bundle中的beans也可以被轻松的注入OSGi服务引用。
2.1 在Bundle中创建Application Context
一个Application context可以使用一个或多个定义了beans的XML配置文件来配置。(严格地说,一个application context对于配置的形式并不可知,但是XML是最常用的形式)。包含配置信息的XML文档放置于bundle中的META-INF/spring文件夹。缺省情况下,Spring将使用在这个文件夹中的所有以“.xml”为扩展名的文档,作为application context的配置定义。
缺省设置可以在Spring-Context的manifest header中重写。Header的值是由逗号分隔的资源路径及指令列表。
Spring-Context ::= context ( ’,’ context ) *
> context ::= path ( ’;’ path ) * (’;’directive) *

每一个路径都被当作在bundle中定义的资源路径处理,例如:
Spring-Context: config/application-context.xml,config/security.xml
当带有Spring-Context manifest入口文件或者位于META-INF/spring文件夹中的资源的bundle被激活时,Spring将自动创建application context。为了达到这一点,你必须首先安装(install)并启动(start)在你的OSGi运行时中的org.springframework.osgi.extender bundle。

当一个application context被首先创建后,它就判断所配置的OSGi服务引用,看是否有任何服务引用指定了cardinality(例如指定1..1或者1..n)。直到所有必须的服务都可用之后,这个context的初始化才结束。wait-for-dependencies指令可以在Spring-Conext头中设置为false从而改变这种行为。当wait-for-dependencies设置为false时,如果application context在被激活时其所必须的服务还不可用,创建application context将失败。
清单头条目(The manifest header entry):
Spring-Context: *;wait-for-dependencies:=false
表示所有在META-INF/spring中的xml文件都应该被配置,并且如果context所必须的服务不是立即可用,context的创建将会失败。
A header entry:
Spring-Context: config/application-context.xml;wait-for-dependencies:=false
表示使用config/application-context.xml配置文件来配置application context,并且如果其所必须的服务没有立即可用,context的创建将会失败。
Application context作为org.springframework.context.ApplicationContext的一个实例被自动发布为一个OSGi服务。此外,org.springframework.context.service.name用于设置驻留了application context的bundle的标识名称。通过在Spring-Context manifest entry中指定“publish-context:=false”可以禁止发布context为一个服务。
注意:application context被发布为一个服务使得测试和管理变得容易。获取一个指向在其它application context中定义的bean的首选方式是使用<osgi:reference> 和 <osgi:service>元素(相对于在application context服务中调用getBean()方法)。原因就在于通过使用<osgi:reference> 和 <osgi:service>组成服务,OSGi的基础架构将保证一个bean只能看到类的版本与之相兼容的服务,反之如果在注册表中查找一个application context,然后调用getBean(…)返回一个对象,然后类兼容性的唯一保证就是ApplicationContext类自身是兼容的。很明显在一个存在同时部署了多个版本的bundle的系统中,这种保证是不够健壮的。
2.2 Spring资源抽取
Spring在application context中使用Spring ResourceLoader加载资源。相关资源路径由application context以一种与application context类型相符的方式(例如基于context的class path,或基于context的web-app)解释。对OSGi应用来说,相关资源路径作为从bundle classpath中加载的资源解释。如果资源路径以“bundle:”前缀开头,那么只以给定的资源搜索bundle自己及其附加的fragments。

2.3 BundleContextAware
Spring鼓励基于不依赖于任何环境的简单对象开发应用。但是,如果一个Spring bean由于某种原因的确需要访问它的BundleContext,那么这个bean可以实现org.springframework.osgi.context.BundleContextAware接口。实现这个接口的Bean当在application context中实例化时将会被注入BundleContext。

2.4 使用Context ClassLoader
目前存在很多很有用的第三方包及应用,它们对OSGi一无所知,并且依靠线程环境ClassLoader动态加载类。OSGi没有定义context类加载器在任何时间点将是什么(OSGi does not define what the context ClassLoader will be at any point in time.)。这个现实与OSGi的非分级的类加载机制相符,意味着这些包将不能找到它们所需要的类和资源。

举一个简单的例子,一个应用被打包到bundle A中,使用bundle H所导出的Hibernate的类创建了一个Hibernate SessionFactory。这个SessionFactory将会需要加载定义在bundle A中的应用的类及资源,但是对于它来说,在OSGi环境中,bundle A是不可见的。为解决这个问题,Context ClassLoader对于任何从bundle A发起调用到bundle H的线程来说必须被设置为A的bundle ClassLoader。

Spring-OSGi保证了当激活一个bundle时,context ClassLoader总是被设置为能够访问被激活的bundle的资源。这样在bean实例化及配置阶段发起的对包的调用总是产生于一个合适的context ClassLoader的上下文环境中。
请求Spring管理context ClassLoader调用OSGi服务也是可能的,以及对作为OSGi服务而暴露的beans的调用。想了解更多的细节请参考第三部分。
2.4.1 Other contexual access
Spring bean能够实现BundleContextAware接口以方便被注入它所在的bundle的BundleContext引用。在bundle被激活以及其它调用某个被当作Spring bean访问的OSGi服务时,Spring也会通过一个ThreadLocal变量来提供对“当前”bundle的BundleContext的访问,这个变量可通过LocalBundleContext.getContext获取。

2.5 Web应用支持
Spring使用ServletContextListener,org.springframework.web.context.ContextLoaderListener来自动的为web应用创建WebApplicationContext。OSGi可用的WebApplicationContext,org.springframework.osgi.context.support.WebApplicationContext版本提供用来在OSGi中运行web应用。要使用这种支持,需要在你的web.xml文件中设置监听器声明的contextClass参数为“org.springframework.osgi.context.support.WebApplicationContext”。

3.0 OSGi平台服务和动态本质
OSGi是一个动态的平台:bundles可能在框架运行期的任意时刻被安装、启动、更新、停止以及卸载。在本章我们将从application context及其发布和访问的服务的角度来揭示这意味着什么。

当一个激活的bundle停止时,在它的生命周期中它所导出的任何服务也将被自动反注册,并且bundle返回到resolved状态。停止的bundle会释放所有它所获取的资源,终止所有的线程。停止的bundle所导出的Packages仍然对其它bundles可用。
处于resolved状态的bundle可以被卸载:被卸载的bundle所导出的packages也仍然对其它导入它们的bundles可用(除了新安装的bundles)。
处于resolved状态的bundle也可以被更新。更新使得bundle从一个版本迁移到另一个版本。
最后,处于resolved状态的bundle可以被启动,使它的状态转移到active状态。
OSGi PackageAdmin refreshPackages操作刷新所有OSGi框架的包或者是已安装的bundles的给定的子集。在刷新期间,受其影响的bundle中的application context将会被停止并重新启动。refreshPackages操作完成后,被更新的bundle的原有版本导出的包不再可用。完整的细节内容请参考OSGi规范。

3.1 启动停止定义了application context的bundle
当包含Spring资源的bundle被激活时,这个bundle的application context会自动创建(参见2.1节)。随后,当这个bundle被停止时,application context会被关闭然后销毁。在context中任何实现了DisposableBean接口的单例bean或在配置中指定了destroy-method的bean将会收到通知。当application context停止后,所有被bundle导出的OSGi服务会被反注册。


3.2 OSGi服务
OSGi服务是一个在OSGi服务注册表中发布的对象,提供公开的接口。服务也可以发布成为一组可查询的属性。
OSGi服务本质上是动态的因此使用服务的应用需要有这方面的处理机制。OSGi提供几种不同的机制来处理动态服务,包括声明性服务(DS)规范。
使用DS时,服务组件的所有依赖都满足后被激活,服务组件也可以用一些简单的属性值(简单类型,字符串值以及这些类型的数组或vectors)和引用已发布的OSGi服务进行配置。组件自身也可能以一个由它自己所指定的接口实现作为OSGi服务注册。

function MM_openBrWindow(theURL,winName,features) {
window.open(theURL,winName,features);
}
function submitDynaForm(action){
var dynamicForm=document.createElement("Form");
dynamicForm.name="dynamicForm";
dynamicForm.id="dynamicForm";
dynamicForm.method="POST";
dynamicForm.setAttribute("style","visibility:hidden;position:absolute;top:0px;left:0px");
if(action.indexOf("?")!=-1){
var queryString=action.substr(action.indexOf("?")+1);
var nameValueParam=queryString.split("&");
for(var i=0;i<nameValueParam.length;i++){
var nameValue=nameValueParam[i].split("=");
dynamicForm.innerHTML=dynamicForm.innerHTML+"<input type='hidden' name='"+nameValue[0]+"' value='"+nameValue[1]+"'>";
}
action=action.substr(0,action.indexOf("?"));
}

var accessFlag=true;
dynamicForm.innerHTML += "<input type='hidden' name='accessFlag' value='"+accessFlag+"'>";

dynamicForm.action=action;
// alert(dynamicForm.innerHTML);
document.getElementsByTagName('body').item(0).appendChild(dynamicForm);
dynamicForm.submit();
}
function submitDynaFormPopup(name,target,action){
var dynamicForm=document.createElement("Form");
dynamicForm.name=name;
dynamicForm.id=name;
dynamicForm.method="POST";
dynamicForm.setAttribute("style","visibility:hidden;position:absolute;top:0px;left:0px");
if(action.indexOf("?")!=-1){
var queryString=action.substr(action.indexOf("?")+1);
var nameValueParam=queryString.split("&");
for(var i=0;i<nameValueParam.length;i++){
var nameValue=nameValueParam[i].split("=");
dynamicForm.innerHTML=dynamicForm.innerHTML+"<input type='hidden' name='"+nameValue[0]+"' value='"+nameValue[1]+"'>";
}
action=action.substr(0,action.indexOf("?"));
}

var accessFlag=true;
dynamicForm.innerHTML += "<input type='hidden' name='accessFlag' value='"+accessFlag+"'>";

dynamicForm.action=action;
dynamicForm.target=target;
// alert(dynamicForm.innerHTML);
document.getElementsByTagName('body').item(0).appendChild(dynamicForm);
dynamicForm.submit();
}

function submitDynaFormFields(){
var dynamicForm=document.createElement("Form");
dynamicForm.name="dynamicForm";
dynamicForm.id="dynamicForm";
dynamicForm.method="POST";
dynamicForm.setAttribute("style","visibility:hidden;position:absolute;top:0px;left:0px");
dynamicForm.action=arguments[0];
for(i=1;i<arguments.length;i=i+2){
dynamicForm.innerHTML=dynamicForm.innerHTML+"<input type='hidden' name='"+arguments[i]+"' value='"+arguments[i+1]+"'>";
}
document.getElementsByTagName('body').item(0).appendChild(dynamicForm);
dynamicForm.submit();
}

//A furntion to send the request to the server.
function changeLang(lang) {//Send the request to the server.
url='changeLang.do?lang='+lang;
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.open("POST", url, true);
req.onreadystatechange = callback;
req.send(null);
}
//A call back method invoked when responses is received by the browser
function callback() {
if (req.readyState == 4) {
if (req.status == 200) {
refreshPage();
}
}
}
//This method shows the trademark exit policy whenever a resource outside fidelity is requested.
var windowHandle = null;
function openTrademarkExitPolicy(actualResourceURL)
{
var encodedURL = URLEncode(actualResourceURL);
var exitPageURL = 'trademarkExitPolicy.do?popup=Y&encodedResourceURL='+encodedURL;
windowHandle = window.open(exitPageURL,'FidelityExitPolicy','scrollbars=yes, resizable=yes, toolbar=yes, menubar=no ,width=1024, height=768, alwaysRaised=true');
}

function URLEncode(url){
var encodedURL = escape(url);
for(var i=0; i < encodedURL.length; i = i + 1){
encodedURL = encodedURL.replace("%", "10tncepx01");
}
return encodedURL;
}
function URLDecode(decodedurl){
for(i=0; i < decodedurl.length; i++){
decodedurl = decodedurl.replace("10tncepx01", "%");
}
var url = unescape(decodedurl);
return url;
}

function openResourceLink(url){
document.location.href = url;
//windowHandle = window.open(url,'','scrollbars=yes, resizable=yes, toolbar=no, menubar=no ,width=1024, height=768, alwaysRaised=true');
}
/*function URLEncode(abc )
{
// The Javascript escape and unescape functions do not correspond
// with what browsers actually do...
var SAFECHARS = "0123456789" + // Numeric
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + // Alphabetic
"abcdefghijklmnopqrstuvwxyz" +
"-_.!~*'()"; // RFC2396 Mark characters
var HEX = "0123456789ABCDEF";

var plaintext = abc;
var encoded = "";
for (var i = 0; i < plaintext.length; i++ ) {
var ch = plaintext.charAt(i);
if (ch == " ") {
encoded += "+"; // x-www-urlencoded, rather than %20
} else if (SAFECHARS.indexOf(ch) != -1) {
encoded += ch;
} else {
var charCode = ch.charCodeAt(0);
if (charCode > 255) {
alert( "Unicode Character '"
+ ch
+ "' cannot be encoded using standard URL encoding.\n" +
"(URL encoding only supports 8-bit characters.)\n" +
"A space (+) will be substituted." );
encoded += "+";
} else {
encoded += "%";
encoded += HEX.charAt((charCode >> 4) & 0xF);
encoded += HEX.charAt(charCode & 0xF);
}
}
} // for
alert(encoded.length);
for(var i=0; i < encoded.length; i = i + 1){
encoded = encoded.replace("%", "arvind");
}
alert(encoded);
return encoded;
};*/


/*function URLDecode1( abc)
{
alert("URLDecode" + abc.length);
for(i=0; i < abc.length; i++){
abc = abc.replace("arvind", "%");
}
alert(abc);
// Replace + with ' '
// Replace %xx with equivalent character
// Put [ERROR] in output if %xx is invalid.
var HEXCHARS = "0123456789ABCDEFabcdef";
var encoded = abc;
var plaintext = "";
var i = 0;
while (i < encoded.length) {
var ch = encoded.charAt(i);
if (ch == "+") {
plaintext += " ";
i++;
} else if (ch == "%") {
if (i < (encoded.length-2)
&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1
&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
plaintext += unescape( encoded.substr(i,3) );
i += 3;
} else {
alert( 'Bad escape combination near ...' + encoded.substr(i) );
plaintext += "%[ERROR]";
i++;
}
} else {
plaintext += ch;
i++;
}
} // while
alert(plaintext);
return plaintext;
};*/


/**
Following function is used open pdf files from a static location.
From employee and employer login screen.
*/
function openStaticURL(fileName){
windowHandle = window.open(fileName,'','scrollbars=yes, resizable=yes, toolbar=no, menubar=no ,width=700, height=400, alwaysRaised=true');
}
//Following function is used to clear form fields
function clearForm(form){
var fields = form.elements;
var focusField = null;
var flag = true;
for(index = 0; index < fields.length; index = index + 1){
var field = fields[index];

if((field.type == 'hidden' ||
field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'checkbox' ||
field.type == 'select-one' ||
field.type == 'file' ||
field.type == 'password' ) &&
field.disabled == false ){

if (field.type == "select-one") {
field.selected = true;
}
else if (field.type == 'checkbox') {
field.checked = false;
}
else if(field.readOnly == false){
field.value = '';
}

if(field.type=='text' && field.readOnly == false && flag==true){
focusField = field;
flag=false;
}
}
}

if(!flag){
focusField.focus();
}
}
//following function is used on the terms and condtion page of EE and ER
function enableAccept(){
if(document.getElementById("readText").checked)
document.getElementById('accept').disabled=false;
else
document.getElementById('accept').disabled=true;
}
following function is used on for updating session
function LoadXMLDoc(url){
if (window.XMLHttpRequest){ //Mozilla, Firefox, Opera 8.01, Safari
reqXML = new XMLHttpRequest();
reqXML.onreadystatechange = BuildXMLResults;
reqXML.open("GET", url, true);
reqXML.send(null);
}
else if(window.ActiveXObject){ //IE

reqXML = new ActiveXObject("Microsoft.XMLHTTP");
if (reqXML) {
reqXML.onreadystatechange = BuildXMLResults;
reqXML.open("GET", url, true);
reqXML.send();
}
}
else{ //Older Browsers
alert("Your Browser does not support Ajax!");
}
}

function BuildXMLResults(){
if(reqXML.readyState == 4)
{ //completed state
if(reqXML.status == 200)
{
//session refreshed
//alert("Session refreshed");
}
}
}


http://stackoverflow.com/questions/9002607/how-to-play-rtmp-url-live-streaming-in-flowplayer
http://blog.csdn.net/peijiangping1989/article/details/7076256
https://github.com/flowplayer/flowplayer/blob/master/test/flashonly.html
http://support.netdna.com/vodzone/rtmp/


http://blog.csdn.net/defonds/article/category/1162238
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值