2009-06-16 65 views
4

在OSGi環境中運行(即在OSGi HttpService中註冊)的HttpServlet想要調用某些OSGi服務來完成它的任務似乎很自然。問題是如何在servlet中獲得對這些OSGi服務的引用。如何從OSGi HttpService中註冊的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的的。你知道任何其他(可能更好)的解決方案嗎?

回答

2

如果您使用setter作爲服務的依賴關係,如您所示,它也可以在OSGi之外工作。你只需要使用一些其他的依賴注入機制。如果沒有,您可以提供一個使用JNDI查找或從servlet上下文初始化servlet的子類。

public class MyServlet_AdapterForMissingDI extends MyServlet{ 

    public void init(ServletConfig config){ 
     setFooService(getItFromSomewhere()); 
    } 

} 

的一點是,如果你有一個可以注入setFooService DI功能,你可以使用同一個servlet在OSGi和其他地方,如果不這樣做(並且仍要支持這種情況),您需要提供適配器。

在相關說明中,查看Felix SCR來配置對象的依賴關係,以及Pax Web Extender白板,它負責將您的servlet與HttpService連接起來。

特別是,如果沒有SCR和白板,您需要考慮fooService稍後不可用或HttpService在您的servlet之後啓動的情況。 在這些情況下,你的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將執行服務查找和綁定。

+0

Pax Web Extender白板看起來像是一個很好的註冊servlet的解決方案。謝謝。然而,主要問題是如何從OSGi環境中的servlet中獲取服務引用。 你已經提到了JNDI查找,但它不覺得正確的方式來訪問OSGi服務註冊表。然後你也提到了servlet上下文,但是沒有辦法使用OSGi HttpService接口將對象放入servlet上下文中。如果我錯了,請糾正我。 – 2009-06-17 12:57:27

-1

您可以將服務注入某個對象,然後由servlet查詢。

+0

這只是將問題轉移一個級別。如何從servlet中獲得對這個對象的引用? – 2009-06-17 12:44:35

2

可能是一箇舊帖子,你可能已經得到了答案。 你是否啓動felix或任何OSGi容器自己。如果是這種情況,您可以將捆綁上下文設置爲servlet上下文的一個屬性。

PAX使用http服務有什麼問題。最終線程管理和其他方面都由您運行此http服務的servlet容器負責。