在OSGi框架下如何开发Web应用?这是个问题。OSGi框架下的Web应用运行方式可以归纳为两种:第一种,将Web容器作为一个Bundle,然后运行在OSGi框架中。第二种,将OSGi框架置于Web容器中。本系列文章以第一种运行方式为主,在系列的最后会适当的对第二种运行方式做些介绍。
第一步:打开Eclipse,新建Bundle项目HelloWorldBundle(使用Elicpse建立Bundle项目的详细过程可以参考 OSGi系列 - 用Eclipse开发Bundle)。HelloWorldBundle项目的目录结构如下图:
第二步:打开MANIFEST.MF文件,切换到Dependencies标签页,在Required Plug-ins加入两个依赖插件:javax.servlet和org.eclipse.osgi.services。javax.servlet提供了我们开发Servlet时必需的Servlet API,org.eclipse.osgi.services提供在Activator注册我们编写的Servlet时需要用到的HTTP服务。
保存MANIFEST.MF,完整的ANIFEST.MF内容如下:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloWorldBundle Bundle-SymbolicName: HelloWorldBundle Bundle-Version: 1.0.0 Bundle-Activator: helloworldbundle.Activator Import-Package: org.osgi.framework;version="1.3.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: javax.servlet;bundle-version="2.5.0", org.eclipse.osgi.services;bundle-version="3.3.0"
第三步:新建HelloServlet .java,作为我们的Servlet演示。HelloServlet .java的内容如下:
package helloworldbundle; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.osgi.framework.BundleContext; public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") private BundleContext context; public HelloServlet(BundleContext context) { this.context = context; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); int counter; if (null != session.getAttribute("counter")) { counter = (Integer) session.getAttribute("counter") + 1; } else { counter = 1; } session.setAttribute("counter", counter); response.setCharacterEncoding("GBK"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<body>"); out.println("<head>"); out.println("<title>Hello World</title>"); out.println("</head>"); out.println("<body>"); out.println("Now time: " + (new java.util.Date()) + ", Counter: " + counter); out.println("</body>"); out.println("</html>"); out.flush(); out.close(); } }
第四步:实现Activator.java,管理HelloWorldBundle的生命周期。在Activator的启动和停止方法里面,我们相应的增加和删除了一个服务监听器,用来监听Http服务的注册和卸载。当HTTP服务被注册时,同时将HelloServlet注册到HTTP服务;当HTTP服务被卸载时,同时也将HelloServlet从HTTP服务上卸载掉。Activator.java的内容如下:
package helloworldbundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; public class Activator implements BundleActivator, ServiceListener { private BundleContext ctx; private ServiceReference<HttpService> ref; public void start(BundleContext context) throws Exception { ctx = context; context.addServiceListener(this, "(objectClass=" + HttpService.class.getName() + ")"); } public void stop(BundleContext context) throws Exception { context.removeServiceListener(this); } public void serviceChanged(ServiceEvent event) { switch (event.getType()){ case ServiceEvent.REGISTERED: registerServlet(); break; case ServiceEvent.UNREGISTERING: unregisterServlet(); break; } } private void registerServlet() { if (ref == null) { ref = ctx.getServiceReference(HttpService.class); if (ref != null) { try { HttpService http = ctx.getService(ref); http.registerServlet("/demo/hello", new HelloServlet(ctx), null, null); System.out.println("/demo/hello已经被注册"); } catch (Exception e) { e.printStackTrace(); } } } } private void unregisterServlet() { if (ref != null) { try { HttpService http = ctx.getService(ref); http.unregister("/demo/hello"); System.out.println("/demo/hello已经被卸载"); ref = null; } catch(Exception e){ e.printStackTrace(); } } } }
第五步:从Elicpse菜单上选择Run >> Run Configurations...,在弹出的Run Configurations对话框左侧列表中找到OSGi Framework,点击New按钮:
在右侧Bundles列表中,选择Workspace下的HelloWordBundle项目,然后在Target Platform下选择一下项目:
- javax.servlet
- org.eclipse.osgi.services
- org.eclipse.equinox.http.servlet
- org.eclipse.equinox.http.jetty
- org.mortbay.jetty.server
- org.mortbay.jetty.util
最后点击对话框右下角的Run按钮,如果一切正常,就会出现我们熟悉的osgi>提示符:
第六步:打开浏览器,输入网址http://localhost/demo/hello,如果出现下面的画面,那么,恭喜你,成功了。
撰写本文章,特别需要感谢《OSGI实战》和《使用 Equinox 框架进行 OSGi 环境下的 Web 开发》两篇文章对我的指点,谢谢!