本文介绍了在任何 Servlet 相关类中按名称获取 JSF 托管 bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个自定义 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 时才可用> 已被调用.因此,在此之前运行的过滤器中,访问 @Injected @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 @Injected @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");


另见:

09-16 23:28