1

据我所知,CDI应该使用过滤器,但是我无法让它为我工作。代码如下所示:@Inject in filter does not work

@WebFilter(filterName="authFilter",servletNames={"Faces Servlet"}) 
public class AuthFilter implements Filter { 

    @Inject UserBean userBean; 

    public AuthFilter() { 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 
     userBean.doSomething(); // Causes NullPointerException 
     chain.doFilter(request, response); 
    } 
} 

UserBean.class

@Stateless 
public class UserBean extends JPABean{ 
// Omitted 
} 

CDI启用,并注入工作,如果我通过InitialContext.doLookup(做手动),或在Servlet中,像这样的:

@WebServlet(name = "MyServlet", urlPatterns = {"/MyPage"}) 
@ServletSecurity(@HttpConstraint(rolesAllowed={"somerole"})) 
public class MyServlet extends HttpServlet { 

    @Inject private UserBean userBean; 

    @Override 
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     userBean.doStuff(); // Works 
     response.sendRedirect(request.getContextPath()); 
} 

CDI不在滤镜中工作吗?在那种情况下,为什么不呢?如果应该的话,我可能会做错什么?

+0

什么容器? JBoss AS 6有一个非常类似的bug。如果你只是使用'@EJB',它会起作用吗? – BalusC

+0

JBoss AS 6确实...... @EJB可能会工作。非常恼人的是,我最后通过InitialContext进行了手动注入,但很好理解。 –

回答

3

在这个例子中,我将一个CODI @ViewAccessScoped bean(RegisterView)注入到一个过滤器中,在bean中设置一个属性并导航到一个使用该bean的视图。当页面加载时,我将用户名设置为“fred”。这也适用于@SessionScoped(但不是@RequestScoped或@ViewScoped)。我认为动态注入是线程安全所必需的,因为web容器中只有一个过滤器实例,因此所有实例变量都是如此。

这个问题解决的问题是Faces Servlet在执行过滤器时没有运行,所以没有FacesContext。由getFacesContext()完成的巧妙工作我从2004年直接从这个blog中解脱出来,我不知道它是由谁写的,并且几年内没有添加任何内容,但是如果有人知道让我知道!也许这是BalusC在他年轻时的 。它使用静态内部类来访问受保护的FacesServlet#setCurrentInstance()方法。

如果您使用response.sendRedirect(),它不起作用。

package uk.co.myco.jsfbeans.helper; 

import java.io.IOException; 
import javax.enterprise.inject.Instance; 
import javax.faces.FactoryFinder; 
import javax.faces.component.UIViewRoot; 
import javax.faces.context.FacesContext; 
import javax.faces.context.FacesContextFactory; 
import javax.faces.lifecycle.Lifecycle; 
import javax.faces.lifecycle.LifecycleFactory; 
import javax.inject.Inject; 
import javax.servlet.DispatcherType; 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletContext; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.annotation.WebFilter; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import uk.co.sportquest.entities.User; 
import uk.co.sportquest.general.BaseClass; 
import uk.co.sportquest.general.Log; 
import uk.co.sportquest.jsfbeans.RegisterView; 

/* 
* @author Brendan Healey 
* 
* http://www.thoughtsabout.net/blog/archives/000033.html 
* 
*/ 

@WebFilter(filterName = "SocialAuthFilter", urlPatterns = {"/pages/socialAuthFilter.xhtml"}, 
dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.ERROR, DispatcherType.REQUEST, DispatcherType.INCLUDE}) 
public class SocialAuthFilter extends BaseClass implements Filter { 

    @Inject 
    private Instance<RegisterView> rvDynamic; 

    private ServletContext servletContext; 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     servletContext = filterConfig.getServletContext(); 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 

     Log.log("testFilter: " + request.getPathInfo()); 

     FacesContext ctx = getFacesContext(req, res); 

     RegisterView registerView; 
     registerView = rvDynamic.get(); 

     User user = new User(); 
     user.setUserName("fred"); 
     registerView.setInputUser(user); 

     FacesContext.getCurrentInstance().getExternalContext().redirect("/pages/register.xhtml"); 

    } 

    @Override 
    public void destroy() { 
    } 

    private abstract static class InnerFacesContext extends FacesContext { 

     protected static void setFacesContextAsCurrentInstance(FacesContext facesContext) { 
      FacesContext.setCurrentInstance(facesContext); 
     } 
    } 

    private FacesContext getFacesContext(ServletRequest request, ServletResponse response) { 
     // Try to get it first 
     FacesContext facesContext = FacesContext.getCurrentInstance(); 
     if (facesContext != null) { 
      return facesContext; 
     } 

     FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); 
     LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); 
     Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); 

     // Either set a private member servletContext = filterConfig.getServletContext(); 
     // in you filter init() method or set it here like this: 
     // ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext(); 
     // Note that the above line would fail if you are using any other protocol than http 

     // Doesn't set this instance as the current instance of FacesContext.getCurrentInstance 
     facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle); 

     // Set using our inner class 
     InnerFacesContext.setFacesContextAsCurrentInstance(facesContext); 

     // set a new viewRoot, otherwise context.getViewRoot returns null 
     UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, ""); 
     facesContext.setViewRoot(view); 

     return facesContext; 
    } 

}