Jsf 在注入servlet过滤器的CDIBean中访问FacesContext
我在下面的servlet中注入cdibeanJsf 在注入servlet过滤器的CDIBean中访问FacesContext,jsf,servlets,cdi,servlet-filters,Jsf,Servlets,Cdi,Servlet Filters,我在下面的servlet中注入cdibean public class FBOAuthFilter implements Filter { @Inject private Instance<LoginBean> loginBeanSource; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain
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");
}
}
}
但是,当我尝试访问CDIBean中的FacesContext时,它是空的。有没有办法访问FacesContext?这不是正确的方法 在命中servlet之前,所有过滤器都会运行。FacesContext仅在点击FacesServlet时可用。因此,只要FacesServlet尚未命中,那么FacesContext就不可用。所以在所有过滤器中它总是空的 您需要以这样的方式重写代码:您可以在过滤器中单独使用现成的请求和响应对象以及CDI,而不依赖FacesContext。看起来您只想执行重定向。简单的方法是:
response.sendRedirect("somepage");
为了正确使用它,只需将LoginBean代码拆分为两个新bean:一个不使用javax.faces.*东西,另一个需要javax.faces.*东西。在任何地方都不使用javax.faces.*的过滤器和托管bean都可以共享这些内容
@Dependent
public class LoginBeanWithoutFacesContext implements Serializable {
public void doLogin(String code) {
// do something without faces context
}
}
最后,在过滤器中使用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);
}
}
}
这样说,考虑使用JEE标准认证或一个已建立的库,而不是为您在LoginBeanWithoutFacesContext所做的工作进行一些本地认证。另请参见在FacesServlet中创建的FacesContext。因为过滤器是在servlet之前执行的,所以FacesContext还不可用。为什么需要FacesContext?你可以不用它吗?@tuner我的大部分业务逻辑都是在servlet筛选器中完成的,我可以做一个变通办法,将所有内容移到Faces servlet,但我想知道在servlet筛选器中访问FacesContext并获取CDI bean的实际实例,而不是代理的可能性。我知道关于这一点有一个Q/a!在过滤器中执行业务逻辑。无法直接找到它,但这将是一个很好的补充回答“请参阅”section@Kukeltje:这取决于功能要求。在这种情况下,它似乎通过某种令牌自动登录,这种令牌可以出现在任何任意URL上。在工作中使用过滤器不是不合理的。登录本身显然是自产代码,而不是使用已建立的库,这实际上往往是一种糟糕的做法。但从技术上讲,这个问题与此无关。没错,我更多的是指OP的声明,即所有业务逻辑都是在过滤器中完成的,而不是登录部分…@Kukeltje:哦,在对他的问题的评论中。对不起,我没看到。似乎与技术问题无关。
@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");
}
}
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);
}
}
}