HK2 依赖注入与 Jersey 2 和 Apache Shiro



我正在使用Jersey 2.5.1创建一个rest api。我正在使用 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_3_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>

四郎.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

我的应用程序.java

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

应用绑定.java

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

我的自定义领域.java

public class MyCustomRealm extends JdbcRealm {
   @Inject DataSource source;
   public MyCustomRealm() {
      super();
   }
   @PostConstruct
   private void postConstruct() {
      // postConstruct is never executed
      setDataSource(source);
   }
}




所以,问题是源代码没有注入到MyCustomRealm中。所有其他不是由 Shiro 创建的类都会注入其依赖项。问题可能是 Shiro 正在通过 ini 文件创建我的自定义领域吗?

我遇到了类似的问题,虽然这对您来说可能不再是问题,但我想提供我使用的解决方法。

问题是MyCustomRealm的所有权。它是由 shiro 在org.apache.shiro.web.env.EnvironmentLoaderListener中通过读取 ini 文件创建的,该文件超出了泽西 servlet 中 hk2 提供程序的范围。

依赖注入仅在 hk2 的服务定位器提供对象时完成 - shiro 不知道这个定位器,只使用其默认构造函数构造MyCustomRealm的实例。

我通过实现一个org.glassfish.jersey.server.spi.ContainerLifecycleListener来解决这个问题,该获取服务定位器和shiro的安全管理器的句柄(通过向ServiceLocator注册的ServletContext)。 然后,它会手动将数据注入到 shiro 创建的领域。

如果您有兴趣,我可以将代码作为要点发布。

我在 MyCustomRealm 中看到的一个问题是,您希望在构造时填写数据源。 有两种方法可以解决此问题;一种是使用构造函数注入,另一种是使用后构造。 这里将使用构造函数注入:

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);
   }
}

最新更新