Spring Jersey在请求范围内的类上注入ContainerRequestContext

时间:2016-03-17 13:40:37

标签: java spring jersey

我已经查看了很多帖子,似乎没有什么能像我喜欢的那样工作。

我想从过滤器中将一个对象注入到ContainerRequestContext属性中,稍后在其他类中检索它。

这是我的过滤器:

@Priority(Priorities.AUTHENTICATION)
public class AuthorizationFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {

        containerRequestContext.setProperty("myObject", new Object());
    }
}

这是我想要访问ContainerRequestContext的类:

@Provider
public class SessionContextProvider implements ISessionContextProvider {
    @Context
    private ContainerRequestContext request;

    @Override
    public Object getSessionContext() {
        return request.getProperty("mySessionContext");
    }
}

和我的春季配置:

@Bean(name="sessionContextProvider")
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ISessionContextProvider sessionContextProvider() {
    return new SessionContextProvider();
}

如果我将ContainerRequestContext注入到我的网络资源中,那么一切都按预期工作。但是,如果调用我的提供者类ContainerRequestContext始终为null。

我似乎不知道为什么这不起作用。

Reagrds 纳斯

2 个答案:

答案 0 :(得分:1)

问题在于,通过Jersey / Spring集成,它允许我们成功地将Spring bean注入到Jersey组件中,但反过来情况并非总是如此。

泽西岛拥有自己的DI框架,HK2 1 ,它负责处理泽西组件的注射。通过Jersey Spring集成,Jersey将查找Spring Bean,并按原样使用它,它不会注入任何依赖项,我想假设Spring应该注意它自己的注入。

话虽这么说,如果你不要求 ISessionContextProvider成为一个Spring bean,那么你可以把它变为HK2服务。这很简单。如果您不需要任何特殊初始化,您可以让HK2创建它。这里有一个简单的配置

public JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        register(new AbstractBinder() {
            bind(SessionContextProvider.class)
                    .to(ISessionContextProvider.class)
                    .in(RequestScoped.class);
        });
    }
}

就是这样。您有一个注射剂ISessionContextProvider 2

如果你需要ISessionContextProvider提供者是一个Spring bean,那么另一个选择是从Spring ApplicatinContext中获取bean,并使用HK2的类似物自己明确地注入它。 ApplicationContextServiceLocator。要做到这一点,我们需要使用Factory来透明地完成所有工作,这样你仍然可以注入bean而不需要在外面做任何额外的工作

import javax.inject.Inject;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.ServiceLocator;
import org.springframework.context.ApplicationContext;

public class SessionContextProviderFactory 
        implements Factory<SessionContextProvider> {

    private final ISessionContextProvider provider;

    @Inject
    public SessionContextProviderFactory(ApplicationContext ctx,
                                         ServiceLocator locator) {
        provider = ctx.getBean(ISessionContextProvider.class);
        locator.inject(provider);
    }

    @Override
    public ISessionContextProvider provide() {
        return provider;
    }

    @Override
    public void dispost(ISessionContextProvider provider) { /* noop */ }
}

然后注册工厂

public JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        register(new AbstractBinder() {
            bindFactory(SessionContextProviderFactory.class)
                    .to(ISessionContextProvider.class)
                    .in(RequestScoped.class);
        });
    }
}

1 -
2 - 另见Dependency injection with Jersey 2.0

答案 1 :(得分:0)

我找到了解决方法。我可以将Spring HttpServletRequest注入我的AuthorizationFilter并在此上设置SessionContext。

@Autowired
private HttpServletRequest request;

....

request.setAttribute("mySessionContext", sessionContext);

然后因为我知道HttpServletRequest会弹出并在我的SessionContextProvider中表示同样的事情我会这样做:

@Autowired
private HttpServletRequest request;

@Override
public SessionContext getSessionContext() {
    return (SessionContext) request.getAttribute("mySessionContext");
}

我不认为这是最好的解决方案。但它的确有效。如果有更好的解决方案,请等待peeskillet进行任何其他输入。

此致 纳斯