目录

概览
安装和启动
一些便利的命令
Tasklist - 一个小的OSGI应用
父pom和通用工程的设置
Tasklist-model
Tasklist-persistence
Tasklist-ui
Tasklist-features
在Karaf中安装应用
总结
参考文献

概览

以这篇文章为起点,我将开始写一系列关于Apache Karaf的文章,Apache Karaf是一个基于Equinox或者Felix框架开发的一个OSGI容器。
与这些框架最大的不同在于它带来了优秀的管理功能。

Karaf突出的特性如下:
- 可扩展控制台和Bash相似的命令补齐功能
- ssh控制台
- 从maven仓库中获取bundles和features的部署文件
- 可以在命令行中轻松的创建一个新的实例

所有这些特性使开发服务端OSGi应用和开发一般的java应用几乎一样的简单。
从某个层面上,部署和管理比目前我知道所有应用服务器都好。所有这些karaf特性的结合带来了最终的程序。在我看来,Karaf允许轻量级的开发风格就像J2EE结合spring应用程序的灵活性一样。

安装和启动

  • karaf官网下载Karaf4.0.7。
  • 解压并运行bin/karaf。

一些便利的命令

命令描述
la显示所有安装的bundle
list显示用户的bundle
service:list显示active的OSGI服务。这个列表十分长。这里有一个方便的方法,就是你可以使用unix的管道,如 “ls
exports显示导出的packages和bundles,这个命令可以帮助你查找出package是来自哪里
feature:list显示所有feature包括已安装和未安装的
feature:install webconsole访问http://localhost:8181/system/console,用karaf/karaf登录并花些时间看下它所提供的信息
diag显示那些无法启动的bundle的诊断信息
log:tail显示日志。可以按ctrl-c返回控制台
Ctrl-d退出控制台。如果是主控制台,则karaf被关闭
  • 重启后OSGI容器会保存状态

    注意Karaf和其他所有的OSGI容器一样会维护已安装和已启动的bundles的最后状态。所以如果有些组件再也不能工作,重启也不一定有所帮助。为了启动一个全新的Karaf,可以停止karaf然后删除data目录或者启动的时候加个clean参数bin/karaf clean。

  • 检查日志

    Karaf运行的时候非常安静。为了不错过错误消息,可以运行tail -f data/karaf.log让日志文件处于打开状态。

Tasklist - 一个小的OSGI应用

没有任何有用的应用,Karaf是一个很棒但是没用的容器。所以让我们来创建第一个应用吧。好消息是创建一个OSGI应用非常的简单,maven会处理很多事情。和一个正常的maven工程的差异是非常少的。我推荐使用Eclipse 4写应用程序,Eclipse 4默认已经安装m2eclipse插件。

从github的Karaf-Tutorial仓库中获取源码。

git clone https://github.com/cschneider/Karaf-Tutorial.git

或者从 https://github.com/cschneider/Karaf-Tutorial/zipball/master 下载示例工程,然后解压到某个目录下。

导入到Eclipse
- 启动Eclipse Neon或者更新版本。
- 在Eclipse中选择File -> Import -> Existing maven project -> Browse到刚才解压的目录选择tasklist 子文件夹。
- Eclipse将显示所有它找到的maven工程。
- 单击默认导入所有工程。

Eclipse将导入所有的工程并使用m2eclipse插件管理它们之间所有的依赖。

tasklist有以下这些工程组成。

模块描述
tasklist-model服务接口和Task类
tasklist-persistence提供了一个TaskService接口的简单持久化实现
tasklist-ui使用TaskService显示任务列表的servlet
tasklist-features为应用提供features的描述信息,使应用能够很容易的安装到Karaf容器中

父pom和通用工程的设置

pom.xml打包bundle,而maven-bundle-plugin创建具有OSGi Manifest信息的jar包。默认情况,插件导入java文件import的或者在bluneprint上下文引用的所有的包。同时导出不包含内部实现的所有包。在我们的例子中我们想要model包被导入,但是persistence的实现包不导入。按照命名约定,我们不需要额外的配置。

Tasklist-model

这个工程包含domain model,这里指Task类和TaskService接口。model同时被persistence工程和用户界面工程使用。任意TaskService服务的使用者只需要依赖model工程。所以不用直接绑定到当前的实现。

Tasklist-persistence

简单持久化实现的TaskServiceImpl类用一个简单的HashMap管理task。类用@Singleton注解标记自己为blueprint bean。注解@OsgiServiceProvider用于标记为自己是一个OSGi服务,而@Properties注解允许添加服务属性。在这个例子中我们设置的属性service.exported.interfaces可以被我们在后续的教程要介绍的CXF-DOSGI使用。目前该教程这个属性可以删除。

@OsgiServiceProvider
@Properties(@Property(name = "service.exported.interfaces", value = "*"))
@Singleton
public class TaskServiceImpl implements TaskService {
    ...
}

blueprint-maven-plugin插件将处理上面的类,且自动创建合适的blueprint xml文件。这样可以帮我们节省手动写blueprint xml文件的时间。

自动创建的blueprint xml文件位于target/generated-resources文件夹下

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
    <bean id="taskService" class="net.lr.tasklist.persistence.impl.TaskServiceImpl" />
    <service ref="taskService" interface="net.lr.tasklist.model.TaskService" />
</blueprint>

Tasklist-ui

UI工程使用一个TaskServlet显示任务列表和单独的任务。为了和tasks任务协作,这个servlet需要TaskService服务。我们通过使用注解@Inject和@OsgiService注入TaskService服务,@Inject注解能够根据类型注入任意的实例。而注解@OsgiService将创建一个指定类型的OSGiSerivce服务的blueprint引用。(译注:这里我是这么理解的,@OsgiService表示从Karaf中获取一个bean,@Inject则负责注入)
这个类被暴露为一个OSGi服务,该类是一个有特别属性alias=/tasklist的接口java.http.Servlet实现。这样做触发了pax web的whiteboard扩展器接收这个服务,并使用url /tasklist映射到该servlet。

相关代码小片段

@OsgiServiceProvider(classes = Servlet.class)
@Properties(@Property(name = "alias", value = "/tasklist"))
@Singleton
public class TaskListServlet extends HttpServlet {

    @Inject @OsgiService
    TaskService taskService;
}

自动创建的blueprint xml文件位于target/generated-resources文件夹下

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
    <reference id="taskService" availability="mandatory" interface="net.lr.tasklist.model.TaskService" />
    <bean id="taskServlet" class="net.lr.tasklist.ui.TaskListServlet">
        <property name="taskService" ref="taskService"></property>
    </bean>
    <service ref="taskServlet" interface="javax.servlet.http.HttpServlet">
        <service-properties>
            <entry key="alias" value="/tasklist" />
        </service-properties>
    </service>
</blueprint>

Tasklist-features

最后一个工程仅安装一个feature描述信息文件到一个maven仓库,这样我们可以很容易的安装应用到Karaf。描述信息定义了一个叫tasklist的feature和将从maven仓库下载安装的bundles

<feature name="example-tasklist-persistence" version="${pom.version}">
    <bundle>mvn:net.lr.tasklist/tasklist-model/${pom.version}</bundle>
    <bundle>mvn:net.lr.tasklist/tasklist-persistence/${pom.version}</bundle>
</feature>

<feature name="example-tasklist-ui" version="${pom.version}">
    <feature>http</feature>
    <feature>http-whiteboard</feature>
    <bundle>mvn:net.lr.tasklist/tasklist-model/${pom.version}</bundle>
    <bundle>mvn:net.lr.tasklist/tasklist-ui/${pom.version}</bundle>
</feature>

一个feature可以由其他features和bundles组成,这些features和bundles也应该被安装。一般bundles使用mvn urls。这也意味着它们从配置好的仓库或者你的本地maven仓库~/.m2/repository中加载。

在Karaf中安装应用

feature:repo-add mvn:net.lr.tasklist/tasklist-features/1.0.0-SNAPSHOT/xml
feature:install example-tasklist-persistence example-tasklist-ui

添加features描述信息文件到Karaf,所以它被添加到可用的features列表中,然后安装和启动tasklist feature。运行命令之后tasklist应用应该运行了。

list

检查tasklist的所有bundles是在active状态。如果没有,尝试启动它们和检查日志。

http:list

ID | Servlet         | Servlet-Name   | State       | Alias     | Url
-------------------------------------------------------------------------------
56 | TaskListServlet | ServletModel-2 | Deployed    | /tasklist | [/tasklist/*]

应该显示TaskListServlet。默认情况下这个例子应该运行在http://localhost:8181/tasklist

你可以通过创建一个文本文件”etc/org.ops4j.pax.web.cfg”改变端口。文本内容为”org.osgi.service.http.port=8080”。这个方式将告诉HttpService使用这个端口8080. 现在tasklist应用应该运行在http://localhost:8080/tasklist地址。

总结

在该教程中我们已经安装了Karaf和学习了一些命令。然后我们创建了一个小的OSGi应用,这个应用涉及到servlets,OSGi服务,blueprint和whiteboard模式。下一个教程我们看下在OSGi中Apache Camel和Apache CXF的使用。

参考文献

Karaf Tutorial Part 1 - Installation and First application


myqrcode

下一篇 Karaf教程之Config Admin服务的使用

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐