我正在尝试编写一个自定义servlet(用于AJAX / JSON),在其中我想按名称引用我的@ManagedBeans
。我希望映射:http://host/app/myBean/myProperty
至:
@ManagedBean(name="myBean")
public class MyBean {
public String getMyProperty();
}
是否可以从常规servlet中按名称加载bean?我可以使用JSF servlet或帮助程序吗?
我似乎对Spring感到宠爱,在Spring中所有这些都太明显了。
最佳答案
在基于servlet的 Artifact (例如@WebServlet
,@WebFilter
和@WebListener
)中,您可以通过以下方法来获取“普通 Vanilla ” JSF @ManagedBean @RequestScoped
:
Bean bean = (Bean) request.getAttribute("beanName");
和@ManagedBean @SessionScoped
通过:Bean bean = (Bean) request.getSession().getAttribute("beanName");
和@ManagedBean @ApplicationScoped
通过:Bean bean = (Bean) getServletContext().getAttribute("beanName");
请注意,这需要先由JSF自动创建bean。否则,这些将返回null
。然后,您需要手动创建bean并使用setAttribute("beanName", bean)
。如果您能够使用CDI
@Named
代替自JSF 2.3弃用的@ManagedBean
,那么它会更加容易,尤其是因为您不再需要手动创建bean了:@Inject
private Bean bean;
请注意,这在您使用@Named @ViewScoped
时将不起作用,因为只能通过JSF View 状态来标识该bean,并且仅在调用FacesServlet
时才可用。因此,在此之前运行的过滤器中,访问@Inject
和@ViewScoped
将始终抛出ContextNotActiveException
。只有在
@ManagedBean
内部时,才可以使用 @ManagedProperty
:@ManagedProperty("#{bean}")
private Bean bean;
请注意,这在@Named
或@WebServlet
或任何其他 Artifact 中不起作用。它实际上仅在@ManagedBean
内部有效。如果您不在
@ManagedBean
内,但是FacesContext
随时可用(即FacesContext#getCurrentInstance()
不返回null
),则也可以使用 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");
也可以看看: