对于所有范围的托管 bean,不太可能从您的应用程序中以编程方式执行此操作。 BalusC 已经指出了如何对应用程序范围的托管 bean 执行此操作。
了解了如何在 Mojarra 2.1(JSF 2.1 实现)中注册托管 bean;没有很多优雅的选项可用于以编程方式注册会话和请求范围的 bean。简而言之,您要么必须调用实现特定的类,要么必须创建和销毁,即自己管理 bean,而不是依赖 JSF 实现来执行此操作。
使用 bean 填充请求和会话范围(非托管方式)
注意 - 这称为“非托管方式”,因为您正在构建 bean,而不是容器。注释如@PostConstruct
and @PreDestroy
除非您自己处理它们并调用适当的方法,否则将不起作用。即使依赖注入也不起作用。
EL 表达式总是在运行时求值,因此它为您提供了足够的机会在求值之前用 beans 填充作用域(如果您有机会这样做,这可能会搬起石头砸自己的脚)。在 Mojarra(可能还有其他 JSF 实现)中,EL 解析器将依赖 ScopeHandler(或等效类)的服务来解析 EL 表达式值。 Mojarra 使用类ApplicationScopeHandler
, RequestScopeHandler
and SessionScopeHandler
获取不同范围的值。
您可以在创建新会话之后或在 JSF 实现处理请求之前填充 Session 和 Request 范围的内容。
可以完成会话范围填充(理想情况下使用HttpSessionListener
) using:
HttpSession session = request.getSession(false);
session == null ? null : session.setAttribute("<keyname>", new Bean());
The keyname
必须与您用于在 EL 表达式中引用 bean 的值匹配。
以类似的方式,您可以使用以下方式填充请求范围(最好在过滤器中完成):
ServletRequest request = ... // get the reference to the servlet request object
request.setAttribute("<keyname>", new Bean());
如果您需要了解这是如何工作的,您应该看看这些类com.sun.faces.context.SessionMap
, com.sun.faces.context.RequestMap
and com.sun.faces.context.ApplicationMap
看看上下文映射是如何在内部管理的,以及如何被使用的SessionScopeHandler
, RequestScopeHandler
and ApplicationScopeHandler
属于静态内部类的类ScopeManager
(另一个静态内部)类com.sun.faces.mgbean.BeanManager
班级。这BeanManager
class 是包含托管 bean 注册的类,下一节将讨论如何“侵入”Mojarra 的注册过程。
使用 Mojarra 类来注册 Bean
Mojarra 实现中托管 Bean 的注册是由public void register(ManagedBeanInfo beanInfo)
的方法com.sun.faces.mgbean.BeanManager
班级。访问该系统并非易事BeanManager
单独使用 JSF 或 Servlet API 的类。然而有ApplicationAssociate
Mojarra 类创建了BeanManager
实例,并且可以使用getCurrentInstance()
方法。 Thomas 的另一个答案已经演示了如何以编程方式注册托管 bean:
ApplicationAssociate.getCurrentInstance().getBeanManager().register(...)
上述方法有一个警告。这种方法不太可能在 init 方法中起作用Servlet
原因很简单getCurrentInstance
方法依赖于 ThreadLocal 变量来检索ApplicationAssociate
实例。线程局部变量由com.sun.faces.application.WebappLifecycleListener
类,因此您必须重现所使用的机制WebappLifecycleListener
类,调用ApplicationAssociate getInstance(ServletContext context)
方法,以获得对ApplicationAssociate
实例。因此,下面的代码,might be(因为我没有尝试使用它)一个更好的,如果你愿意使用 Mojarra 特定的类:
ServletContext sc = ... //get the ServletContext reference;
ApplicationAssociate.getInstance(sc).getBeanManager().register(...)
您仍然必须注意此机制产生的怪癖,因为很可能某些 Mojarra 类和实例不会在您的 Servlet 之前加载或初始化。因此,我建议加载并尝试配置您的 servletload-on-startup
值高于所使用的值FacesServlet
.