⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wicket通过osgi框架注入jetty.txt

📁 OSGI 开发指南源代码|实例|入门及相关的文档
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Wicket通过OSGi框架注入Jetty
2007-08-24 来自:lizhe1985  [收藏到我的网摘]
来源:JavaEye技术社区

  Wicket框架的优点就不多说了,总之第一次看到她就让人耳目一新。我的框架就是采用OSGi、Spring、Hibernate、Wicket、Jetty等开源技术搭建的,所以这篇文章就是我在将Wicket通过OSGi框架注入Jetty中的一点心得体会。目前wicket刚刚推出1.3Beta3版,由于1.3版和2.0版比较接近,所以采用1.3版来测试。

  首先介绍一下我的整体思路,将Jetty和wicket分别作为OSGi的Bundle,对外提供服务;自己的基于wicket的web应用也作为一个Bundle。另外因为web应用中要用到其它Bundle提供的服务,当然采用IOC方式最方便,所以需要wicket和spring整合一下。

  先说Jetty和Wicket这两个Bundle,其实Jetty6.1.5已经兼容OSGi,它的jar包已经可以直接作为Bundle使用,我们目前涉及到的就是其安装目录下的lib/jetty-6.1.5.jar,lib/jetty-util-6.1.5.jar和lib/servlet-api-2.5.6.1.5.jar这三个jar包。前两个是jetty作为嵌入式服务器所必需的,最后一个是jetty的servlet实现。

  因为我们采用编程式处理web应用,所以需要将web应用的信息注入到Jetty中。那么为什么不使用配置文件如web.xml呢?因为如果使用配置文件就要解决两个问题:

  第一是绝对路径问题,OSGi的Bundle并没有自己固定部署的位置,所以部署时绝对路径可以任选,这样如果采用配置文件声明web应用,那么配置文件就要随着Bundle位置变更而变更,一般Bundle都是jar包的形式保存,势必导致修改的困难。

  第二是类加载问题,因为我们要使用IOC和其他Bundle声明的服务,如果采用配置文件方式,类的初始化都由ClassLoader直接处理,因此上面所说的很难办到。 

  采用编程式处理web应用,就需要建一个Bundle(wanged_core_jetty),用来处理其他Bundle提供的Handler(这个jetty中的主要部件,可以参看Jetty 6.1.5的配置一文)。先看配置文件bean.xml:

xml 代码

<bean id="jettyHandlerManager" class="wanged.core.jetty.JettyHandlerManager"> 
<property name="handlers" ref="handlers" /> 
</bean> 

<bean name="jettyServer" class="wanged.core.jetty.JettyServer" init-method="start" destroy-method="stop" /> 
以及osgi-service.xml:

xml 代码

<!-- 服务 和 引用 --> 
<osgi:reference id="handlers" interface="org.mortbay.jetty.Handler" cardinality="1..n"> 
<osgi:listener ref="jettyServer" /> 
</osgi:reference> 
这里引用了其他Bundle提供的接口为org.mortbay.jetty.Handler的服务,并注册一个监听器jettyServer来处理Handler的动态绑定与删除问题,以便可以动态添加/删除web应用。下面看看具体代码:

java 代码

package wanged.core.jetty; 

import java.util.Dictionary; 

import org.mortbay.jetty.Handler; 
import org.mortbay.jetty.Server; 
import org.mortbay.jetty.handler.HandlerCollection; 
import org.springframework.osgi.service.TargetSourceLifecycleListener; 

/** 
* 启动Jetty服务器,监听Handler的添加与删除,并动态更新服务器的Handler 
* @author wanged 
* 
*/ 

@SuppressWarnings("unchecked") 
public class JettyServer implements TargetSourceLifecycleListener{ 

private Server server = new Server(8080); 

private HandlerCollection handlers = new HandlerCollection(); 

public void start(){ 
this.server.setHandler(this.handlers); 
try { 
this.server.start(); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 

/** 
* 绑定新的Handler,并启动之 
*/ 
public void bind(Object obj, Dictionary dict) throws Exception { 
Handler h = (Handler)obj; 
this.handlers.addHandler(h); 
h.start(); 
} 

/** 
* 删除Handler,并停止之 
*/ 
public void unbind(Object obj, Dictionary dict) throws Exception { 
Handler h = (Handler)obj; 
this.handlers.removeHandler(h); 
h.stop(); 
} 

public void stop(){ 
try { 
this.server.stop(); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 

}

  实现接口TargetSourceLifecycleListener,监听服务的绑定与删除。另一个类如下:

java 代码
package wanged.core.jetty; 

import java.util.Collection; 

import org.mortbay.jetty.Handler; 

/** 
* Jetty服务器Handler的管理器,用来动态管理作为服务注册的Handler 
* @author wanged 
* 
*/ 
public class JettyHandlerManager { 
private Collection handlers; 

public void setHandlers(Collection handlers) { 
this.handlers = handlers; 
} 

} 

  这个类只是简单声明了一个setHandlers方法,功能可以扩展。到此为止Jetty的相关工作已经处理完了。

  下面该说说web应用了,我的web应用放在一个叫wanged_wicket_app的Bundle中。涉及到的类比较多,所以现将类列出再一一解说。首先看SpringWicketFilter:

java 代码
package wanged.web.wicket; 

import org.apache.wicket.protocol.http.IWebApplicationFactory; 
import org.apache.wicket.protocol.http.WicketFilter; 

public class SpringWicketFilter extends WicketFilter{ 
private IWebApplicationFactory factory ; 

public IWebApplicationFactory getApplicationFactory(){ 
return factory; 
} 

public void setApplicationFactory(IWebApplicationFactory factory){ 
this.factory = factory; 
} 

}

  为什么不直接用WicketFilter呢,因为WicketFilter需要有一个applicationClass的参数需要定义在init-param中,需要解析web.xml才能得到,而且生成的WebApplication不能使用IOC功能。熟悉Wicket的朋友会问,Wicket不是已经和Spring整合了么?是的,确实整合了,但这种整合无法用在OSGi环境下,所以我们需要自定义一个WicketFilter的子类来声明一个注入了Spring上下文的IWebApplicationFactory的实现SpringWebApplicationFactory:

java 代码

package wanged.web.wicket; 

import org.apache.wicket.protocol.http.IWebApplicationFactory; 
import org.apache.wicket.protocol.http.WebApplication; 
import org.apache.wicket.protocol.http.WicketFilter; 
import org.springframework.beans.BeansException; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 

public class SpringWebApplicationFactory implements IWebApplicationFactory, ApplicationContextAware { 
private WebApplication webApplication; 

private ApplicationContext context; 

private String diskStorePath; 

public void init() { 
DefaultApplication app = new DefaultApplication(); 
app.setApplicationContext(context); 
app.setDiskStorePath(this.diskStorePath); 
this.webApplication = app; 
} 

public WebApplication createApplication(WicketFilter filter) { 
return webApplication; 
} 

public void setApplicationContext(ApplicationContext context) throws BeansException { 
this.context = context; 
} 

public void setDiskStorePath(String path){ 
this.diskStorePath = path; 
} 
} 

  这里引用了一个DefaultApplication,这是WebApplication的子类,在Wicket应用中有至关重要的作用,每一个wicket的web应用都需要自定义一个:

java 代码

package wanged.web.wicket; 

import java.io.File; 

import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore; 
import org.apache.wicket.protocol.http.WebApplication; 
import org.apache.wicket.protocol.http.pagestore.DiskPageStore; 
import org.apache.wicket.session.ISessionStore; 
import org.apache.wicket.spring.injection.annot.SpringComponentInjector; 
import org.apache.wicket.util.lang.Bytes; 
import org.springframework.beans.BeansException; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 

import wanged.web.wicket.login.LoginPage; 

public class DefaultApplication extends WebApplication implements ApplicationContextAware { 
private ApplicationContext context; 
private String diskStorePath; 


@SuppressWarnings("unchecked") 
@Override 
public Class getHomePage() { 
return LoginPage.class; 
} 

@Override 
public void init() { 
super.init(); 
addComponentInstantiationListener(new SpringComponentInjector(this, this.context)); 
} 

public void setApplicationContext(ApplicationContext context) throws BeansException { 
this.context = context; 
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -