我有一个 Jersey REST 应用程序,具有基于令牌的用户身份验证。当请求传入时,将创建一个自定义
RestContext
对象并将其作为属性添加到 ContainerRequestContext
(通过在收到请求后立即运行的过滤器)。此上下文管理用户授权(通过角色)和对其他业务逻辑的访问。它可在资源中用于执行业务逻辑。处理请求后,RestContext
会在管道末端执行的第二个过滤器中被清理。
虽然需要两个过滤器,但效果很好。我一直在阅读有关 HK2 和
InjectionResolver
的使用的信息,我想知道是否可以使用注入将这个 RestContext
注入到我的资源和其他过滤器中(例如,我有一个过滤器,可以从SecurityContext
)但我找不到答案。一般来说,如何根据请求上下文为每个请求注入一个对象?这可能吗?有没有更简单的方法,例如使用 RestContext
?编辑
:正如所指出的,我基本上试图按照文档的方式在我的资源中注入一个自定义类。但是,我似乎无法正确注册我的 @Context
来绑定我的类的注入。我得到以下信息:
AbstractBinder
编辑2:我设法取得了一些小小的进展。我通过以下方式创建配置:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=RestContext,parent=RestContextFilter,qualifiers={}),position=0,optional=false,self=false,unqualified=null,1435496015)
因为文档明确指出绑定程序的注入不支持通过类而是通过实例
new ResourceConfig(allResources())
.packages(packagesToScan())
.registerInstances(new RestContextBinder());
RestContext 在请求/响应过滤器中经过
A MultiException has 3 exceptions. They are:
1. java.lang.IllegalStateException: Not inside a request scope.
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of my.package.RestContextFilter errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on my.package.RestContextFilter
编辑。然后它被用来创建一个
@Inject
并将其设置在 SecurityContext
中,并在响应过滤器中被清除。响应过滤器请求没有范围吗?为什么我会收到错误消息?既然 Jersey 2.7 已经出来了,解决方案就更简单了。 听起来您想要一个
ContainerRequestContext
绑定。以下是如何使用 Jersey 2.7 进行设置:
您将需要一个请求过滤器,并且因为RequestScoped
将是
RestContext
,您可以将提供程序注入到您的过滤器中,在其上设置一些属性,并知道它们将可用于请求的其余部分。RequestScoped
您需要注册过滤器并使用 HK2 绑定将
@Priority(Priorities.AUTHORIZATION) // filter deals with roles, comes after AUTHENTICATION
public class RestContextFilter implements ContainerRequestFilter
{
// you need to inject a provider, rather than the class directly
// because this filter is instantiated before the request scope is ready
private Provider<RestContext> rcProvider;
@Inject
public RestContextFilter(Provider<RestContext> rcProvider)
{
this.rcProvider = rcProvider;
}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// now you're in a request scope and can get your context
RestContext rc = rcProvider.get();
// set some properties on rc here (current user or roles or whatever)
}
}
绑定到您的
RestContext
中:ResourceConfig
然后您可以在资源中注入
public class MyResourceConfig extends ResourceConfig
{
public MyResourceConfig()
{
register(RestContextFilter.class);
register(new AbstractBinder()
{
@Override
protected void configure()
{
bindFactory(new Factory<RestContext>()
{
@Override
public RestContext provide()
{
return new RestContext();
}
// this will get called at the end of the request
// allowing you to close your request scoped object
@Override
public void dispose(RestContext instance)
{
instance.close();
}
}, RequestScoped.class).to(RestContext.class).in(RequestScoped.class);
}
});
}
}
,它将包含您的过滤器设置的所有信息。例如:
RestContext
与字段注入相比,我更喜欢构造函数注入,因为我认为这对于阅读您的代码的其他开发人员来说,它使您的依赖关系更加明显。