首页 文章

如何从OSGi HttpService中注册的Servlet获取OSGi服务引用?

提问于
浏览
4

在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的具体实现联系起来 . 你知道其他(也可能更好)解决这个问题的方法吗?

3 回答

  • 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中注册 .

    Update: 这是我用于其中一个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

    可能是一个旧帖子,你可能已经得到了答案..你是自己推出felix或任何OSGi容器 . 如果是这种情况,您可以将bundle上下文设置为servlet上下文的属性 .

    使用PAX的http服务有什么不对 . 最终,线程管理和其他方面由运行此http服务的servlet容器处理 .

  • 2

    您可以将服务注入到某个对象中,然后由servlet查询 .

相关问题