问题描述
我正在尝试编写一个自定义 servlet(用于 AJAX/JSON),我想在其中按名称引用我的 @ManagedBeans
.我希望映射:
I'm trying to write a custom servlet (for AJAX/JSON) in which I would like to reference my @ManagedBeans
by name. I'm hoping to map:
http://host/app/myBean/myProperty
到:
@ManagedBean(name="myBean")
public class MyBean {
public String getMyProperty();
}
是否可以按名称从常规 servlet 加载 bean?是否有我可以使用的 JSF servlet 或帮助程序?
Is it possible to load a bean by name from a regular servlet? Is there a JSF servlet or helper I could use for it?
我似乎被 Spring 宠坏了,这一切都太明显了.
I seem to be spoilt by Spring in which all this is too obvious.
推荐答案
在基于 servlet 的工件中,例如 @WebServlet
、@WebFilter
和 @WebListener
,你可以抓住一个普通香草"JSF @ManagedBean @RequestScoped
作者:
In a servlet based artifact, such as @WebServlet
, @WebFilter
and @WebListener
, you can grab a "plain vanilla" JSF @ManagedBean @RequestScoped
by:
Bean bean = (Bean) request.getAttribute("beanName");
和 @ManagedBean @SessionScoped
由:
Bean bean = (Bean) request.getSession().getAttribute("beanName");
和 @ManagedBean @ApplicationScoped
由:
Bean bean = (Bean) getServletContext().getAttribute("beanName");
请注意,这预先要求该 bean 已经由 JSF 预先自动创建.否则这些将返回 null
.然后您需要手动创建 bean 并使用 setAttribute("beanName", bean)
.
Note that this prerequires that the bean is already autocreated by JSF beforehand. Else these will return null
. You'd then need to manually create the bean and use setAttribute("beanName", bean)
.
如果您可以使用 CDI @命名为
而不是自 JSF 2.3 弃用的 @ManagedBean
,那么它更容易,特别是因为您不再需要手动创建 bean:
If you're able to use CDI @Named
instead of the since JSF 2.3 deprecated @ManagedBean
, then it's even more easy, particularly because you don't anymore need to manually create the beans:
@Inject
private Bean bean;
请注意,当您使用 @Named @ViewScoped
时,这将不起作用,因为 bean 只能由 JSF 视图状态标识,并且只有在 FacesServlet
时才可用> 已被调用.因此,在此之前运行的过滤器中,访问 @Inject
ed @ViewScoped
将始终抛出 ContextNotActiveException
.
Note that this won't work when you're using @Named @ViewScoped
because the bean can only be identified by JSF view state and that's only available when the FacesServlet
has been invoked. So in a filter which runs before that, accessing an @Inject
ed @ViewScoped
will always throw ContextNotActiveException
.
只有当你在 @ManagedBean
里面时,你才能使用 @ManagedProperty
:
Only when you're inside @ManagedBean
, then you can use @ManagedProperty
:
@ManagedProperty("#{bean}")
private Bean bean;
请注意,这不适用于 @Named
或 @WebServlet
或任何其他工件.它仅在 @ManagedBean
内真正有效.
Note that this doesn't work inside a @Named
or @WebServlet
or any other artifact. It really works inside @ManagedBean
only.
如果您不在 @ManagedBean
中,但 FacesContext
很容易获得(即 FacesContext#getCurrentInstance()
return null
),您也可以使用 Application#evaluateExpressionGet()
:
If you're not inside a @ManagedBean
, but the FacesContext
is readily available (i.e. FacesContext#getCurrentInstance()
doesn't return null
), you can also use Application#evaluateExpressionGet()
:
FacesContext context = FacesContext.getCurrentInstance();
Bean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);
可以方便地如下:
@SuppressWarnings("unchecked")
public static <T> T findBean(String beanName) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}
并且可以如下使用:
Bean bean = findBean("bean");
另见:
- 支持 bean (@ManagedBean) 或 CDI Bean (@Named)?
这篇关于在任何 Servlet 相关类中按名称获取 JSF 托管 bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!