@ManagedProperty(value = "#param.id") 在非请求范围 Bean
Posted
技术标签:
【中文标题】@ManagedProperty(value = "#param.id") 在非请求范围 Bean【英文标题】:@ManagedProperty(value = "#param.id") in a non-request Scope Bean@ManagedProperty(value = "#param.id") 在非请求范围 Bean 【发布时间】:2011-06-02 13:22:14 【问题描述】:我需要将参数(POST)传递给@managedBean,我使用了这样的托管属性:
@ManagedProperty(value = "#param.id")
private int id;
而Bean的作用域是ViewScope
我最终得到了这个错误:
无法创建托管 bean 收据。发现以下问题: - 表达式#param.id,request所引用的对象的范围比引用的托管bean视图范围短
我能做什么?
arjan 看看:
我的页面: 小面标题
<form method="post" action="faces/index.xhtml">
<input name="id" value="4" />
<input type="submit" value="submit" />
</form>
<h:form>
<h:commandLink value="click" action="index">
<f:param id="id" name="id" value="20"/>
</h:commandLink>
</h:form>
【问题讨论】:
【参考方案1】:两种方式:
使 bean 请求限定范围并将视图范围作为另一个 @ManagedProperty
注入。
@ManagedBean
@RequestScoped
public class RequestBean
@ManagedProperty(value="#param.id")
private Integer id;
@ManagedProperty(value="#viewBean")
private ViewBean viewBean;
view scoped bean 在@PostConstruct
和 request scoped bean 的 action 方法中可用。你只需要记住id
可能会在没有参数的情况下回发到同一个视图时丢失。
或者,在 bean 初始化期间从请求参数映射中手动获取它。
@ManagedBean
@ViewScoped
public class ViewBean
private Integer id;
@PostConstruct
public void init()
id = Integer.valueOf(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id"));
这样,初始id
在整个视图范围内都可用。
【讨论】:
谢谢,第一个解决方案(在 requestScoped 中注入 viewScoped bean)是一种好的和流行的做法吗??? 我的应用程序由 GlassFish 提供服务,我也可以使用 CDI bean,但我决定使用 JSF bean 做一些项目,因为我是 JSF 的新手,这是个好主意吗? 取决于id
的用途。您想在每次请求时“刷新”它吗?选择方式 1。或者您想在整个视图范围内使用初始值?走2路。
谢谢,非常完整的描述。
@Tarik:我总是从代码 sn-ps 中省略明显性,以使答案更加集中。考虑到问题的表述方式,OP 非常清楚对 getter/setter 的需求。如果 OP 不知道,我宁愿添加像 // +getter+setter
这样的评论,而不是添加一大堆显而易见的东西。只需让您的 IDE 自动生成 getter/setter 并将它们全部隐藏在类的底部即可。【参考方案2】:
作为直接从 bean 中的请求中获取参数的替代方法,您可以使用 view parameters
。
这些需要在使用托管 bean 的 Facelet 上声明如下:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:body>
<f:metadata>
<f:viewParam id="id" name="id" value="#myBean.id" />
</f:metadata>
<!-- Rest of Facelet here -->
</h:body>
</html>
如果您现在请求此页面,将使用为 id 参数提供的请求值调用 backing bean 的 setter。这适用于GET
和(非人脸)POST
请求。
优点是您可以在此处使用标准的 JSF 转换器和验证器。当然,如果您的托管 bean 没有绑定到特定视图,那么这个解决方案就不太理想了。
需要注意的一个小特殊的事情是,在提供视图参数的初始请求之后执行普通人脸回发时,将再次调用 bean 中的设置器,即使 bean 在视图范围内并且没有新的值是明确提供的。
为了测试它是否有效,我使用了以下托管 bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
@ManagedBean
@ViewScoped
public class MyBean
Long id;
@PostConstruct
public void test()
System.out.println("post construct called");
public void actionMethod(ActionEvent event)
System.out.println("action called");
public Long getId()
return id;
public void setId(Long id)
this.id = id;
还有以下 Facelet:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:body>
<f:metadata>
<f:viewParam id="id" name="id" value="#myBean.id" />
</f:metadata>
<h:outputText value="#myBean.id"/>
<h:form>
<h:commandButton value="test" actionListener="#myBean.actionMethod"/>
</h:form>
<form method="post">
<input name="id" value="4" />
<input type="submit" value="submit" />
</form>
</h:body>
</html>
在输入字段中输入一个数字,然后单击提交按钮。如果该数字被打印回屏幕上,则测试成功。请注意,第二个表单是常规表单,并且不会同时发布任何 JSF 状态。我在 JBoss AS 6 上对此进行了测试,它可以工作。将 id 参数证明为 GET 参数也可以。
【讨论】:
据我在书籍和教程中发现,它们仅适用于 Get 参数,您确定它们可以与 Post 参数一起使用吗????... 嗯,虽然我不是这方面的权威来源,但我很确定我以前用过 POST 参数。我会再次检查并更新我的答案。 我再次测试并更新了我的答案。这只是两个文件,所以应该很容易复制。 我还查看了 Mojarra 源代码,看看这些参数最终是如何解决的。在 Mojarra 2.03 中,它位于 UIViewParameter 第 217 行: String paramValue = context.getExternalContext().getRequestParameterMap().get(getName());由于请求参数映射始终包含来自 POST 和 GET 请求的参数,因此这会自动解释它应该可以工作。然而,在 JSF 规范中没有明确声明应该支持 POST 和 GET。规范似乎并没有明确说明这一点。 感谢您为我花费的时间。祝你好运 :)。 Java 程序员和编程语言一样优秀。以上是关于@ManagedProperty(value = "#param.id") 在非请求范围 Bean的主要内容,如果未能解决你的问题,请参考以下文章
可以将@ManagedBean 作为@ManagedProperty 注入@WebServlet?
无法将 JSF ViewScoped bean 作为 ManagedProperty 注入 Validator
ViewScoped Bean 中 SessionScope 的 ManagedProperty - 瞬态?
CDI @Named bean 中的 @javax.faces.bean.ManagedProperty 返回 null