在OSGi环境中运行的HttpServlet(即在OSGi HttpService中注册)想要调用一些OSGi服务来完成它的任务,这似乎很自然。问题是如何在servlet中获取对这些OSGi服务的引用。
一种方法是将依赖项注入正在向OSGi HttpService注册的HttpServlet实例,如下所示:
MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);
httpService.registerServlet("/myservlet", servlet, initparams, context);
我不确定这是否是一种有效的方法,因为在非OSGi环境中,servlet生命周期由Web容器管理,因此不会为稍后创建的servlet实例注入服务引用。
当使用PAX Web作为OSGi HttpService的实现时,还有另一种方法可以解决这个问题。 PAX Web将OSGi BundleContext作为特殊属性“osgi-bundlecontext”导出到ServletContext中。然后可以使用BundleContext获取必要的服务引用:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext context = servletConfig.getServletContext()
BundleContext bundleContext =
(BundleContext) context.getAttribute("osgi-bundlecontext");
ServiceReference serviceRef =
bundleContext.getServiceReference("com.foo.FooService")
}
然而,这种方法相当丑陋,并且将您与OSGi HttpService的具体实现联系起来。你知道其他(也可能是更好的)解决这个问题的方法吗?
答案 0 :(得分:2)
如果您使用setter来依赖服务,如图所示,它也可以在OSGi之外工作。您只需要使用其他一些依赖注入机制。如果没有,您可以提供一个子类,使用JNDI查找或servlet上下文初始化servlet。
public class MyServlet_AdapterForMissingDI extends MyServlet{
public void init(ServletConfig config){
setFooService(getItFromSomewhere());
}
}
关键是如果你有可以注入setFooService
的DI功能,你可以在OSGi和其他地方使用相同的servlet,如果你没有(并且仍然想支持这种情况),你提供一个适配器。
在相关的说明中,请查看Felix SCR以配置对象的依赖项,以及Pax Web Extender Whiteboard,它负责使用HttpService挂接您的servlet。
具体来说,如果没有SCR和Whiteboard,您需要考虑以后fooService不可用时的情况,或者在servlet之后启动HttpService。 在这些情况下,您的servlet将引用一个死服务,该服务可防止bundle被垃圾收集,或者您的servlet不会在HttpService中注册。
更新:这是我用于其中一个servlet的SCR描述符。 SCR处理servlet实例化,生命周期,注册(通过白板)和依赖关系。 servlet中没有特定于OSGi的代码。甚至不再需要BundleActivator(SCR注册所有服务):
<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
<provide interface="javax.servlet.Servlet" />
</service>
<reference name="DATASOURCES"
interface="javax.sql.DataSource"
cardinality="0..n" policy="dynamic"
bind="bindDataSource" unbind="unbindDataSource"/>
</component>
servlet的依赖项在reference
标记中指定。 SCR将执行服务查找和绑定。
答案 1 :(得分:2)
可能是一个老帖子,你可能已经得到了答案.. 您是自己推出felix还是其他任何OSGi容器。如果是这种情况,您可以将bundle上下文设置为servlet上下文的属性。
PAX使用http服务有什么不对。最终,线程管理和其他方面由运行此http服务的servlet容器负责。
答案 2 :(得分:-1)
您可以将服务注入某个对象,然后由servlet查询。