Внедрение зависимостей HK2 с помощью Jersey 2 и Apache Shiro

Я создаю API для отдыха, используя Джерси 2.5.1. Я использую HK2 для внедрения зависимостей. Позже я решил использовать Apache Shiro для аутентификации и авторизации.

При создании собственного царства Широ я столкнулся с некоторыми проблемами. В моей сфере я хотел внедрить зависимость. Однако, когда я запустил свое приложение, зависимость не была разрешена.

Вот моя установка:

веб.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app
public class MyApplication extends ResourceConfig {
   public MyApplication() {
      register(new ApplicationBinder());
      packages(true, "my.app.api");
   }
}
0.xsd" version="3.0"> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <servlet> <servlet-name>MyApplication</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>my.app.api.MyApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MyApplication</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>

shiro.ini

[main]

authcBasicRealm = my.app.api.MyCustomRealm
matcher = my.app.api.MyCustomCredentialsMatcher
authcBasicRealm.credentialsMatcher = $matcher
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager

[urls]

/** = authcBasic

MyApplication.java

public class MyApplication extends ResourceConfig {
   public MyApplication() {
      register(new ApplicationBinder());
      packages(true, "my.app.api");
   }
}

ApplicationBinder.java

public class ApplicationBinder extends AbstractBinder {
   @Override
   protected void configure() {
      bind(UserDAO.class).to(new TypeLiteral<Dao<User>>(){});
      bind(RealDatasource.class).to(DataSource.class);
   }
}

MyCustomRealm.java

public class MyCustomRealm extends JdbcRealm {

   @Inject DataSource source;

   public MyCustomRealm() {
      super();
   }

   @PostConstruct
   private void postConstruct() {
      // postConstruct is never executed
      setDataSource(source);
   }
}




Итак, проблема в том, что источник не внедряется в MyCustomRealm. Все остальные классы, созданные не Широ, внедряют его зависимости. Может ли проблема заключаться в том, что Широ создает мою CustomRealm через файл ini?


person ulejon    schedule 09.02.2014    source источник


Ответы (2)


Я столкнулся с похожей проблемой, и, хотя это, вероятно, больше не проблема для вас, я хотел предоставить обходной путь, который я использовал.

Проблема в праве собственности на MyCustomRealm. Он создается shiro в org.apache.shiro.web.env.EnvironmentLoaderListener путем чтения файла ini, который находится вне области действия провайдера hk2 в сервлете Джерси.

Внедрение зависимостей выполняется только тогда, когда объект предоставляется ServiceLocator hk2 — shiro не знает об этом локаторе и только создает экземпляр MyCustomRealm с его конструктором по умолчанию.

Я работал над этим, реализовав org.glassfish.jersey.server.spi.ContainerLifecycleListener, который получает дескриптор ServiceLocator и SecurityManager Широ (через ServletContext, который зарегистрирован с ServiceLocator). Затем он вручную вводит данные в область, созданную Широ.

Если вам интересно, я могу опубликовать код как суть.

person space    schedule 03.11.2015
comment
Привет, спасибо за ответ. Как вы сказали, для меня это больше не проблема, так как я больше не работаю с этой кодовой базой. Тем не менее, хорошее решение - person ulejon; 11.11.2015
comment
@space Я знаю, что это старый вопрос, но мне было бы интересно узнать суть, если у вас все еще есть ваш пример? - person Josef P.; 01.09.2016

Одна проблема, которую я вижу в MyCustomRealm, заключается в том, что вы ожидаете, что DataSource будет заполнен во время создания. Есть два способа решить эту проблему; один - использовать внедрение конструктора, а другой - использовать пост-конструкцию. Здесь будет использоваться внедрение конструктора:

public class MyCustomRealm extends JdbcRealm {

   private final DataSource source;

   @Inject
   public MyCustomRealm(DataSource source) {
      super();

      this.source = source;

      // source does not get injected
      setDataSource(source);
   }
}

Вот как вы могли бы сделать это с postConstruct:

public class MyCustomRealm extends JdbcRealm {

   @Inject DataSource source;

   public MyCustomRealm() {
      super();
   }

   @javax.annotation.PostConstruct
   private void postConstruct() {
      // source does not get injected
      setDataSource(source);
   }
}
person jwells131313    schedule 10.02.2014
comment
Привет. Спасибо, что нашли время ответить! К сожалению, это не сработало. Я пытался использовать @PostConstruct (я отредактировал свой пост), однако метод postConstruct() никогда не выполняется. - person ulejon; 10.02.2014