由于是初次接触OSGI开发,先模仿编写一个简易字典查询程序,用于理解基于OSGI的程序开发。
要求:实现一个B/S应用的简易字典查询,提供一个字典服务,用户在浏览器中输入一个单词,点击查询,给出这个单词的解释(由于是练习程序,所以仅仅支持很少单词的查询)。
有四个Bundle,分别是字典查询响应Bundle,字典查询接口Bundle,本地字典服务Bundle,远程字典服务Bundle。
下面分析介绍它们。
1.字典查询响应Bundle
提供输入要查询单词的页面,接受用户的查询请求,从 BundleContext 中获取字典服务的Service,
调用字典服务的查询接口得到查询结果,并返回结果到页面。
2.字典查询接口 Bundle
对外提供字典查询的接口。
3.本地字典服务Bundle
提供字典查询服务,是从本地的字典中查询结果。
4.远程字典服务Bundle
提供字典查询服务,是从远程的字典中查询结果。
此次主要用OSGI框架嵌入Http服务器的方式开发。
首先配置开发环境,点击Run->Run Configurations选择开发运行所需要的Bundle,注:如缺少某些Bundle请去官方网站下载http://archive.eclipse.org/equinox/drops/R-3.6.2-201102101200/
(1)完成字典查询接口Bundle工程。
创建名为DictQuery的Plug-in工程,其中注意an OSGI framework选择standard选项
然后在org.haiwi.demo.dictquery包下创建接口QueryService
package org.haiwi.demo.dictquery;
public interface QueryService {
/*
* author:Haiwi
* 输入查询word
* 返回查询结果
*/
String QueryWord(String word);
}
点击META-INF文件夹下的MANIFEST.MF文件,点击选项卡Runtime点击Exported Packages下的Add添加org.haiwi.demo.dictquery包为其他Bundle提供服务,则MANIFEST.MF文件会多出一行配置
Export-Package:org.haiwi.demo.dictquery
(2)完成本地字典查询Bundle
同(1)创建名LocalDictQuery的插件工程
导入字典查询接口Bundle,即打开LocalDictQuery工程的META-INF下的MANIFEST.MF文件选择Dependencies页签,点击Imported Packages的Add,选择org.haiwi.demo.dictquery包。
编写实现QueryService接口的类LocalDictQueryServiceImpl,实现DictQuery函数体
package org.haiwi.demo.localdictquery;
import java.util.concurrent.ConcurrentHashMap;
import org.haiwi.demo.dictquery.QueryService;
public class LocalDictQueryServiceImpl implements QueryService {
private static final ConcurrentHashMap<String,String> dict=new ConcurrentHashMap<String, String>();
static{
dict.put("test", "测试");
dict.put("china", "中国");
dict.put("LocalTest", "LocalDictQueryServiceImpl");
}
@Override
public String QueryWord(String word) {
System.out.println("start LocalDictQueryServiceImpl");
String result=dict.get(word);
if(null==result)
result="本地库中未存在!";
return result;
}
}
最后编写Activator的代码,在Bundle启动时候注册我们提供的字典查询服务,停止时卸载字典查询服务。在org.haiwi.demo.localdictquery包下建立类LocalDictQueryActivator。
package org.haiwi.demo.localdictquery;
import org.haiwi.demo.dictquery.QueryService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class LocalDictQueryActivator implements BundleActivator {
private static BundleContext context;
private ServiceRegistration sr=null;//Service注册类
static BundleContext getContext() {
return context;
}
@Override
public void start(BundleContext bundleContext) throws Exception {
System.out.println("start org.haiwi.demo.localdictquery.LocalDictQueryActivator");
LocalDictQueryActivator.context = bundleContext;
sr=context.registerService(QueryService.class.getName(), new LocalDictQueryServiceImpl(), null);
}
@Override
public void stop(BundleContext bundleContext) throws Exception {
System.out.println("end org.haiwi.demo.localdictquery.LocalDictQueryActivator");
LocalDictQueryActivator.context = null;
sr.unregister();
}
}
(3)完成实现远程字典查询Bundle。
创建工程名RemoteDictQuery,过程和LocalDictQuery类似,
其中实现代码做一下改动
package org.haiwi.demo.remotedictquery;
import java.util.concurrent.ConcurrentHashMap;
import org.haiwi.demo.dictquery.QueryService;
public class RemoteDictQueryServiceImpl implements QueryService {
private static final ConcurrentHashMap<String,String> dict=new ConcurrentHashMap<String,String>();
static{
dict.put("sky", "天空");
dict.put("computer", "计算机");
}
@Override
public String QueryWord(String word) {
System.out.println("RemoteDictQueryServiceImpl 开始");
String result=dict.get(word);
if(null==result)
result="远程库中未存在!";
return result;
}
}
(4)完成字典查询响应Bundle
首先在插件工程DictQuery的Src目录下创建page文件夹用于存放html页面,创建org.haiwi.demo.servlet包下存放对应的响应servlet,并在org.haiwi.demo.dictquery下创建Activator。
其中要引用Servlet API。同时要引入javax.servlet和javax.servlet.http两个包。
其中类QueryServiceActivator代码如下
package org.haiwi.demo.dictquery;
import org.haiwi.demo.servlet.DictQueryServlet;
import org.haiwi.demo.servlet.HelloServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
public class QueryServiceActivator implements BundleActivator {
private HttpService httpService=null;
private ServiceReference sr=null;
@Override
public void start(BundleContext context) throws Exception {
System.out.println("start org.haiwi.demo.dictqueryquery.QueryServiceActivator!");
//取得HttpService对象
sr=context.getServiceReference(HttpService.class.getName());
HttpService httpService=(HttpService)context.getService(sr);
//注册页面和对应的Servlet类
HttpContext httpContext = httpService.createDefaultHttpContext();
httpService.registerServlet("/servlet/dictquery", new DictQueryServlet(context) , null , httpContext);
httpService.registerServlet("/servlet/hello", new HelloServlet(), null, httpContext);
//
httpService.registerResources("/page", "/page", httpContext);
}
@Override
public void stop(BundleContext context) throws Exception {
System.out.println("end org.haiwi.demo.dictqueryquery.QueryServiceActivator!");
httpService.unregister("/servlet/dictquery");
httpService.unregister("/servlet/hello");
httpService.unregister("/page");
}
}
其中类DictQueryServlet代码如下
package org.haiwi.demo.servlet;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.haiwi.demo.dictquery.QueryService;
import org.osgi.framework.BundleContext;
@SuppressWarnings("serial")
public class DictQueryServlet extends HttpServlet {
public BundleContext context=null;
public DictQueryServlet(BundleContext context){
this.context=context;
}
private void ResponseWrite(HttpServletResponse response,StringBuffer resultBuff){
StringBuffer strBuff=new StringBuffer();
strBuff.append("<h1>");
strBuff.append(resultBuff);
strBuff.append("</h1>");
strBuff.append("");
strBuff.append("<a href=\"http://localhost/page/DictQuery.html\">返回查询</a>");
try {
response.getWriter().write(strBuff.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response){
StringBuffer resultBuff=new StringBuffer();
String key=request.getParameter("key");
if(null==key||"".equals(key.trim())){
resultBuff.append("查询Key值不能为空!");
}else{
QueryService queryService =(QueryService)context.getService(context.getServiceReference(QueryService.class.getName()));
String value=queryService.QueryWord(key);
resultBuff.append(" Key值:"+key);
resultBuff.append("<br />");
resultBuff.append("Result值:"+value);
}
ResponseWrite(response,resultBuff);
}
public void doPost(HttpServletRequest request,HttpServletResponse response){
doGet(request,response);
}
}
其中DictQuery.html代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>字典查询</title>
</head>
<body>
<form action="/servlet/dictquery" method="post">
请输入Key:<input type="text" name="key"/>
<input type="submit" value="查询"/>
</form>
</body>
</html>
(5)配置运行环境点击Run->Run Configurations选择如下
点击运行(下次无须配置直接点运行即可)启动Bundle服务,此时可以通过输入ss命令查看各Bundle的运行状态。
可以先输入ss命令(stop 28)停止LocalDictQuery Bundle服务,只用RemoteDictQuery Bundle服务,输入查询Key值查看结果如下
然后先输入ss命令(start 28;stop 32)开启LocalDictQuery Bundle服务,停止RemoteDictQuery Bundle服务,输入查询Key值查看结果如下