程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> 打造一個Hello World OSGi Web應用程序

打造一個Hello World OSGi Web應用程序

編輯:J2EE

【51CTO精選譯文】在《你好,OSGi》的之前一篇文章中,我們介紹了OSGi Web應用開發工具Equinox的配置方法,在這一篇中,我們會進行Hello World OSGi Web應用程序的開發。該練習中的應用程序是一個包含了兩個資源的 OSGi 套件。第一個是 helloworld.html,它是一個靜態的 Html 文件;第二個是 HelloWorldServlet,它是一個 HttpServlet。有一個重點需注意,OSGi 容器提供 HttpService 服務。每個想要處理 HTTP 請求的套件都將調用該服務上的方法來通知 OSGi 容器它能夠處理哪些 URL。將 URL 注冊為 OSGi 套件可處理,存在兩種方式:

51CTO編輯推薦:OSGi入門與實踐全攻略

程序方式:首選檢索來自 OSGi 的服務寄存器 HttpService,然後調用其上的方法將請求 URL 注冊為套件可處理。

聲明方式:在 plugin.XML 文件中定義套件可處理的請求 URL。

我們將一步一步地對這些技巧進行講解,先從程序注冊方式開始。

程序注冊方式

按照下面的步驟,可使用程序方式將 URL 注冊為插件可處理。

你首先應做的是參加一個新的 OSGi 插件,命名為com.Javaworld.sample.osgi.web.programmatic。(有關在 Eclipse 中創建 OSGi 插件的更多信息,請查閱本系列的第一節。)

打開 com.javaworld.sample.osgi.web.programmatic 的 MANIFEST.MF 文件並對其進行修改,導入 javax.servlet, Javax.servlet.http, org.osgi.service.http 和org.osgi.util.tracker 包。更改完成之後,你的 MANIFEST.MF 應如列表 3 類似。

列表 3. 程序式插件的 MANIFEST.MF 文件

  1. Manifest-Version: 1.0
  2. Bundle-ManifestVersion: 2
  3. Bundle-Name: Webapp Plug-in
  4. Bundle-SymbolicName: com.Javaworld.sample.osgi.web.programmatic
  5. Bundle-Version: 1.0.0
  6. Bundle-Activator: com.Javaworld.sample.osgi.web.webapp.Activator
  7. Bundle-Vendor: JavaWORLD
  8. Bundle-Localization: plugin
  9. Import-Package: Javax.servlet;version="2.4.0",
  10. Javax.servlet.http;version="2.4.0",
  11. org.osgi.framework;version="1.3.0",
  12. org.osgi.service.http;version="1.2.0",
  13. org.osgi.util.tracker;version="1.3.2"

如你所見,Import-Package 清單頭的值定義了你需要導入的包列表。

在插件的根目錄創建一個簡單的 helloworld.html 文件,如列表 4 所示。該文件用來顯示消息“Hello From helloworld.Html”。

列表 4. helloworld.Html

  1. < !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/Html4/loose.dtd">
  2. < Html>
  3. < head>
  4. < meta http-equiv="Content-Type" content="text/Html; charset=ISO-8859-1">
  5. < title>HelloWorld OSGi Web< /title>
  6. < /head>
  7. < body>
  8. < h3>Hello From helloworld.Html< /h3>
  9. < /body>
  10. < /Html>

下一步,創建如列表 5 所示的 HelloWorldServlet。

列表 5. HelloWorldServlet

  1. package com.Javaworld.sample.osgi.web.webapp;
  2. import Java.io.IOException;
  3. import Javax.servlet.ServletException;
  4. import Javax.servlet.http.HttpServlet;
  5. import Javax.servlet.http.HttpServletRequest;
  6. import Javax.servlet.http.HttpServletResponse;
  7. public class HelloWorldServlet extends HttpServlet{
  8. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9. resp.setContentType("text/Html");
  10. resp.getWriter().println("< h3>Hello from HelloWorldServlet< /h3>");
  11. }
  12. }

HelloWorldServlet 類對 HttpServlet 進行擴展並重寫其 doGet() 方法。新的 doGet() 方法唯一的操作就是在輸出中寫入“Hello from HelloWorldServlet”。

下一步,你需要在 com.javaworld.sample.osgi.web.programmatic 插件啟動時執行相同的代碼。Activator.Java 將作為該插件的套件的激活器(Activator),如列表 6 所示。

列表 6. Activator.Java

  1. import org.osgi.framework.BundleActivator;
  2. import org.osgi.framework.BundleContext;
  3. import org.osgi.util.tracker.ServiceTracker;
  4. public class Activator implements BundleActivator {
  5. ServiceTracker httpServiceTracker;
  6. public void start(BundleContext context) throws Exception {
  7. System.out.println("Hello World!!");
  8. httpServiceTracker = new HttpServiceTracker(context);
  9. httpServiceTracker.open();
  10. }
  11. public void stop(BundleContext context) throws Exception {
  12. System.out.println("Goodbye World!!");
  13. httpServiceTracker.close();
  14. httpServiceTracker = null;
  15. }
  16. }

Activator 類對 BundleActivator 進行擴展並實現了兩個方法:

start():當 OSGi 容器啟動該插件時調用 start() 方法。在start()HttpServiceTracker 類 的一個對象;這是你用來跟蹤 HttpService 的 ServiceTracker 類。一旦你擁有了 HttpService 類的一個對象,可以調用它的 open() 方法來開始跟蹤 HttpService。

stop():當關閉插件時,OSGi 容器調用 stop() 方法。在 stop() 方法內,你調用 HttpServiceTracker 對象的 close() 方法來終止跟蹤 HttpService。

最後一步是創建 HttpServiceTracker 類,如列表 7 所示。

列表 7. HttpServiceTracker

  1. import org.osgi.framework.BundleContext;
  2. import org.osgi.framework.ServiceReference;
  3. import org.osgi.service.http.HttpService;
  4. import org.osgi.util.tracker.ServiceTracker;
  5. public class HttpServiceTracker extends ServiceTracker{
  6. public HttpServiceTracker(BundleContext context) {
  7. super(context, HttpService.class.getName(), null);
  8. }
  9. public Object addingService(ServiceReference reference) {
  10. HttpService httpService = (HttpService) context.getService(reference);
  11. try {
  12. httpService.registerResources("/helloworld.Html", "/helloworld.Html", null);
  13. httpService.registerServlet("/helloworld", new HelloWorldServlet(), null, null);
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. return httpService;
  18. }
  19. public void removedService(ServiceReference reference, Object service) {
  20. HttpService httpService = (HttpService) service;
  21. httpService.unregister("/helloworld.Html");
  22. httpService.unregister("/helloworld");
  23. super.removedService(reference, service);
  24. }
  25. }

HttpServiceTracker 介紹

HttpService 是一項 OSGi 服務,允許 OSGi 環境中的套件動態的注冊以及取消注冊 HttpService 的 URI 名稱空間中的資源和 servlet —— 換句話說,即將請求 URI 映射到一個靜態 Html 文件或一個 HttpServlet。HttpServiceTracker 類是類型 ServiceTracker 的一個對象,後者簡化了對 HttpService 的跟蹤。(有關 OSGi 的 ServiceTracker 的更多信息,請查閱本系列文章的第一節中的“跟蹤服務”。)

列表 7 中 HttpServiceTracker 類重寫了兩個方法:addingService() 和 removedService()。有必要對這兩個方法進行解釋一下:

addingService()

一個回調方法,一旦 HttpService 可用時將對其調用。在這個方法中,首先調用 HttpService.registerResources("/helloworld.html", "/helloworld.html", null),將 helloworld.html 文件映射到 /helloworld.Html。之後,每當你請求 http://localhost/helloworld.Html 時, HttpService 將為用戶提供 helloworld.html。請注意,你無需將 helloworld.html 映射到 /helloworld.html URL;文件名無需匹配該地址,並且你可以將其映射到類似 /test.Html 的文件上。

如果想要在你的插件中提供(serve)多個 HTML 文件,你需要創建多個目錄。如果想要一個 /html 目錄,可以通過調用 HttpService.registerResources("/html", "/html", null) 來注冊它。然後,如果你還想要訪問 Html 文件夾中的 test.htm,相應的地址是 http://localhost/html/test.Html。registerServlet() 方法用於將 URL 映射到 HttpServlet 類。在這個簡單的代碼中,利用對 registerServlet("/helloworld", new HelloWorldServlet(), null, null) 的調用將 /helloworld URL 映射到 HelloWorldServlet 類。如需將初始化參數傳遞到你的 HttpServlet,你可以創建一個 Java.util.Dictionary 對象並將其作為第三方自變量傳遞到 registerServlet()。

removedService()

每當重寫你的 ServiceTracker 中的 addingService() 方法來獲得一個服務時,還是重寫 removedService() 來取消該服務。在 removedService() 方法內,你調用 unregister() 方法來取消注冊 /helloworld.Html 和 /helloworld URI。這將通知 HttpService :com.Javaworld.sample.osgi.web.programmatic 不再想要為指定 URL 提供請求服務。如果你調用 unregister() 方法來取消對 servlet 的注冊, 該 servlet 的 destroy() 方法將被調用以便對其自身進行清除。

現在,HelloWorld OSGi Web應用程序已經准備就緒,並且你可以在 Equinox OSGi 框架中執行你全部的套件。你應該能夠通過 http://localhost/helloworld.Html 訪問 helloworld.Html,以及通過 http://localhost/helloworld 訪問 HelloWorld 的servlet。

聲明注冊方式

你可能已經注意到,通過程序方式將請求 URL 注冊為 OSGi 創建可處理,相應的工作流並不小。而且,如果想要更改 helloworld.html 的 URL(比如從 /helloworld.html 更改到 /hello.Html),你將不得不更新 HttpServiceTracker.Java,重新編譯代碼,然後在 OSGi 容器中對其進行部署。下面,我們來看看聲明方式,它稍微簡單點。

1. 創建一個新的插件項目,com.Javaworld.sample.osgi.web.declarative。選擇 OSGi Equinox 框架作為目標平台。

2. 編輯 com.javaworld.sample.osgi.web.declarative 套件的 MANFIEST.MF 文件,導入 javax.servlet 和 Javax.servlet.http 包並將 org.eclipse.equinox.http.registry 設置為該套件的被請求套件。完成這項修改之後,你的 MANIFEST.MF 文件將與列表 8 類似。

列表 8. 聲明方式插件的 MANIFEST.MF 文件

  1. Manifest-Version: 1.0
  2. Bundle-ManifestVersion: 2
  3. Bundle-Name: Declarative Plug-in
  4. Bundle-SymbolicName: com.Javaworld.sample.osgi.web.declarative;singleton:=true
  5. Bundle-Version: 1.0.0
  6. Bundle-Vendor: JavaWORLD
  7. Bundle-Localization: plugin
  8. Import-Package: Javax.servlet;version="2.4.0",
  9. Javax.servlet.http;version="2.4.0"
  10. Require-Bundle: org.eclipse.equinox.http.registry

這個 Require-Bundle 清單頭包含一個套件符號名的列表,在對導入搜索之後並且在套件路徑搜索之前,需對其進行搜索。不過,對其請求套件,只有那些標記為通過被請求套件導出的包才是可見的。

3. 從 com.javaworld.sample.osgi.web.programmatic 套件將 helloworld.Html 和 HelloWorldServlet.java 復制到 com.Javaworld.sample.osgi.web.declarative 套件。

4. 最後,更改 com.Javaworld.sample.osgi.web.declarative 套件的 plugin.XML 文件,將所有請求注冊為它能夠處理,如列表 9 所示。

Listing 9. plugin.XML

  1. < ?XML version="1.0" encoding="UTF-8"?>
  2. < ?eclipse version="3.0"?>
  3. < plugin>
  4. < extension-point id="servlets" name="HttpService servlets" schema="schema/servlets.exsd"/>
  5. < extension-point id="resources" name="HttpService resources" schema="schema/resources.exsd"/>
  6. < extension-point id="httpcontexts" name="HttpService httpcontexts" schema="schema/httpcontexts.exsd"/>
  7. < extension
  8. id="helloServlet"
  9. point="org.eclipse.equinox.http.registry.servlets">
  10. < servlet
  11. alias="/decl/helloworld"
  12. class="com.Javaworld.sample.osgi.web.webapp.HelloWorldServlet">
  13. < /servlet>
  14. < /extension>
  15. < extension
  16. id="helloResource"
  17. point="org.eclipse.equinox.http.registry.resources">
  18. < resource
  19. alias="/decl/helloworld.Html"
  20. base-name="/helloworld.Html"
  21. />
  22. < /extension>
  23. < /plugin>

請注意,plugin.XML 具有兩個 < extension> 元素。第一個,具有 id 屬性,其值為 helloServlet,表示 HelloWorldServlet類將被用於處理 /decl/helloworld 請求。通過將 point 屬性的值設置為 org.eclipse.equinox.http.registry.servlets,你可以標示這是 servlet 類。第二個 < extension> 元素,具有指定值為 helloResource 的 id 屬性,表示用戶請求 /decl/helloworld.html 應返回 helloworld.Html 給用戶。

現在,使用聲明方式重新創建的 HelloWorld OSGi Web應用已經准備好了,並且你可以在 Equinox OSGi框架中執行你全部的套件。你可以通過 http://localhost/decl/helloworld.Html 訪問 helloworld.Html 以及通過 http://localhost/decl/helloworld 訪問 HelloWorld servlet。在下一篇,也是本系列的最後一篇文章中,將介紹如何在Eclipse外部執行OSGi 容器,敬請關注!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved