您的位置:首页 > 理论基础 > 计算机网络

使用NetBeans6开发OSGi应用(4)——Servlet与Http服务[88250原创]

2008-03-05 18:29 911 查看
转载请保留作者信息:

作者:88250

Blog:http:/blog.csdn.net/DL88250

MSN & Gmail & QQ:DL88250@gmail.com

摘要

上一次,我们分析了KF(Knopflerfish)框架的设计,实践了基于OSGi的应用程序框架的设计。这一讲,我们将基于KF实现的OSGi规范Http Service,做一个简单的Servlet结合HTML/Javascript的实践。


关于基于OSGi的Web开发

在开始前,我们先看一下一些关于OSGi在Web应用方面的尝试。

开发Web应用,最重要的要属Web Server了(亦或Application Server)。在Server的厂商中 IBM、BEA和JBoss应用服务器采用OSGi,虽然目前我们的主要任务的做应用,但是可以了解这些最基本的东西。

好了,简要说一下OSGi在Web上的开发方式:

1. 将Web Server作为Bundle插入OSGi

目前,Apache Jetty可以做到。使用Spring DM(Spring-OSGi)的话,Tomcat的OSGi整合在未来应该也可以做。参考 这个

2. 在Web Server内使用OSGi的Bundle

在Web容器里使用Spring DM(Spring-OSGi)可以做到。


目前来说

在Java的Web开发上,Spring Framework是首选,但是如果应用是以OSGi作为底层的话,情况就不同了:

1. 使用Spring,从Web应用开发的角度来说,视图/持久化/事务管理方便,可结合其他框架或技术的选择余地大
2. 使用OSGi,从系统整体开发角度来说,扩展性、维护性超好,系统整体结构清晰,可以把商业/控制逻辑做到很优良的组件话
3. 结合这两者使用的话(Spring DM),支持的扩展有限且技术相当复杂,得不偿失

所以,权衡后,我更偏向与直接使用OSGi来做Web应用,因为现在手头的一个项目只是运用例简单的HTML,AJAX与Servlet。


让我们简单实践一下!

准备

上一次 :-)


开工:

1. 创建工程

打开NB6,创建一个普通Java应用工程——OSGiServlet:






注意,www文件夹是存放HTML源文件的地方,要直接放在src文件夹下。然后要导入3个Jar libs:
http_all-2.0.0.jar: OSGi 的 http service实现
knopflerfish-osgi.jar: 基本OSGi实现
servlet-api.jar: Sun的servlet实现


2.编写Activator与Servlet类



/*
* @(#)Activator.java
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package cn.edu.ynu.sei.osgiservlet;

import java.net.URL;
import java.util.Hashtable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.knopflerfish.service.log.LogRef;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;

/**
* OSGi activator for <code>InfoServlet</code>.
* @author 88250
* @version 1.0.0.0, Mar 5, 2008
*/
public class Activator implements BundleActivator {

// This is my world
static BundleContext bc;

static LogRef log;

static final String RES_ALIAS = "/"; // the http server root

static final String RES_DIR = "/www"; // bundle resource directory

static final String SERVLET_ALIAS = "/servlet/firstservlet"; // a small servlet

Hashtable registrations = new Hashtable();

public void start(BundleContext bc) throws BundleException {

this.bc = bc;
this.log = new LogRef(bc);

ServiceListener listener = new ServiceListener() {

public void serviceChanged(ServiceEvent ev) {
ServiceReference sr = ev.getServiceReference();

switch (ev.getType()) {
case ServiceEvent.REGISTERED:
setRoot(sr);
break;
case ServiceEvent.UNREGISTERING:
unsetRoot(sr);
break;
}
}
};

String filter = "(objectclass=" + HttpService.class.getName() + ")";

try {
bc.addServiceListener(listener, filter);

ServiceReference[] srl = bc.getServiceReferences(null, filter);
for (int i = 0; srl != null && i < srl.length; i++) {
listener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED,
srl[i]));
}
} catch (Exception e) {
log.error("Failed to set up listener for http service", e);
}
}

public void stop(BundleContext bc) throws BundleException {
}

void setRoot(ServiceReference sr) {

if (registrations.containsKey(sr)) {
return; // already done
}

log.info("set root for " + sr);

HttpService http = (HttpService) bc.getService(sr);

HttpContext context = new HttpContext() {

public boolean handleSecurity(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException {
return true;
}

public URL getResource(String name) {

// when registering the root, it seems
// like we get no separator before the file.
// Is that a bug?? Code below is a workaround
if (name.startsWith(RES_DIR) &&
name.length() > RES_DIR.length() &&
'/' != name.charAt(RES_DIR.length())) {
name = RES_DIR + "/" + name.substring(RES_DIR.length());
}

// default to index.html
if (name.equals(RES_DIR)) {
name = "/www/index.html";
}

// and send the plain file
URL url = getClass().getResource(name);

return url;
}

public String getMimeType(String reqEntry) {
return null; // server decides type
}
};

try {
http.registerResources(RES_ALIAS, RES_DIR, context);
http.registerServlet(SERVLET_ALIAS, new InfoServlet(sr),
new Hashtable(), context);

registrations.put(sr, context);
} catch (Exception e) {
log.error("Failed to register resource", e);
}
}

void unsetRoot(ServiceReference sr) {
if (!registrations.containsKey(sr)) {
return; // nothing to do
}

log.info("unset root for " + sr);

HttpService http = (HttpService) bc.getService(sr);

if (http != null) {
http.unregister(RES_ALIAS);
http.unregister(SERVLET_ALIAS);
bc.ungetService(sr);
}
registrations.remove(sr);
}
}

/*
* @(#)InfoServlet.java
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package cn.edu.ynu.sei.osgiservlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.framework.ServiceReference;

/**
* The first OSGi servlet application.
* @author 88250
* @version 1.0.0.0, Mar 5, 2008
*/
public class InfoServlet extends HttpServlet {

ServiceReference httpSR;

public InfoServlet(ServiceReference httpSR) {
this.httpSR = httpSR;
}

public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
// Handle just as GET
doGet(request, response);
}

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

PrintWriter out = response.getWriter();

response.setContentType("text/html");

out.println("<html>");
out.println("<head>");
out.println("<title>Demo</title>");
out.println("I am a simple servlet base running in OSGi :-)");
out.println("</head>");
out.println("<body>");

try {
} catch (Exception e) {
out.println("<pre>");
e.printStackTrace(out);
out.println("</pre>");
}

}
}

还有一个简单的HTML页面(/www/index.html):

<html>
<head>
<title>The First OSGi Servlet Appication</title>
</head>

<body>
<h2>Test page for OSGi web server</h2>
<p>
Hello OSGi Servlet
</p>
<script type="text/javascript">
document. writeln("Test javascript!");
</script>
</body>
</html>

3. manifest.mf


Manifest-Version: 1.0


Bundle-ManifestVersion: 2


Bundle-Name: OSGi Servlet


Bundle-SymbolicName: cn.edu.ynu.sei.osgiservlet


Bundle-Version: 1.0.0.0


Bundle-Category: example


Bundle-Description: Demo HTTP servlet


Bundle-Activator: cn.edu.ynu.sei.osgiservlet.Activator


Import-Package: javax.servlet,


javax.servlet.http,


org.knopflerfish.service.log,


org.osgi.framework,


org.osgi.service.http

4. 测试

编译这个Bundle,安装它到KF里并运行之,结果如下图:




以地址 http://localhost:8080/servlet/firstservlet 访问我们的Servlet:



总结

本次,我们基于OSGi做了一个简单的HTTP/Servlet 容器,可以满足简单的应用。这样,我们可以把我们的应用统一在一个框架里,简化了很多技术细节。但是,做企业应用的话这样是远远不够的,我们也不是太有可能基于OSGi构建一个自己的Application Server,所以,只要容器支持OSGi,结合Spring DM是最好的选择。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: