有了osgi下建立hello world的基礎,再來講搭建Web環境,會相對容易一些。一般來說,有兩種建立Web環境的方式:將HTTP服務器嵌入OSGi框架和將OSGi框架嵌入Servlet容器。
HTTP服務器嵌入OSGi框架
首先,除了下載Equinox框架,還要去下載下列這些bundle:(需要注意其版本)
- javax.servlet
- org.apache.commons.logging
- org.eclipse.equinox.http.jetty
- org.eclipse.equinox.http.servlet
- org.eclipse.osgi.services
- org.mortbay.jetty.server
- org.mortbay.jetty.util
本人下載的jar包版本截圖如下:
這些jar包可以在我的下載裏面下:OSGI中包含web服務器配置需要的jar.zip
其中org.eclipse.osgi_3.7.0.v20110613.jar是Equinox框架的Jar包。然後在Eclipse的Window->Preferences->Plug-in Development->Target Platform中,將以上的Jar放置在New Target之中,並選中它作爲運行平臺,如下圖所示:
經過上面,步驟,基本搭建好Web的運行環境。然後在Run->Run Configurations中,OSGi Framwork下新建一個運行實例,選中剛剛加載進來的搜有Bundle,點擊Run,如圖所示:
如果沒有異常,運行效果如下(ss命令是本人額外輸入的):
下面,我描述下簡單寫的一個Web應用,前端一個Form表單,後臺使用Servlet簡單處理。參照“OSGi開發環境建立和Hello World”,建立OSGi工程。在Manifest.MF文件中,加入幾個Imported Packges:
上圖左邊是項目結構圖,右邊是Manifest.MF文件中引入的包。先看一下WeatherSerlvet的代碼,很簡單,就根據前端傳來的城市名字,返回天氣情況:
public class WeatherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BundleContext context;
public WeatherServlet(BundleContext context) {
this.context = context;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
doGet(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String queryWord = request.getParameter("query_word");
response.setContentType("text/html");
ServletOutputStream output = response.getOutputStream();
try {
output.println("Result is " + queryWeather(queryWord));
output.close();
return;
} catch (Exception e) {
output.println("Error occurs");
output.println(e.toString());
output.close();
return;
}
}
private String queryWeather(String city) {
if(city.equals("SZ"))
return "cool";
return "hot";
}
}
然後再看一下Activator的代碼:
public class Activator implements BundleActivator, ServiceListener {
private BundleContext bundleContext;
private ServiceReference ref;
private Servlet servlet;
public void start(BundleContext context) throws Exception {
bundleContext = context;
servlet = new WeatherServlet(bundleContext);
registerServlet();
context.addServiceListener(this, "(objectClass=" + HttpService.class.getName() + ")");
}
public void stop(BundleContext context) throws Exception {
try {
unregisterServlet();
} catch (Throwable t) {
t.printStackTrace();
}
servlet = null;
bundleContext = null;
ref = null;
}
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 = bundleContext.getServiceReference(HttpService.class.getName());
}
if (ref != null){
try {
HttpService http = (HttpService) bundleContext.getService(ref);
if(null != http){
http.registerServlet("/osgicn/index", servlet, null, null);
http.registerResources("/osgicn/page","page",null);
System.out.println("Html頁面已經註冊,可以訪問了!");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 卸載Web應用
*/
private void unregisterServlet(){
if (ref != null) {
try {
HttpService http = (HttpService) bundleContext.getService(ref);
if(null != http){
http.unregister("/osgicn/index");
http.unregister("/osgicn/page");
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
與一般的Bundle代碼不同的是,這裏需要將Html與Servlet資源註冊。對應這兩行代碼:
http.registerServlet("/osgicn/index", servlet, null, null);
http.registerResources("/osgicn/page","page",null);
第一句是註冊servlet,第二句是將page目錄下的靜態資源映射到/osgicn/page
的URL空間之下。在瀏覽器中,輸入http://localhost/osgicn/page/index.html
,可以看到這樣的頁面:
輸入SZ,可以看到結果cool,輸入其他的結果爲hot。
在Equinox官網,提供了另外一種註冊資源的方式,需要加入 org.eclipse.equinox.http.registry到Target Platform,然後將資源的映射關係寫在XML文件中。其實這兩種方法沒有什麼本質區別,只是將映射關係的硬編碼換成了XML配置文件。具體可以參見這裏以上工程對應代碼,我已經上傳CSDN 和 GitHub
OSGi框架嵌入Servlet容器
在Equinox官網的示例,參見blog。我這裏講的是另一種方式,將OSGi的Web Bundle部署到Virgo容器,也屬於OSGi框架嵌入Servlet容器的範疇。爲什麼不介紹官網的方式,而是介紹部署到Virgo的方式?第一,我們一直使用這種方式開發Web應用,很熟悉Virgo;第二,這種方式已經有了對Web企業級開發的支持;第三,入門相對簡單,也對我們社區之後陸續介紹Web企業及框架起鋪墊作用。首先,在該網址,下載Virgo的zip包。我們使用的是3.5版本的,點擊下載即可,如下圖:
關於Virgo的介紹,可以參見Virgo簡介。然後,我們在項目中使用了Maven,所以最好配置一下,方便管理依賴和編譯工程。關於安裝Maven和Maven的Eclipse插件這裏就不多說,網上很多教程,相對簡單。當然,不使用Maven也可以,在這裏,只是下載管理依賴包麻煩一些。然後是一些依賴包,下面列出常用的,均放置到Virgo的repository/usr目錄下,如下:
這些Jar包,在我們demo中,用到的很少,我也偷一次懶,將我們項目所用的所有包都扔上來。(在開發時候,很多jar包都會用到)與基礎的Hello World教程一樣,需要下載eclipse,最好較新的版本。然後安裝Virgo的Eclipse插件——Eclipse Virgo Tools,安裝插件的update site爲:http://download.eclipse.org/virgo/release/tooling。我們新建工程是使用Maven的Archetype插件,這樣可以快速生成項目骨架。可以參見社區的另一篇文章。按照該文章,我們可以建立如下的demo工程。(如果不想安裝插件,可以直接下載我們的代碼,import到Eclipse即可。)
在XML文件中做好Spring MVC的配置,我給的示例是使用Spring MVC的轉發請求功能,在HomeController裏面:
public class HomeController {
public static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
return "Index";
}
@RequestMapping(value = "/Target", method = RequestMethod.GET)
public String transfer(Model model) {
return "Target";
}
}
訪問localhost:8080,會跳轉到Index.jsp,在Index.jsp點擊/Target鏈接,Controller會將請求跳轉到Target.jsp。
以上的跳轉是經過Spring MVC的dispatcher Servlet攔截轉發的,在OSGi環境能夠引入Spring MVC,可以極大地方便開發者搭建企業級Web系統。
對上面的樣例,做一些簡單說明:1.這個工程展示的是將Web邏輯全部放在一個Bundle之中,OSGi支持多個Web Bundle構建成一個Web應用。多個Web Bundle的時候,需要引入Virgo Snaps。關於Snaps的介紹可以參見這篇文章。
2.本文的第二部分,讀者可以看出,已經引入了Spring,在此基礎之上,再嵌入數據層,一個開發框架的原型已經出來了。我們之後會很詳細地介紹本小組使用的框架,歡迎關注。
3.本文設計代碼已經放在GitHub 關於文中提到的依賴jar,也全部放在GitHub
由於涉及到很多配置,如Maven、Virgo插件等,加上本人水平有限,讀者有可能會遇到不少一些問題。可以在本文留言。
本文由OSGi China提供 轉載請註明來源