过滤器中的@Inject不起作用

发布于 2024-12-10 14:28:04 字数 1247 浏览 0 评论 0原文

据我所知,CDI 应该在过滤器中工作,但我无法让它为我工作。代码如下所示:

@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());
}

Do not CDI work in Filters?既然如此,为什么不呢?如果应该的话,我可能做错了什么?

As far as I know, CDI should work in filters, but I can't get it to work for me. Code looks like the following:

@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 is enabled, and injection works if I do it in manually via InitialContext.doLookup() or in a Servlet, like this:

@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());
}

Does not CDI work in Filters? In that case, why not? If it should, what could I possibly be doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

剩一世无双 2024-12-17 14:28:04

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

此方法解决的问题是,当过滤器执行时,Faces Servlet 尚未运行,因此没有 FacesContext。 getFacesContext() 所做的巧妙工作是我直接从 2004 年的博客中摘取的,我不知道是谁写的,而且已经好几年没有添加内容了,但如果有人知道请告诉我!也许是 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;
    }

}

In this example I inject a CODI @ViewAccessScoped bean (RegisterView) into a filter, set a property in the bean and navigate to a view which uses the bean. When the page loads I see the username set to "fred". This also works with @SessionScoped (but not @RequestScoped or @ViewScoped). I think dynamic injection is required for thread safety because there is only one instance of the filter in the web container and hence all instance variables.

The problem this is solving is that Faces Servlet hasn't run when the filter executes so there is no FacesContext. The clever work done by getFacesContext() I have lifted straight from this blog from 2004, I don't know who it was written by and there has been no content added for some years, but if anyone knows let me know! Maybe it was BalusC in his
younger days. It uses a static inner class to access the protected FacesServlet#setCurrentInstance() method.

It doesn't work if you use 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;
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文