1 概述
Equinox 提供了两种OSGi embedded HttpSerivce的实现,如下:
本文以使用org.eclipse.equinox.http.jetty为例,介绍一下通过Eclipse3.3.1.1编写基于bundles的web应用程序。有两种方式在Equinox中运行HTTP Server,如下(本文采用第一种方式):
2 创建工程
首先在Eclipse中新建一个新工程,New->Project->Plug-in Development->Plug-in Project,单击Next按钮;输入工程名:HttpServiceExample。在Target Platform中选择an OSGi framework单选按钮,同时在右边的下拉框中选择standard,单击Next按钮;在Classpath中输入bin,在Activator 中输入com.example.http.service.Activator,单击Next按钮;单击Finish按钮。
用Plug-in Manifest Editor打开工程META-INF目录下的MANIFEST.MF文件。选择Dependencies标签,单击Required Plug-ins下的Add按钮。在弹出的对话框中选择以下plug-in:
3 新建web资源
在工程的com.example.http.service包中应该已经生成了一个Activator类,为其添加两条控制台输出并注册资源。需要注意的是,BundleEntryHttpContext.java和ContextPathServletAdaptor.java是在名为org.eclipse.equinox.http.helper的bundle中,而这个bundle需要到eclipse cvs下载。为了方便读者,笔者将两个类的源码下载并保存到com.example.http.service.helper包中。
package com.example.http.service; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.eclipse.equinox.jsp.jasper.JspServlet; 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; import com.example.http.service.helper.BundleEntryHttpContext; import com.example.http.service.helper.ContextPathServletAdaptor; import com.example.http.service.helper.FilterServletAdaptor; public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { System.out.println("starting bundle..."); ServiceReference sr = context.getServiceReference(HttpService.class.getName()); HttpService hs = (HttpService) context.getService(sr); HttpContext hc = new BundleEntryHttpContext(context.getBundle(), "/web"); hs.registerResources("/jsp", "/", hc); Servlet jspServlet = new ContextPathServletAdaptor( new JspServlet(context.getBundle(), "/web/"), "/jsp"); hs.registerServlet("/jsp/*.jsp", jspServlet, null, hc); // Filter 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); } public void stop(BundleContext context) throws Exception { System.out.println("stoping bundle..."); ServiceReference sr = context.getServiceReference(HttpService.class.getName()); HttpService hs = (HttpService) context.getService(sr); hs.unregister("/web"); hs.unregister("/jsp"); } }
另外再新建一个LoginServlet,如下:
package com.example.http.service; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet { /** * */ private static final long serialVersionUID = -1300648117298008054L; /** * */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // String user = request.getParameter("user"); String password = request.getParameter("password"); if("user".equals(user) && "123456".equals(password)) { request.setAttribute("message", "hello " + user); RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/jsp/hello.jsp"); dispatcher.forward(request, response); } else { RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/web/login.html"); dispatcher.forward(request, response); } } }
在工程根目录下新建一个web目录,在其中新建一个login.html如下:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Login</title> </head> <body> <br> <form name="loginForm" method="post" action="/login"> <table> <tr> <td><div align="right">User Name:</div></td> <td><input type="text" name="user"></td> </tr> <tr> <td><div align="right">Password:</div></td> <td><input type="password" name="password"></td> </tr> <tr> <td></td> <td><input type="Submit" name="Submit" value="Submit"></td> </tr> </form> </body> </html>
再新建一个hello.jsp,如下:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>hello</title> </head> <body> <h2><%=request.getAttribute("message") %></h2> </body> </html>
4 扩展点
在工程根目录下新建一个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>
修改MANIFEST.MF文件,在Bundle-SymbolicName: HttpServiceExample后边加上;singleton:=true,如下
Bundle-SymbolicName: HttpServiceExample;singleton:=true
5 运行
Run->Open Run Dialog,首先在弹出对话框中,单击右侧的Deselect All。然后选择:
再单击Validate Bundles按钮,如果提示还缺少bundles,那么就根据提示添加bundles。直到提示No problems were detected,单击Run。
控制台中除了其它bundles的输出外,还应该有HttpServiceExample的输出:starting bundle...。在控制台输入ss并回车,应该看到所有的state都是ACTIVE。打开浏览器访问http://localhost/web/login.html,输入用户名user,密码123456后会进入显示hello.jsp的内容,否则会提示重新输入用户名和密码。