Spring 会话 bean 将 FacesContext.getCurrentInstance() 视为空引用

Spring session bean sees FacesContext.getCurrentInstance() as Null reference

我有一个 Actor class 来处理用户会话范围内的数据

    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    @Component(value = "actor")
    @Scope(value = "session")
    public class Actor{
        public Actor() {
            System.out.println("Inside void init Actor..........");
            System.out.println(JsfUtils.getFacesContext());// This prints Null

      }
    }

web.xml

<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">      
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
   <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
</web-app>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">
    <context:load-time-weaver aspectj-weaving="off" />
    <task:scheduler id="taskScheduler"/>
    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="2" />
        <property name="maxPoolSize" value="8" />
        <property name="queueCapacity" value="2000" />
    </bean>
    <task:annotation-driven executor="taskExecutor" scheduler="taskScheduler"/>


    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>    
    <bean id="contextApplicationContextProvider" class="net.main.spring.context.ApplicationContextProvider"></bean>

//    <context:component-scan base-package="net.main.x">//</context:component-scan> more goes here


    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="Default_Persistence_Unit"/>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="MYSQL"/>
                <property name="showSql" value="false"/>
            </bean>
        </property>
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
        </property>
    </bean>
    <bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <tx:annotation-driven  transaction-manager="jpaTransactionManager" proxy-target-class="true"/>

</beans>

在旧项目中运行良好,所以我认为 JSF 的版本是我使用 2.2.12 版和 Spring 4.1.4 的原因。我尝试降级 JSF 版本或升级 Spring 版本,但没有成功。另一个问题是 Actor 构造函数被多次调用。

所以这里有隐藏的行为吗,Spring 应该看到 FacesContext 是真的吗,因为请求是由 JSF servlet 映射的,或者它不能,因为 FacesContext 在另一个范围。

我假设 Spring 是在 JSF 之前初始化的,因此它将 FacesContext 视为空,如果是这样的话,您如何订购初始化容器

提前致谢

我有 LoggedInFilter 没有发布在问题上

public class LoggedInFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            Actor actor = SpringUtils.getBean(Actor.class);
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            String uri = req.getRequestURI();
            boolean isAdminPage = uri.contains("/cpanel/");
            if (!actor.isLoggedIn() && (uri.contains("/select-issue") || isAdminPage)) {
                request.getRequestDispatcher("/login.html").forward(request, response);
            } else if (isAdminPage) {
                if (actor.isAdmin()) {
                    chain.doFilter(request, response);
                } else {
                    res.sendRedirect("/404.html");
                }
            } else {
                chain.doFilter(request, response);
            }

        } catch (Exception ex) {
            SystemLogger.getLogger(getClass().getSimpleName()).error(ex.getMessage());
        }
    }

挖掘问题发现原因在过滤器上

过滤器看不到 FacesContext,因为 Faces servlet 尚未在过滤器范围上初始化,请参阅此 answer 了解更多信息 因此,当在过滤器上注入 actor 时,它的构造函数开始,如果您当时尝试使用 FacesContext

,则会抛出 BAM NullPointerException

我的错误我真的不认为过滤器会影响对问题的理解因此我可以看到没有人能在第一时间解决这个问题对不起大家