【问题标题】:Guice: Injecting Interceptors in ServletModuleGuice:在 ServletModule 中注入拦截器
【发布时间】:2012-02-01 12:17:22
【问题描述】:

我正在尝试使用 Guice 创建的 Vaadin 应用程序实例注入拦截器。 我已经按照Vaadin Wiki 中的 Vaadin-Guice 集成文档和 Guice Wiki 中有关 Interceptor DI 的文档:

public class RecruitmentServletConfig extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {

        ServletModule servletModule = new ServletModule() {

            @Override
            protected void configureServlets() {
                ...
                bind(Application.class).to(RecruitmentApplication.class).in(ServletScopes.SESSION);
                SecurityGuard securityGuard = new SecurityGuard();
                requestInjection(securityGuard);
                bindInterceptor(Matchers.subclassesOf(CustomComponent.class), Matchers.annotatedWith(AllowedRoles.class), securityGuard);
            }
        };
        return Guice.createInjector(servletModule);
    }
}

SecurityGuard 拦截器:

public class SecurityGuard implements MethodInterceptor {
    @Inject private Application application;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        AllowedRoles allowedRoles = invocation.getMethod().getAnnotation(AllowedRoles.class);
        if (((User) application.getUser()).hasRole(allowedRoles.value())) {
            return invocation.proceed(); 
        } else {
            return null;
        }
}

但是,我在服务器启动时收到 OutOfScopeException:

SEVERE: Exception sending context initialized event to listener instance of class de.embl.eicat.recruit.ioc.RecruitmentServletConfig
com.google.inject.CreationException: Guice creation errors:
1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped object. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request.
at recruit.ioc.RecruitmentServletConfig$1.configureServlets(RecruitmentServletConfig.java:86)

【问题讨论】:

  • 注意 Application.class 的范围:需要为每个新用户会话创建应用程序实例(因此 .in(ServletScopes.SESSION)。但是,configure() / configureServlets() 方法是在创建任何用户会话之前在服务器启动时调用,我猜这解释了 OutOfScopeException。这是真的,应该在哪里调用 requestInjection(securityGuard)?

标签: java guice vaadin


【解决方案1】:

如果您将Application 包装在Provider 中,它是否有效?

public class SecurityGuard implements MethodInterceptor {
    @Inject private Provider<Application> application;

    public Object invoke(MethodInvocation invocation) throws Throwable {
       AllowedRoles allowedRoles = invocation.getMethod().getAnnotation(AllowedRoles.class);
        if (((User) application.get().getUser()).hasRole(allowedRoles.value())) {
            return invocation.proceed(); 
        } else {
            return null;
        }
}

【讨论】:

  • 这是正确的解决方案。通过使用提供者而不是直接引用,Guice 将在每次应用程序需要时调用提供者,而不是尝试预先进行。假设提供程序将在 vaadin 会话回调期间被调用,它会通过将应用程序从已在堆栈上设置的会话范围中拉出来成功。
猜你喜欢
  • 1970-01-01
  • 2015-10-10
  • 1970-01-01
  • 2012-08-16
  • 2012-03-18
  • 2011-09-02
  • 1970-01-01
  • 2012-11-20
  • 2022-01-16
相关资源
最近更新 更多