1 概述
Equinox 提供了两种OSGi embedded HttpSerivce的实现,如下:
- org.eclipse.equinox.http。适合资源受限的环境。兼容Servlet 2.4,但是对Servlet 2.1以外的API提供了有限的支持。
- org.eclipse.equinox.http.jetty。使用Jetty 作为引擎,支持Servlet 2.4。
- Embed a server in Equinox。
- Embed Equinox in an existing servlet container。
首先在 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:
- javax.servlet
- javax.servlet.jsp
- org.eclipse.osgi.services
- org.eclipse.equinox.http.jetty
- org.eclipse.equinox.http.servlet
- org.eclipse.equinox.http.registry
- org.eclipse.equinox.jsp.jasper
- org.eclipse.equinox.jsp.jasper.registry
- org.mortbay.jetty
- org.apache.jasper
- org.apache.commons.el
- org.apache.commons.logging
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);
}
}
}
修改MANIFEST.MF文件,在Bundle-SymbolicName: HttpServiceExample后边加上;singleton:=true,如下
Bundle-SymbolicName: HttpServiceExample;singleton:=true
5 运行
Run->Open Run Dialog,首先在弹出对话框中,单击右侧的Deselect All。然后选择:
- HttpServiceExample
- javax.servlet
- org.eclipse.osgi.services
- org.eclipse.equinox.http.jetty
- org.eclipse.equinox.http.servlet
- org.eclipse.equinox.http.registry
- org.eclipse.equinox.jsp.jasper
- org.eclipse.equinox.jsp.jasper.registry
- org.mortbay.jetty.server
- org.mortbay.jetty.util
- org.apache.jasper
- org.apache.commons.el
- org.apache.commons.logging
再单击Validate Bundles按钮,这个是检查你所导入的Bunbles有没有还存在引用其它Bunble的检查器,如果提示还缺少bundles,也就是弹出bunble的列表,则说明还有所列举的bunbles还存在依赖关系,还缺失了一些bunbles,只要点击bunble就可以看到还缺哪些,你再一个个勾选加入即可,直到提示No problems were detected,单击Run。
控制台中除了其它bundles的输出外,还应该有HttpServiceExample的输出:starting bundle...。在控制台输入ss并回车,应该看到所有的state都是ACTIVE。打开浏览器访问http://localhost/web/login.html,输入用户名user,密码123456后会进入显示hello.jsp的内容,否则会提示重新输入用户名和密码。