`
javierhui
  • 浏览: 7093 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

很久之前的osgi整理

阅读更多
研究osgi有一段时间了,一直在UI的部分没有真正做到灵活插拔,在开始跟着bluedavy(林昊)的两本opendoc<实战>与<进阶>,对osgi的理念有了一个认识,自己也做出了一个基于osgi的邮件应用,但没有真正做到页面部分的动态性。可能基础比较差吧
兴奋!!拜读了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
分享到:
评论
1 楼 shunai 2010-04-08  
谢谢!我也刚开始接触OSGi,吃力ing
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Android毕设实战项目基于Android的医院挂号系统.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    (源码)基于CC++的简易聊天室系统.zip

    # 基于CC++的简易聊天室系统 ## 项目简介 这是一个简单易用的聊天室练手项目,主要用于提高开发者对CC++与网络编程的理解。虽然该聊天室是运行在shell上的命令行程序,但项目致力于提升其易用性和用户体验,帮助CC++初学者和使用者摆脱命令行界面简陋、交互体验差的固有印象。此程序客户端和服务端一体,服务端对环境有数据库相关要求,客户端可能需安装dl库,同时引入了jsoncpp、sqlite3等第三方库。 ## 项目的主要特性和功能 ### 特性 客户端和服务端一体设计。 尽可能简化客户端操作,提高易用性。 运用菜单形式,减少用户手动输入操作。 对用户密码进行不可逆加密,保障信息安全。 ### 功能 支持用户注册、登录,可选择保存账号密码实现免密登录。 提供全局广播模式,支持私聊、群聊功能。 允许用户添加、删除好友,设置特别关心和黑名单。 能够创建群组、加入群组,并对群员进行管理。

    ITIL 术语和缩写中文(简体).pdf

    ITIL 术语和缩写中文

    毕业设计物联网实战项目基于ESP8266的三路86面板智能开关.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕设单片机实战项目基于 STM32F407+ESP8266+RFID 的模拟公交车刷卡收费系统(物联网版).zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    《人工智能在智能客服领域的应用方案》

    《人工智能在智能客服领域的应用方案》:在当今数字化时代,企业与客户之间的互动日益频繁,客户服务的质量和效率成为企业竞争的关键因素之一。传统的客服模式面临着诸多挑战,如人工客服成本高昂、工作时间受限、服务质量参差不齐、难以应对大量并发的客户咨询等问题。随着人工智能技术的飞速发展,智能客服应运而生,它能够为企业提供高效、便捷、低成本的客户服务解决方案,极大地提升客户体验和企业运营效率。无论是电商、金融、电信、教育等行业,都可以通过对客服数据的分析,优化自身的业务流程和服务质量,提升企业的竞争力。

    毕业设计物联网实战项目基于云端语音识别的智能控制设备,类似于天猫精灵,小爱同学。采用的芯片为stm32f407,wm8978,esp8266。.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    【光电技术领域】基于单片机的音乐梦幻灯与USB转接器设计:电子琴硬件组成及仿真电路实现

    内容概要:本文档是上海理工大学光电信息与计算机工程学院学生周文龙撰写的《光电融合集成电路路技术》设计报告,指导教师为隋国荣。报告分为两个部分:一是音乐梦幻灯设计,二是USB转接器仿真设计。音乐梦幻灯设计部分,以单片机为核心,通过硬件电路和软件编程实现简易电子琴,能够自动播放音乐并在电源接通时显示LED灯,详细介绍了硬件组成、原理图、元件清单及调试过程;USB转接器仿真设计部分,旨在搭建USB转接器电路,熟悉AD和嘉立创EDA等仿真平台的操作,绘制并验证电路原理图和PCB制版图,掌握焊接工艺和电路测试,为未来从事电工电子技术行业打下基础。 适合人群:电气工程、自动化、计算机等相关专业的大专院校学生,以及对单片机应用和电子电路设计感兴趣的初学者。 使用场景及目标:①学习单片机控制电子琴的原理和实现方法,包括硬件设计和软件编程;②掌握USB转接器电路的设计流程,包括原理图绘制、仿真、PCB制版图设计和电路板焊接;③提升实际动手能力和解决实际问题的能力,为未来从事相关行业打下基础。 阅读建议:本报告详细记录了设计过程中的每一个环节,包括理论知识的应用和实际操作的经验,建议读者在阅读过程中结合实际操作,逐步理解和掌握每个步骤的具体实现方法。同时,可以参考报告中提到的相关文献和工具,加深对单片机和电子电路设计的理解。

    毕设单片机实战项目基于ESP8266的可充电天气小时钟.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕业设计物联网实战项目基于PHP7的物联网管理系统ThinkIMF ,PHP IOT FRAMEWORK.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    (源码)基于C语言的简单计算器.zip

    # 基于C语言的简单计算器 ## 项目简介 这是一个基于C语言的简单计算器项目,借助命令行界面为用户提供基本数学运算功能。项目运用标准C库,无需额外依赖。 ## 项目的主要特性和功能 1. 具备命令行界面,用户可在命令行输入数字和运算符,程序负责解析并执行。 2. 支持加法、减法、乘法和除法等基本数学运算。 3. 能进行错误处理,遇到不合法输入(如非数字字符或错误运算符)时,会提示用户重新输入。 4. 采用交互式设计,用户可随时退出程序或继续计算新表达式。 ## 安装使用步骤 假设用户已下载并解压了项目的源码文件,按以下步骤操作 1. 编译源代码使用C编译器(如GCC)编译项目中的 calculator.c 文件,命令为 gcc calculator.c o calculator。 2. 运行程序在终端或命令行界面中,输入 .calculator 运行程序。 3. 输入表达式按照提示输入表达式,例如 5 + 3,然后按回车键。

    VB珠宝首饰店管理系统设计(源代码+系统+开题报告+答辩PPT).zip

    摘 要 面对信息时代的机遇与挑战,利用高科技手段来提高企业的管理水平无疑是一条行之有效的途径。利用计算机管理可以最大限度的发挥准确、快捷、高效等作用, 在越来越激烈的珠宝行业中,计算机管理技术对珠宝首饰公司的服务管理提供强有力的支持。因此,利用全新的计算机网络和珠宝首饰管理系统,已成为提高珠宝首饰公司的管理效率,改进服务水准的重要手段之一。本系统应用Visual Basic 6.0 中文版开发前台,用Microsoft Access 作后台服务器,采用客户机/服务器(C/S)管理思想来对珠宝首饰进销存管理。 关键词:管理水平, 管理效率,服务水准,珠宝首饰管理系统,客户机/服务器,管理思想

    (源码)基于C语言的调试终端及格式化输出系统.zip

    # 基于C语言的调试终端及格式化输出系统 ## 项目简介 本项目是一个基于C语言的调试终端及格式化输出系统,专为嵌入式系统或其他资源受限的环境设计。它提供了类似C标准库中printf函数的功能,支持格式化输出字符串、整数、浮点数等数据类型,适用于TI的C2000 MCU tms320f280049,使用CCS V8.1 IDE进行开发。 ## 项目的主要特性和功能 1. 调试终端初始化通过DebugTerminalInit函数初始化调试终端,配置GPIO引脚和SCIA模块,实现数据回显。 2. 格式化输出提供printf、vsprintf、vsnprintf和vscnprintf函数,支持格式化输出字符串、整数、浮点数等数据类型。 3. 数字输出number函数支持多种进制和标志位的数字格式化输出。 4. 指针地址输出pointer函数支持不同类型的指针地址格式化输出。

    机械工程PT5000汽轮机滑动轴承系统模拟试验台:动态行为与振动控制研究

    内容概要:PT5000汽轮机滑动轴承系统模拟试验台是一个类似于电厂汽轮机发电机的缩小模型,旨在帮助用户获取汽轮机转子动态行为和滑动轴承油膜现象的实际经验,并研究振动控制方法。该试验台模拟两级涡轮机(低压和中压),每级转子两侧各有8个叶片,共计16个叶片。通过电机驱动而非涡轮发电机,可以进行启停机测试,识别共振现象。试验台还支持多种实验,如不平衡/现场动平衡、轴不对中实验、摩擦实验、油膜故障试验、轴颈轴承实验以及根据油压和温度进行的转子动力学试验。试验台配备了多种传感器和控制系统,包括电涡流传感器、温度传感器、压力传感器等,用于监测和记录实验数据。 适合人群:从事汽轮机设计、制造、维护的技术人员,以及相关专业的高校师生和研究人员。 使用场景及目标:①研究汽轮机转子的动态行为和滑动轴承的油膜现象;②进行振动控制方法的研究;③模拟再现油膜涡动转和油膜震荡,研究其控制条件;④进行不平衡、不对中、摩擦等常见故障的模拟和分析;⑤通过调整油压、温度和预加载力,研究轴的行为变化。 其他说明:该试验台不仅适用于教学和科研,还可用于工业领域的培训和技术验证。试验台具有丰富的配置和可选配件,可以根据具体需求进行定制。试验台的机械和电气参数详细列出,确保用户能够全面了解设备性能。

    【更新至2023年】2000-2023年中国气候政策不确定性指数(全国、省、市三个层面)

    【更新至2023年】2000-2023年中国气候政策不确定性指数数据(全国、省、市三个层面) 1.时间:2000-2023年 2.来源:使用人工审计和深度学习算法MacBERT模型,基于中国《人民日报》《光明日报》《经济日报》《环球时报》《科技日报》《中国新闻社》等6家主流报纸中的1,755,826篇文章,构建了2000年1月至2023年12月的中国全国、省份和主要城市层面的CCPU指数。研究框架包括六个部分:数据收集、清洗数据、人工审计、模型构建、指数计算与标准化以及技术验证。 3.范围:中国、省、市三个层次 4.参考文献:Ma, Y. R., Liu, Z., Ma, D., Zhai, P., Guo, K., Zhang, D., & Ji, Q. (2023). A news-based climate policy uncertainty index for China. Scientific Data, 10(1), 881. 5.时间跨度:全国层面:日度、月度、年度;省级层面:月度、年度;地级市层面:月度、年度

    Android毕设实战项目pc+android 教务询查系统.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    【telesky旗舰店】ACS712 5-30A通用.zip

    【telesky旗舰店】ACS712 5-30A通用.zip

    (源码)基于GD32F30x微控制器的USB设备驱动程序.zip

    # 基于GD32F30x微控制器的USB设备驱动程序 ## 项目简介 本项目聚焦于GD32F30x微控制器,开发了一套USB设备驱动程序,可实现USB设备的初始化、配置、数据传输以及中断处理等功能,涵盖主机模式下的枚举过程管理与设备模式的数据传输及中断处理。 ## 项目的主要特性和功能 1. USB设备驱动支持GD32F30x微控制器的USB设备模式,能完成设备初始化、端点配置、数据传输和中断处理等操作。 2. 枚举过程管理在主机模式下,对USB设备的枚举过程进行管理,包含获取设备描述符、设置地址和配置等步骤。 3. 数据传输支持USB设备的数据接收和发送。 4. 中断处理处理USB设备的各类中断事件,如传输完成、挂起、唤醒等。 5. 电源管理具备设备的挂起和唤醒等电源管理功能。 ## 安装使用步骤 1. 环境准备确保已安装GD32F30x微控制器的开发环境,包含IDE和必要的驱动库。 2. 代码下载从指定路径下载USB设备驱动代码。

    房地产开发行业深度:商业地产REITs支持文件落地,助推存量盘活提振消费-20230513-国信证券-49页.pdf

    房地产开发行业深度:商业地产REITs支持文件落地

Global site tag (gtag.js) - Google Analytics