
在 jersey 2 中,`perrequesttypeinjectableprovider` 已被弃用,应通过 `abstractbinder` 配合 `injectionresolver` 实现请求作用域的依赖注入;关键前提是必须将自定义 binder 显式注册到 `resourceconfig`,否则注入点将始终为 null。
Jersey 2 的依赖注入体系基于 HK2,其扩展机制与 Jersey 1 截然不同。你提供的 UserSessionProvider 改写方向基本正确,但核心遗漏了 Binder 的注册 —— 这正是导致 Session 始终为 null 的根本原因。
✅ 正确实现步骤
1. 定义 InjectionResolver(推荐静态内部类,避免字段注入陷阱)
public class SessionBinder extends AbstractBinder {
@Override
protected void configure() {
bind(SessionResolver.class)
.to(new TypeLiteral>() {})
.in(Singleton.class); // Resolver 本身是单例,无需每次创建
}
// 注意:不要在 resolver 中直接使用 @Context 字段!
// HttpServletRequest 必须通过 injectee 或服务上下文动态获取
public static class SessionResolver implements InjectionResolver {
@Override
public Object resolve(Injectee injectee, ServiceHandle> handle) {
// ✅ 安全获取当前请求:通过 HK2 的 RequestScope 上下文或 Servlet 容器桥接
final HttpServletRequest request =
(HttpServletRequest)
handle.getService(RequestScopedContext.class)
.get(HttpServletRequest.class);
// 或更通用的方式(兼容非 Servlet 环境):
// final ContainerRequest containerReq =
// handle.getService(ContainerRequest.class);
// if (containerReq != null) { ... }
Session session = SessionUtils.createSession(request);
request.setAttribute(WebSessionConfig.s.servlet_attribute_name, session);
return session;
}
@Override
public boolean isConstructorParameterIndicator() {
return true;
}
@Override
public boolean isMethodParameterIndicator() {
return true;
}
}
} ⚠️ 重要提醒:@Context HttpServletRequest request; 字段在 AbstractBinder 或 InjectionResolver 中无法自动注入(Binder 实例化早于请求生命周期)。必须通过 ServiceHandle 动态解析当前请求上下文。
2. 在 ResourceConfig 中显式注册 Binder
public class MyApplication extends ResourceConfig {
public MyApplication() {
// ✅ 必须注册!否则 HK2 完全忽略该 Binder
register(SessionBinder.class);
// 其他资源、过滤器等...
register(UserResource.class);
}
}若使用 web.xml,需确保 ResourceConfig 类被正确扫描或显式指定:
JerseyServlet org.glassfish.jersey.servlet.ServletContainer javax.ws.rs.Application com.example.MyApplication
3. 使用示例(Controller 中注入)
@Path("/user")
public class UserResource {
@Context private HttpServletRequest request; // 可选:仅用于调试对比
@Inject private Session session; // ✅ 现在能正确解析并注入!
@GET
public Response getInfo() {
System.out.println("Session ID: " + session.getId()); // 不再为 null
return Response.ok().build();
}
}? 总结
- Jersey 2 中 PerRequestTypeInjectableProvider 的等效方案是:AbstractBinder + InjectionResolver
; - InjectionResolver 必须绑定到 InjectionResolver
类型,并通过 register() 显式启用; - 切勿在 resolver 中依赖 @Context 字段注入——务必通过 ServiceHandle 获取当前请求上下文;
- 若仍为空,请检查:Binder 是否注册、包扫描是否覆盖、Session 类是否有无参构造器(若需反射实例化)、以及是否启用了 HK2 的 ServiceLocator 自动发现。
遵循以上结构,即可稳定实现 Jersey 2 中的请求级 Session 注入。










