使用自定义hk2 InjectionResolver注入应用程序配置

跟我上一个问题有所帮助。 我正在尝试使用JSR-330标准注释和与泽西捆绑的HK2框架注入应用程序配置数据。

理想情况下,我想为Named注释创建一个自定义的InjectionResolver ,它将在MapProperties对象中查找所需的值,我将从其他地方读取的数据填充该值。 在我的第一次尝试中,我创建了一个类似的Application实例

 public class MyApplication extends ResourceConfig { ... packages(MY_PACKAGES); property(MY_CONFIG_PROPERTY, someValue); register(new AbstractBinder() { @Override protected void configure() { bind(ConfigurationInjectionResolver.class) .to(new TypeLiteral<InjectionResolver>(){}) .in(Singleton.class) } }); } 

然后我的InjectionResolver看起来像

 public class ConfigurationInjectionResolver implements InjectionResolver { @Context Application application; @Override public Object resolve(Injectee injectee, ServiceHandle serviceHandle) { // lookup data in application.getProperties(); } } 

我的问题是application.getProperties()是空的。 知道什么是错的吗? 另外,我可以绑定我的Injector实例而不是绑定类吗? 这样我就可以构造将我的Map数据作为参数传递的实例。

“我的问题是application.getProperties()是空的。知道什么是错的吗?

不,这实际上对我来说非常好。

 public class ConfigurationInjectionResolver implements InjectionResolver { @Context Application application; @Override public Object resolve(Injectee injectee, ServiceHandle root) { Named annotation = injectee.getParent().getAnnotation(Named.class); Map props = application.getProperties(); String name = annotation.value(); System.out.println(props.get(name)); return props.get(name); } @Override public boolean isConstructorParameterIndicator() { return false; } @Override public boolean isMethodParameterIndicator() { return false; } } @ApplicationPath("/rest") public class JerseyApplication extends ResourceConfig { public JerseyApplication() { packages("jersey.startup.test"); property("hello.config", "Hello World Property"); register(new AbstractBinder() { @Override protected void configure() { bind(ConfigurationInjectionResolver.class) .to(new TypeLiteral>() { }).in(Singleton.class); } }); } } 

资源

 @Path("/config") public class ConfigResource { @Named("hello.config") String hello; @GET public Response getHello() { return Response.ok(hello).build(); } } 

C:\>curl http://localhost:8080/test/rest/config
Hello World Property

就个人而言,在这种情况下,我会创建自己的注释,以便不覆盖@Named注释的任何现有function。


另一个酷的选择

HK2有一个配置扩展,您可以从一个.properties文件加载一个Properties对象,并使用@Configured注释自动注入这些属性。 我找不到任何关于此的文档,但在HK2源代码示例中有一个示例用法。

这是一个示例实现

必需的依赖项。 检查Jersey版本,看看它依赖的HK2版本。 在我的情况下,泽西2.13使用HK2 2.3.0-b10,所以应该是${hk2.version}

  org.glassfish.hk2 hk2-configuration-hub ${hk2.version}   org.glassfish.hk2 hk2-configuration-integration ${hk2.version}   org.glassfish.hk2 hk2-property-file ${hk2.version}  

应用配置

 @ApplicationPath("/rest") public class JerseyApplication extends ResourceConfig { @Inject public JerseyApplication(ServiceLocator locator) { packages("jersey.startup.test"); ServiceLocatorUtilities.addClasses(locator, ConfigResource.class); try { loadConfigurationProperties(locator); } catch (IOException ex) { Logger.getLogger(JerseyApplication.class.getName()) .log(Level.SEVERE, null, ex); } } private void loadConfigurationProperties(ServiceLocator locator) throws IOException { ConfigurationUtilities.enableConfigurationSystem(locator); PropertyFileUtilities.enablePropertyFileService(locator); PropertyFileService propertyFileService = locator.getService(PropertyFileService.class); Properties props = new Properties(); URL url = getClass().getResource("/configuration.properties"); props.load(url.openStream()); PropertyFileHandle propertyFileHandle = propertyFileService.createPropertyHandleOfAnyType(); propertyFileHandle.readProperties(props); } } 

configuration.properties

 AppConfiguration.App.hello=Hello Squirrel Property! 

资源

 @Path("/config") @ConfiguredBy("AppConfiguration") public class ConfigResource { @Configured String hello; @GET public Response getHello() { return Response.ok(hello).build(); } } 

C:\>curl http://localhost:8080/test/rest/config
Hello Squirrel Property!

Diclaimer:由于这个function没有很好的记录,我不确定我是否有一个很好的实现。 只是通过反复试验。 比如说这个

 ServiceLocatorUtilities.addClasses(locator, ConfigResource.class); 

我觉得不应该是必要的。 这似乎是多余的,因为我已经打包了。 因此,将ConfigResource显式添加到定位器上下文对我来说似乎并不合适。