簡體   English   中英

如何干凈地覆蓋Jersey使用的默認ServiceLocator?

[英]How can I cleanly override the default ServiceLocator used by Jersey?

我正在開發一個應用程序,它使用Jersey(2.5)作為其REST前端,Jetty作為嵌入式HTTP(S)服務器,兩者都采用所謂的“嵌入式”方式,例如。 不依靠制作.war並部署它,而是通過程序化配置處理程序,資源,注入......

我想以某種方式覆蓋Jersey在服務器端使用的HK2 ServiceLocator ,或者可能為父服務定位器提供一個父服務器來解析在應用程序的REST部分之外定義的依賴關系。 從我看到的代碼來看,這似乎是不可能的:ServiceLocator通過調用InjectionsApplicationHandler實例化:

if (customBinder == null) {
        this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder());
    } else {
        this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder(),
                                                customBinder);
    }

注射中的代碼告訴我以下內容:

 public static ServiceLocator createLocator(Binder... binders) {
    return _createLocator(null, null, binders);
 }

這意味着新創建的服務定位器具有一些任意生成的名稱,並且沒有父級。

有沒有(干凈的)方法來改變這種行為,以便我自己注入ServiceLocator作為應用程序的父類?

我知道這個答案有點晚了。 我在同一個問題上掙扎,但在Dropwizard框架中。 經過一些調試,我看到了一些令我開心的代碼!

final ServiceLocator locator = (ServiceLocator) webConfig.getServletContext()
            .getAttribute(ServletProperties.SERVICE_LOCATOR);

這段代碼在jerseyes WebComponent構造器中。 所以解決方案是為ServletContext提供ServletProperties.SERVICE_LOCATOR 在Dropwizard環境中,我實現了它

environment.getApplicationContext().getAttributes().setAttribute(ServletProperties.SERVICE_LOCATOR, locator);

我們有類似的設置,我已經設法使用jwells131313的新bridgeServiceLocator API來使用我們的架構。

編輯:請注意,當前的HK2橋接實現意味着Singleton實例僅對其創建的ServiceLocator是本地的,這意味着橋接體系結構可以包含多個Singleton服務的實例。 請參閱此問題以獲取更多信息和可能的解決方法/替代方法。

編輯#2:修復了ServiceLocator橋中的上述錯誤。 修復程序將在hk2 2.5.0-b07或更高版本中

基本上我創建了一個Feature實現來設置橋接並將其注冊到Jersey(在我們的實例中通過ServletContainer )。

public class InjectionBridge implements Feature
{
  private static ServiceLocator _applicationServiceLocator;

  private final ServiceLocator _serviceLocator;

  @Inject
  private InjectionBridge(ServiceLocator serviceLocator)
  {
    _serviceLocator = serviceLocator;
  }

  @Override
  public boolean configure(FeatureContext context)
  {
    if (_applicationServiceLocator != null)
      ExtrasUtilities.bridgeServiceLocator(_serviceLocator, _applicationServiceLocator);
    return true;
  }

  public static void setApplicationServiceLocator(ServiceLocator applicationServiceLocator)
  {
    _applicationServiceLocator = applicationServiceLocator;
  }
}

然后,從應用程序代碼調用setApplicationServiceLocator並使用應用程序創建的ServiceLocator來管理應用程序資源。

這意味着Jersey RESTful服務實現現在可以簡單地使用@Inject批注聲明字段,並訪問那些注入資源以服務請求。

在創建ServiceLocator之后,您無法使一個ServiceLocator成為另一個ServiceLocator的父級。

但是,從hk2 2.4.0-b11開始,將能夠擁有ServiceLocator - > ServiceLocator橋。 因此,ServiceLocator的所有服務都可以放入Jersey(或任何其他ServiceLocator)的ServiceLocator中。 這是API: bridgeServiceLocator 它位於hk2的hk2-extras模塊中。

在hk2 2.4.0-b10中有一個版本可以使用,完全測試和記錄的功能將在hk2 2.4.0-b11

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM