在Jersey 2中,我可以在我的资源中注入自定义的特定于请求的值吗?具体来说,我想注入一个MyThing
,它可以从我的自定义安全上下文MySecurityContext
派生。我想直接注入MyThing
以使代码清洁。
有没有办法做到这一点?根据{{3}},使用ContextResolver
无法完成,this question和this article表示可能。
使用身份验证过滤器,我可以使用以下代码设置自定义安全上下文:
@Provider
public class HttpTokenAuthFilter implements IComposableJaxRsAuthFilter {
@Override
public boolean doAuth(ContainerRequestContext requestContext) throws WebApplicationException {
// error handling omitted
requestContext.setSecurityContext(MySecurityContext.fromHeaders(requestContext));
}
}
...然后在我的资源中我可以从中提取一个值:
@Path("/foo")
public class MyResource {
@Context
private SecurityContext securityContext;
@Get
public String doGetFoo() {
MyThing myThing = ((MySecurityContext)securityContext).getThing();
// use myThing to produce a result
}
...但是,由于这将重复很多,我宁愿写一下:
@Context
private MyThing myThing;
我尝试定义ContextResolver
。我看到它正在构建,但我从未看到它被调用,所以我还没有尝试过任何上面链接的技术。这甚至是正确使用的类吗?
@Provider
public class MyThingResolver implements ContextResolver<MyThing> {
public MyThingResolver() {
System.out.println("ctor");
}
@Override
public MyThing getContext(Class type) {
System.out.println("getContext");
if (type.equals(MyThing.class)) {
return new MyThing(); // TODO: SHOULD ACTUALLY USE CURRENT MySession
}
return null;
}
}
答案 0 :(得分:1)
根据this answer以及this followup指定的优化,几乎可以使用Factory
完成注入。唯一需要注意的是,您必须通过MyThing
注入Provider
,否则它将在过滤器运行和交换之前创建(使用默认 SecurityContext
)在MySecurityContext
。
工厂代码如下所示:
public class MyThingFactory implements Factory<MyThing> {
@Context
private SecurityContext securityContext;
@Override
public MyThing provide() {
return ((MySecurityContext)securityContext).getThing();
}
@Override
public void dispose(MyThing session) {
}
}
然后资源可以像这样注入:
@Context
private Provider<MyThing> myThingProvider;
......并按照这样消费:
MyThing myThing = myThingProvider.get();
// use myThing
AbstractBinder
中的工厂注册如下所示:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.in(RequestScoped.class);
根据@peeskillet的评论,可以通过代理Provider
来摆脱MyThing
。 (Per @ jwells131313,MyThing
因此必须是一个接口或一个可代理的类。)
然后绑定看起来像这样:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.proxy(true) //
.in(RequestScoped.class);
注射最终按预期工作:
@Context
private MyThing myThing;