如何在 CXF 中的 ContainerRequestFilter 中注入 ResourceInfo

How to inject ResourceInfo in a ContainerRequestFilter in CXF

我正在尝试使用 Apache CXF 和 Spring 构建基于令牌的身份验证和授权系统。我完全按照 this fantastic post 来做这件事。 但是我一开始就遇到了 AuthorizationFilter 的问题。我已经看到很多 posts、apache JIRA、github 评论,但还没有找到解决这个看似 CXF 问题的方法。

@PreMatching
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;

@Context
public void setResourceInfo(ResourceInfo resourceInfo) {
    this.resourceInfo = resourceInfo;
}

@Override
public void filter(final ContainerRequestContext requestContext) throws IOException {

    Method method = resourceInfo.getResourceMethod();

在上面的代码中,注入的 resourceInfo 是一个 代理对象 ,它具有 none 的关联属性。因此,来自那个 resourceInfo 对象的任何东西都返回 null,更具体地说 resourceInfo.getResourceMethod()null,导致 NPE。 这是关于这个问题的 JIRA post,说:

In some circumstances (like using @ApplicationScoped annotation for example) the CDI runtime will create a proxy class for a particular bean. As the result, the CXF side is going to bind the particular provider metadata to this proxy instance. It looks logical and unambiguous.

However, the interesting things are happening when CXF will try to inject contextual proxies (@Context annotations) into the provider instance. The injections are successful but the target object for them will be the proxy instance (not the real instance behind it). Consequently, at runtime, when the proxy delegates the call to a backing instance, all contextual proxies are null in there (simply put, not set).

Referring to the recent discussions with Sergey Beryozkin, the best solution would be to delegate the @Context annotation to CDI framework (as such, relieving the CXF from doing the injection work). This proposal may need a support from the JAX-RS specification side.

Simpler (interim?) possible solution would be to complement the CDI injection with @Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach).

Regarding constructor injection, it seems like CXF does not support passing the arguments to provider constructor (in case of CDI, w/o @Context annotation) so I it would be another (separate) issue to look at.

谁能帮我指出这个更简单的方法是关于什么的:

Simpler (interim?) possible solution would be to complement the CDI injection with @Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach)

或者有没有其他方法,Spring Framework 可以以正确的方式注入 ResourceInfo 对象?

我已经在我的 applicationContext.xml 中注册了这样的过滤器:

<jaxrs:server id="endpoints">
    <jaxrs:providers>
            <ref bean="authenticationFilter" />
            <ref bean="authorizationFilter" />
        </jaxrs:providers>
    </jaxrs:server>

问题是 @PreMatching 注释。

Global binding annotation that can be applied to a container request filter to indicate that such filter should be applied globally on all resources in the application before the actual resource matching occurs.

关键是高亮部分"before the actual resource matching occurs"。因此,即使在资源与请求匹配之前,过滤器也会被调用。而如果还没有匹配到的资源,那么就不可能从ResourceInfo中得到任何信息。如果您只是删除 @PreMatching 注释,则在找到 匹配资源后 将调用过滤器,您将能够访问 [=11] 中的所有信息=].