Jersey 2中如何为可注入类设置值以在API资源注入时可用?
解决Jersey 2.x中注入后调用对象方法的问题
背景
已从Jersey 1.19迁移至Jersey 2.41(搭配HK2与Jetty 10.0.20),使用Java 17。此前成功搭建v1版本REST服务器,现需完成v2版本适配。在v1代码中,可在启动HTTPServer的类中为待注入类ISyslogServerParms设置值,但在Jersey 2中尝试多次均未成功。目前ISyslogServerParms的注入已正常完成,但找不到合适位置调用setEventTrackers()方法。
原Jersey 1.x实现代码
Injector injector = Guice.createInjector(new SyslogAPIModule()); ISyslogServerParms serverParms = injector.getInstance(ISyslogServerParms.class); serverParms.setEventTrackers(eventTrackers);
当前Jersey 2.x代码结构
API类
package com.w3p.api; @Path("njams") public class MyMessageAPI { @Inject private ISyslogServerParms syslogServerParms; @POST @Path("syslog") @Consumes(MediaType.TEXT_XML) public Response handleSysLogMsg(String syslogData) { // 业务逻辑 } }
REST服务器类
public class MyRestServer { private final List<String> eventTrackers; public MyRestServer(List<String> eventTrackers) { this.eventTrackers = eventTrackers; } public void run() { ApplicationConfig config = new ApplicationConfig(eventTrackers); // 启动Jetty服务器的逻辑 } }
ResourceConfig类
public class ApplicationConfig extends ResourceConfig{ @Inject public ApplicationConfig(List<String> eventTrackers) { packages("com.w3p.api"); register(new ApplicationBinder()); ServiceLocator locator = ServiceLocatorFactory.getInstance().create("MyMessageAPI"); ISyslogServerParms parms = locator.getService(ISyslogServerParms.class); parms.setEventTrackers(eventTrackers); } }
问题原因
你手动创建的ServiceLocator和Jersey内部实际使用的不是同一个实例,因此无法获取到已注册的ISyslogServerParms对象,导致parms为null。
解决方案
方法1:绑定阶段直接初始化实例(推荐)
在HK2的Binder中创建ISyslogServerParms实例并设置eventTrackers,绑定后注入时直接使用已初始化完成的对象。
- 修改
ApplicationConfig,将eventTrackers传入Binder:
public class ApplicationConfig extends ResourceConfig{ public ApplicationConfig(List<String> eventTrackers) { packages("com.w3p.api"); register(new ApplicationBinder(eventTrackers)); } }
- 修改
ApplicationBinder,在绑定逻辑中初始化实例:
public class ApplicationBinder extends AbstractBinder { private final List<String> eventTrackers; public ApplicationBinder(List<String> eventTrackers) { this.eventTrackers = eventTrackers; } @Override protected void configure() { // 替换为你的ISyslogServerParms实现类 SyslogServerParms serverParms = new SyslogServerParms(); serverParms.setEventTrackers(eventTrackers); bind(serverParms).to(ISyslogServerParms.class); } }
这种方式符合依赖注入的设计原则,避免了后续手动修改注入对象的状态。
方法2:获取Jersey实际使用的ServiceLocator
通过@Inject获取Jersey内部的ServiceLocator,直接从中获取ISyslogServerParms实例并调用方法:
public class ApplicationConfig extends ResourceConfig{ @Inject public ApplicationConfig(List<String> eventTrackers, ServiceLocator serviceLocator) { packages("com.w3p.api"); register(new ApplicationBinder()); ISyslogServerParms parms = serviceLocator.getService(ISyslogServerParms.class); if (parms != null) { parms.setEventTrackers(eventTrackers); } } }
注意:这种方式需要确保ISyslogServerParms已经在Binder中完成绑定,否则可能仍会获取到null。如果使用延迟绑定,可调用serviceLocator.getServiceHandle(ISyslogServerParms.class).getService()强制初始化实例。
内容的提问来源于stack exchange,提问作者John Ormerod
相关产品推荐
相关产品推荐

