java web组件开发osgi与jsp

来源:互联网 发布:肩扛摄像机和dv知乎 编辑:程序博客网 时间:2024/04/29 12:04

在前一篇文章中,通过OSGi(Open Services Gateway Initiative)的热插拔特性,我们已经窥见了OSGi在Java Web开发中的一些优势。但是因为OSGi是最早为嵌入式系统设计,所以OSGi标准中的HTTP服务只提供了有限的Servlet与静态资源的发布功能,没有一个完整的WEB容器概念,这种模式更适合通过WEB方式暴露(Export)服务,不太适合开发展现层的WEB应用。这也是导致很多公司很少涉足这个领域的很大因素。在这份文档中,用一个简单的例子来说明如何在使用JSP以及使用JSTL等标签库的情况下应用OSGi开发基于组建的Web应用。

 

1. 创建plug-in工程osgi_jsp_test


2. 在工程的根目录下创建"web"目录,并在其中增加WEB-INF文件夹。


3. 建立web.xml文件,内容如下:

Xml代码 复制代码
  1. <?xml version="1.0" encoding="ISO-8859-1"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
  5.     version="2.4">  
  6.     <description>JSP 2.0 Examples.</description>  
  7.     <display-name>JSP 2.0 Examples</display-name>  
  8. </web-app>  

 

 

 

4.编写JSP,内容如下
 foreach.jsp

Html代码 复制代码
  1. <html>  
  2. <head>  
  3. <title>Tag Plugin Examples: forEach</title>  
  4. </head>  
  5. <body>  
  6. <!-- 例子一 -->  
  7. <!-- forEach标签示例 -->  
  8.     <h1>Tag Plugin Examples - <c:forEach></h1>  
  9.     <hr><font color="#000000"/></br>  
  10.     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
  11.     <%@ page import="java.util.Vector" %>  
  12.     <h3>Iterating over a range</h3>  
  13.     <c:forEach var="item" begin="1" end="100">  
  14.     ${item}        
  15.     </c:forEach>  
  16.     <%   
  17.     Vector v = new Vector();   
  18.     v.add("One");   
  19.     v.add("Two");   
  20.     v.add("Three");   
  21.     v.add("Four");   
  22.     pageContext.setAttribute("vector", v);   
  23.     %>  
  24.     <h3>Iterating over a Vector</h3>  
  25.     <c:forEach items="${vector}" var="item" >  
  26.     ${item}        
  27.     </c:forEach>  
  28.   
  29. <!-- 例子二 -->  
  30. <!-- c:if标签示例 -->  
  31.     <h1>Tag Plugin Examples - <c:if></h1><hr>  
  32.     <font color="#000000"/>  
  33.     </br>  
  34.     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
  35.     <h3>Set the test result to a variable</h3>  
  36.     <c:if test="${1==1}" var="theTruth" scope="session"/>  
  37.     The result of testing for (1==1) is: ${theTruth}   
  38.     <h3>Conditionally execute the body</h3>  
  39.     <c:if test="${2>0}">  
  40.     It's true that (2>0)!   
  41.     </c:if>  
  42.   
  43. <!-- 例子三 -->  
  44. <!-- choose示例 -->  
  45.     <h1>Tag Plugin Examples - <c:choose></h1>  
  46.     <hr></br>  
  47.     <font color="#000000"/></br>  
  48.     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
  49.     <c:forEach var="index" begin="0" end="4"># ${index}:   
  50.     <c:choose>  
  51.         <c:when test="${index == 1}">One!</br></c:when>  
  52.         <c:when test="${index == 4}">Four!</br></c:when>  
  53.         <c:when test="${index == 3}">Three!</br></c:when>  
  54.         <c:otherwise>Danlley?</br></c:otherwise>  
  55.     </c:choose>  
  56.     </c:forEach>  
  57. </body>  
  58. </html>   

 

 

 

5. 编辑配置文件

 ---------------------------------------------------
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: Osgi_jsp_test Plug-in
 Bundle-SymbolicName: osgi_jsp_test
 Bundle-Version: 1.0.0
 Bundle-ClassPath: target/classes/,
  lib/jstl.jar,
  lib/standard.jar
 Bundle-Activator: org.danlley.osgi.jsp.common.Activator
 Import-Package: org.osgi.framework;version="1.3.0"
 Require-Bundle: javax.servlet,
  javax.servlet.jsp,
  org.mortbay.jetty,
  org.apache.commons.logging,
  org.apache.commons.el,
  org.apache.jasper,
  org.eclipse.equinox.http.registry,
  org.eclipse.equinox.http.helper,
  org.eclipse.equinox.http.jetty,
  org.eclipse.equinox.http.servlet,
  org.eclipse.equinox.jsp.jasper,
  org.eclipse.equinox.jsp.jasper.registry,
  org.eclipse.equinox.registry,
  org.eclipse.equinox.common,
  org.eclipse.equinox.app,
  org.eclipse.osgi,
  org.eclipse.osgi.util,
  org.eclipse.osgi.services,
  org.eclipse.core.commands,
  org.eclipse.core.jobs
 ---------------------------------------------------

 

 

 

6. 修改Activator类
 注,由于Bundle可以在任何时候安装,启动,停止或卸载,所以使用其他Bundle提供的服务时,必须跟踪这些服务的状态。如果在一个Bundle中需要使用其他Bundle提供的服务,则需要在考虑服务不存在或突然被注销的情形。由于OSGi环境是一个动态的环境,如果使用一个服务,可以使用ServiceTracker对该服务进行跟踪。我们在这里使用一下ServiceTracker,在OSGi提供的接口中,对ServiceTracker提供了四种对象初始化方式:

 

Java代码 复制代码
  1. import org.osgi.framework.BundleContext;   
  2. import org.osgi.framework.ServiceReference;   
  3. import org.osgi.util.tracker.ServiceTrackerCustomizer;   
  4. import org.osgi.framework.Filter;   
  5.   
  6. public ServiceTracker(BundleContext context,ServiceReference reference,ServiceTrackerCustomizer    
  7. customizer);   
  8.   
  9. public ServiceTracker(BundleContext context,String clazz,ServiceTrackerCustomizer customizer);   
  10.   
  11. public ServiceTracker(BundleContext context,Filter filter,ServiceTrackerCustomizer customizer);  

 

 BundleContext是一个OSGi框架与Bundle之间进行交互的一个结合点。当代码需要在任何时候与框架交互时,你将用到BundleContext。事实上这是用OSGi API交互的唯一方法,并且在框架启动Bundle的时候时,每个Bundle的Activator都会接收到BundleContext的实例。

 OSGi中services总是通过ServiceReference来访问的,他唯一对应一个service对象要访问的一个服务,以下步骤是必须的:
  1)。获取ServiceReference引用
  2)。通过BundleContext.getService()获取服务对象实例

Java代码 复制代码
  1. final HttpService httpService = (HttpService) context.getService(reference);  

 

 

 

 ServiceTrackCustomer是由OSGi提供的一个用于监控服务的接口类,当在OSGi里面注册,修改,反注册一个Service的时候,OSGi会调用ServiceTrackCustomer的方法addingService, modifiedService, removedService. 关于这个方面的示例,我想应该可以在我的另外一篇文章《管窥Java开发中OSGi组件的热插拔》中找到:http://danlley.javaeye.com/blog/218676

 

 

 接下来,实现Activator类,由于我们需要执行JSP页面,因此就需要在系统中加载JspServlet,为此,我们需要复写在类中实现的一个成员方法:

 

Java代码 复制代码
  1. public java.lang.Object addingService(org.osgi.framework.ServiceReference reference);  

 

实现如下:

Java代码 复制代码
  1. public Object addingService(ServiceReference reference) {   
  2.     final HttpService httpService = (HttpService) context.getService(reference);   
  3.     try {   
  4.         System.out.println("开始注册JspServlet");   
  5.         HttpContext commonContext = new BundleEntryHttpContext(context.getBundle(),    
  6.         "/web");    
  7.         httpService.registerResources("/jsp-examples""/", commonContext);   
  8.         Servlet adaptedJspServlet = new ContextPathServletAdaptor(new    
  9.         JspServlet(context.getBundle(), "/web"), "/jsp-examples");    
  10.         httpService.registerServlet("/jsp-examples/*.jsp", adaptedJspServlet, null,    
  11.         commonContext);    
  12.         System.out.println("JspServlet注册结束");   
  13.     } catch (Exception e) {   
  14.         // TODO Auto-generated catch block   
  15.         e.printStackTrace();   
  16.     }   
  17.     return httpService;   
  18. }  

 

 

 HttpService 通过这样的方法来注册资源文件:HttpService.registerResources(资源 Mapping Url,资源文件路径, HttpContext 实例);


 示例:service.registerResources("/demo/page","page",null);

 

构建HttpContext实例,org.eclipse.equinox.http.helper项目为我们已经做好了一个构建HttpContext实例的类,并提供了两个构造方法:

Java代码 复制代码
  1. public BundleEntryHttpContext(Bundle bundle);   
  2. public BundleEntryHttpContext(Bundle b, String bundlePath);  

 

 

HttpContext接口的定义如下:

 

 

Java代码 复制代码
  1. public abstract interface org.osgi.service.http.HttpContext {   
  2.     public static final java.lang.String REMOTE_USER = "org.osgi.service.http.authentication.remote.user";   
  3.     public static final java.lang.String AUTHENTICATION_TYPE = "org.osgi.service.http.authentication.type";   
  4.     public static final java.lang.String AUTHORIZATION = "org.osgi.service.useradmin.authorization";   
  5.     public boolean handleSecurity(javax.servlet.http.HttpServletRequest arg0,    
  6.     javax.servlet.http.HttpServletResponse arg1)throws java.io.IOException;   
  7.     public java.net.URL getResource(java.lang.String arg0);   
  8.     public java.lang.String getMimeType(java.lang.String arg0);   
  9. }  

 

 

 

 在BundleEntryHttpContext对HttpContext接口的实现过程时,如果我们采用的是第二种方式(传入BundlePath),在调用getResource()方法时,resourceName就会加上BundlePath作为路径前缀。

 

 

 适配器ContextPathServletAdaptor事实上是对javax.servlet.Servlet接口的一个实现。Servlet接口定义如下: 

 

Java代码 复制代码
  1. public abstract interface javax.servlet.Servlet {   
  2.     public abstract void init(javax.servlet.ServletConfig arg0) throws    
  3.         javax.servlet.ServletException;   
  4.     public abstract javax.servlet.ServletConfig getServletConfig();   
  5.     public abstract void service(javax.servlet.ServletRequest arg0,    
  6.         javax.servlet.ServletResponse arg1) throws    
  7.         javax.servlet.ServletException, java.io.IOException;   
  8.     public abstract java.lang.String getServletInfo();   
  9.     public abstract void destroy();   
  10. }  

 

 

Eclipse的org.eclipse.equinox.http.servlet项目对OSGi的HttpService做了一个实现类HttpServiceImpl,通过他提供的registerServlet接口实现,我们就可以将JspServlet注册到我们的OSGi环境中。HttpServiceImpl的接口实现声明如下 

 

Java代码 复制代码
  1. public class org.eclipse.equinox.http.servlet.internal.HttpServiceImpl implements org.osgi.service.http.HttpService {   
  2.     private org.osgi.framework.Bundle bundle;   
  3.     private org.eclipse.equinox.http.servlet.internal.ProxyServlet proxy;   
  4.     java.util.Set aliases;   
  5.   
  6.     public HttpServiceImpl(org.osgi.framework.Bundle bundle,    
  7.         org.eclipse.equinox.http.servlet.internal.ProxyServlet proxy);   
  8.     public synchronized void unregisterAliases();   
  9.     public synchronized void registerServlet(java.lang.String alias, javax.servlet.Servlet servlet,    
  10.         java.util.Dictionary initparams, org.osgi.service.http.HttpContext context) throws    
  11.         javax.servlet.ServletException, org.osgi.service.http.NamespaceException;   
  12.     public synchronized void registerResources(java.lang.String alias, java.lang.String name,    
  13.         org.osgi.service.http.HttpContext context) throws org.osgi.service.http.NamespaceException;   
  14.     public synchronized void unregister(java.lang.String alias);   
  15.     public org.osgi.service.http.HttpContext createDefaultHttpContext();   
  16. }  

 

 

  下面给出Activator类代码的完整实现,代码如下:


 Activator.java

 

Java代码 复制代码
  1. package org.danlley.osgi.jsp.common;   
  2.   
  3.   
  4. import javax.servlet.Servlet;   
  5.   
  6. import org.eclipse.equinox.http.helper.BundleEntryHttpContext;   
  7. import org.eclipse.equinox.http.helper.ContextPathServletAdaptor;   
  8. import org.eclipse.equinox.jsp.jasper.JspServlet;   
  9. import org.osgi.framework.BundleActivator;   
  10. import org.osgi.framework.BundleContext;   
  11. import org.osgi.framework.ServiceReference;   
  12. import org.osgi.service.http.HttpContext;   
  13. import org.osgi.service.http.HttpService;   
  14. import org.osgi.util.tracker.ServiceTracker;   
  15.   
  16. public class Activator implements BundleActivator {   
  17.   
  18.     private ServiceTracker httpServiceTracker;   
  19.   
  20.     public void start(BundleContext context) throws Exception {   
  21.         httpServiceTracker = new HttpServiceTracker(context);   
  22.         httpServiceTracker.open();   
  23.     }   
  24.   
  25.     public void stop(BundleContext context) throws Exception {   
  26.         httpServiceTracker.open();   
  27.     }   
  28.   
  29.     private class HttpServiceTracker extends ServiceTracker {   
  30.   
  31.         public HttpServiceTracker(BundleContext context) {   
  32.             super(context, HttpService.class.getName(), null);   
  33.         }   
  34.   
  35.         public Object addingService(ServiceReference reference) {   
  36.             final HttpService httpService = (HttpService) context.getService(reference);   
  37.             try {   
  38.                 System.out.println("开始注册JspServlet");   
  39.                 HttpContext commonContext = new BundleEntryHttpContext(context.getBundle(),    
  40.                 "/web");    
  41.                 httpService.registerResources("/jsp-examples""/", commonContext);   
  42.                 Servlet adaptedJspServlet = new ContextPathServletAdaptor(new    
  43.                 JspServlet(context.getBundle(), "/web"), "/jsp-examples");    
  44.                 httpService.registerServlet("/jsp-examples/*.jsp", adaptedJspServlet, null,    
  45.                 commonContext);    
  46.                 System.out.println("JspServlet注册结束");   
  47.             } catch (Exception e) {   
  48.                 // TODO Auto-generated catch block   
  49.                 e.printStackTrace();   
  50.             }   
  51.             return httpService;   
  52.         }   
  53.   
  54.         public void removedService(ServiceReference reference, Object service) {   
  55.             final HttpService httpService = (HttpService) service;   
  56.             httpService.unregister("/jsp-examples");    
  57.             httpService.unregister("/jsp-examples/*.jsp");    
  58.             super.removedService(reference, service);   
  59.         }   
  60.     }   
  61. }  

 

 

7.启动服务
 ----------------------------------------------------------------------------
 osgi> Jul 25, 2008 4:51:00 PM org.mortbay.http.HttpServer doStart
 INFO: Version Jetty/5.1.x
 Jul 25, 2008 4:51:00 PM org.mortbay.util.Container start
 INFO: Started org.mortbay.jetty.servlet.ServletHandler@10f6d3
 Jul 25, 2008 4:51:00 PM org.mortbay.util.Container start
 INFO: Started HttpContext[/,/]
 Jul 25, 2008 4:51:00 PM org.mortbay.http.SocketListener start
 INFO: Started SocketListener on 0.0.0.0:80
 Jul 25, 2008 4:51:00 PM org.mortbay.util.Container start
 INFO: Started org.mortbay.http.HttpServer@1adc30
 开始注册JspServlet
 JspServlet注册结束
 ss

 Framework is launched.

 id State       Bundle
 0 ACTIVE      org.eclipse.osgi_3.3.2.R33x_v20080105
 1 ACTIVE      javax.servlet_2.4.0.v200706111738
 3 ACTIVE      org.eclipse.equinox.jsp.jasper.registry_1.0.0.v20070607
 4 ACTIVE      org.eclipse.core.jobs_3.3.1.R33x_v20070709
 5 ACTIVE      javax.servlet.jsp_2.0.0.v200706191603
 6 ACTIVE      org.apache.commons.logging_1.0.4
 7 ACTIVE      org.apache.commons.logging_1.0.4.v200706111724
 8 ACTIVE      org.eclipse.equinox.http.helper_1.0.0.qualifier
 9 ACTIVE      org.eclipse.osgi.services_3.1.200.v20070605
 10 ACTIVE      org.eclipse.equinox.jsp.jasper_1.0.100.qualifier
 11 ACTIVE      org.eclipse.core.commands_3.3.0.I20070605-0010
 12 ACTIVE      org.eclipse.equinox.http.registry_1.0.1.R33x_v20071231
 13 ACTIVE      org.apache.commons.el_1.0.0.v200706111724
 14 ACTIVE      org.eclipse.equinox.common_3.3.0.v20070426
 15 ACTIVE      org.eclipse.equinox.http.jetty_1.0.1.R33x_v20070816
 16 ACTIVE      org.eclipse.equinox.app_1.0.1.R33x_v20070828
 17 ACTIVE      org.mortbay.jetty_5.1.11.v200706111724
 18 ACTIVE      org.eclipse.equinox.http.servlet_1.0.1.R33x_v20070816
 19 ACTIVE      org.eclipse.equinox.registry_3.3.1.R33x_v20070802
 21 ACTIVE      org.apache.jasper_5.5.17.v200806031609
 24 ACTIVE      org.eclipse.osgi.util_3.1.200.v20070605
 32 ACTIVE      osgi_jsp_test_1.0.0
 ----------------------------------------------------------------------------

原创粉丝点击