访问在servlet-filter中注入的CDI bean中的FacesContext

时间:2017-04-26 20:52:01

标签: jsf servlets cdi servlet-filters

我有以下servlet注入CDI bean

public class FBOAuthFilter implements Filter {
    @Inject 
    private Instance<LoginBean> loginBeanSource;


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
        FilterChain fc) throws IOException, ServletException {
        try{
           String code = request.getParameter("code");
           LoginBean loginBean = loginBeanSource.get();
           loginBean.doLogin(code);
        } catch(Exception ex){
           System.out.println("Exception");
        }
   }
}

CDI Bean:

@Named(value="loginbean")
@SessionScoped
public class LoginBean implements Serializable{



     public void doLogin(String code){
        //do something

        FacesContext context = FacesContext.getCurrentInstance();
        System.out.println(context == null);
        context.getExternalContext().redirect("somepage");

    }
}

但是,当我尝试访问CDI Bean中的FacesContext时,它为null。有没有办法访问FacesContext?

1 个答案:

答案 0 :(得分:1)

这不是正确的方法。

所有过滤器在命中servlet之前 运行。 FacesContext仅在命中FacesServlet时可用。因此,只要FacesServlet尚未被点击,FacesContext都不可用。因此,在所有过滤器中始终为null

您需要以以下方式重写代码:仅使用过滤器中易于使用的requestresponse对象和CDI,而不必依赖FacesContext。看来您只想执行重定向。 “普通香草” servlet方式是:

response.sendRedirect("somepage");

为了正确使用该代码,只需将您的LoginBean代码拆分为两个新的bean:一个在任何地方都不使用javax.faces.*的东西,另一个则需要javax.faces.*的东西。然后,过滤器和托管Bean都可以共享不在任何地方使用javax.faces.*的东西。

@Dependent
public class LoginBeanWithoutFacesContext implements Serializable {

    public void doLogin(String code) {
        // do something without faces context
    }
}

@Named
@SessionScoped
public class LoginBean implements Serializable {

     @Inject
     private LoginBeanWithoutFacesContext loginBeanWithoutFacesContext;

     public void doLogin(String code) {
         loginBeanWithoutFacesContext.doLogin(code);

         FacesContext context = FacesContext.getCurrentInstance();
         context.getExternalContext().redirect("somepage");
    }
}

最后在过滤器中使用LoginBeanWithoutFacesContext

public class FBOAuthFilter implements Filter {

    @Inject 
    private LoginBeanWithoutFacesContext loginBeanWithoutFacesContext;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            String code = request.getParameter("code");
            loginBeanWithoutFacesContext.doLogin(code);
            response.sendRedirect("somepage");
        }
        catch (Exception e) {
            throw new ServletException(e);
        }
    }
}

也就是说,考虑对您显然在LoginBeanWithoutFacesContext中从事的工作使用JEE标准身份验证或完善的库,而不要使用某些本地认证。另请参见How to handle authentication/authorization with users in a database?