Jersey 2.26+Spring Boot 2下@Context变量被工厂重复创建问题
解决Jersey 2.26 + Spring Boot 2中@Context注入导致Factory重复创建及请求上下文异常的问题
问题根源分析
从你的代码和异常信息来看,这个问题主要来自两个核心点:
- Jersey 2.26对HK2依赖注入流程的调整:新版本中RequestScoped作用域的Factory实例化时机发生了变化,你的
UserFactory在构造函数中直接初始化User,而此时HttpServletRequest还未绑定到当前请求上下文,导致后续抛出findOrCreate returned a null异常。 - @Context注解的特殊处理逻辑:@Context原本用于注入Jersey原生的上下文对象(如Request、Response等),对自定义类型使用@Context会触发额外的上下文查找流程,进而导致Factory被重复实例化(方法执行前后各一次)。
分步解决方案
1. 重构UserFactory,延迟User实例化到provide()方法
把User的创建逻辑从构造函数移到provide()方法中,确保在请求上下文完全就绪后再获取HttpServletRequest:
public class UserFactory implements Factory<User> { private final HttpServletRequest request; private final RequestIdentityService requestIdentityService; @Inject public UserFactory(HttpServletRequest request, RequestIdentityService requestIdentityService) { // 仅注入依赖,不做业务逻辑处理 this.request = request; this.requestIdentityService = requestIdentityService; } @Override public User provide() { // 在此处创建User,此时请求上下文已就绪 String userName = requestIdentityService.getCurrentUser(request); return new User(userName); } @Override public void dispose(User instance) { } }
2. 替换@Context为@Inject注入自定义类型
对于自定义的User类型,使用Jersey/HK2标准的@Inject注解替代@Context,避免触发额外的上下文查找逻辑,减少Factory重复实例化的可能:
@GET @Path("/user-entitlements") public Set<String> getUserEntitlements(@Inject User user) { return service.getUserEntitlements(user); }
3. 确保Jersey与Spring上下文的桥接正确
如果RequestIdentityService是Spring管理的Bean,需要确保Jersey能正确访问Spring上下文。在你的Jersey配置类中显式注册Spring桥接Feature:
register(SpringComponentProviderFeature.class);
Spring Boot整合Jersey时,spring-boot-starter-jersey依赖已经包含了该Feature,但显式注册可以避免版本兼容问题。
4. 验证RequestScoped绑定的正确性
保持你的Binder配置不变,但确保使用的是Jersey提供的RequestScoped(org.glassfish.jersey.process.internal.RequestScoped),而非HK2的原生RequestScoped:
register( new AbstractBinder() { @Override public void configure() { bindFactory(UserFactory.class) .to(User.class) .in(org.glassfish.jersey.process.internal.RequestScoped.class); } } );
为什么旧版本正常?
在Jersey 2.26之前,RequestScoped Factory的构造函数执行时机与请求上下文的绑定时机是同步的,因此在构造函数中直接获取HttpServletRequest不会出现null的情况;同时旧版本对@Context注解的处理逻辑更宽松,不会触发额外的Factory实例化流程。
内容的提问来源于stack exchange,提问作者Krzysztof Krasoń
相关产品推荐
相关产品推荐

