@ManagedProperty - 将一个请求作用域的bean注入到另一个请求作用域的bean中

3

我有一个名为SearchBean的东西:

@ManagedBean(name = "searchBean")
@RequestScoped
public class SearchBean implements Serializable
{
    private String input = null;

    // getter methods
    public String getInput() {
        return input;
    }

    // setter method
    public void setInput(String input) {
        this.input = input;
    }

    public String Submit() {
        return null;
    }    
}

我可以使用@ManagedProperty将其注入到另一个bean中吗?例如:
@ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @ManagedProperty(value = "#{searchBean}")
    private SearchBean searchBean;  

    @PostConstruct
    public void init()
    {   
       System.out.println("Value: " + searchBean.getInput());
    }

    public SearchBean getSearchBean() {
       return searchBean;
    }

    public void setSearchBean(SearchBean searchBean) {
       this.searchBean = searchBean;
    }   
}

同时,还有 Facelet(search.xhtml):

<h:form id="formSearch">
   <h:commandButton value="Search" action="#{searchBean.Submit}" />
</h:form>
更新: 我已经通过 ui:insert 组件将 search.xhtml 插入到 book.xhtml 中,如下所示:
<h:form id="formBooks">
   <ui:insert name="search">
      <ui:include src="/templates/common/search.xhtml"/>
   </ui:insert> 
</h:form>

searchBean.getInput() 方法应该在表单提交后返回一个值。上述的注入方法是否可行?


@user:我删除了我的回答,因为那只回答了你的最初问题,即托管属性注入是否有效(显然是“是”),但McDowell更好地回答了你的真正问题(即在调用@PostConstruct时该属性为空)。 - BalusC
@BalusC:当我刷新后,你的答案消失了,我以为是我的浏览器出了问题。对不起,我的错。我仍在尝试通过实际示例来学习规范,但有时会遇到困难,不知道如何前进。不过还是谢谢你的回答。 - ChuongPham
1个回答

9

我假定SearchBean.input将被绑定到输入框

public class SearchBean implements Serializable {
    private String input = null;

像这样的东西:

<h:inputText value="#{searchBean.input}" />

如果是这样,那么这将为空:
@PostConstruct
public void init()
{   
   System.out.println("Value: " + searchBean.getInput());
}

但是,假设已经设置了一个值,在调用此方法时它不会为空:

public String Submit() {
    return null;
}

Image from Richard Hightower's JSF for nonbelievers: The JSF application lifecycle

来源于Richard Hightower的JSF for nonbelievers: The JSF application lifecycle的图片。

原因在于JSF生命周期的工作方式:

  1. #{searchBean...}首次解析并发现不存在时:
    • 实例化bean
    • 执行任何依赖注入(在这种情况下没有)
    • 调用@PostConstruct方法
    • 将bean放入范围内
  2. 假设应用请求值和验证阶段成功,SearchBean.setInput(String)在更新模型值阶段中被调用
  3. SearchBean.Submit()在调用应用程序阶段中被调用

此过程在JSF规范中定义。


现在,如果直接从参数映射中注入SearchBean.input,则在@PostConstruct期间它不会为空:
@ManagedProperty(value = "#{param.someParamName}")
private String input;

然而,这样做并没有真正的优势 - 您跳过了任何输入验证,并且无法将 SearchBean.input 用作字段绑定,因为它将在更新模型值阶段被覆盖。 SearchBean.Submit() 方法是您执行搜索的应用程序逻辑所在的位置。

@McDowell:规范的那部分对我来说还有点模糊,所以我想做一个实际的例子来看看它是如何工作的。你是对的:我将searchBean#input绑定到了h:inputText,根据你的解释,返回的值将为null - 这就解释了为什么在提交表单时我得到了null。你能否用一些代码示例来解释一下如何在SearchBean.Submit()方法中设置值?我不理解这一部分。 - ChuongPham
@user463053 - 在更新模型值期间,输入控件将设置SearchBean.input;当在调用应用程序期间调用Submit()方法时,您只需引用this.input即可。 - McDowell
那是另一种方式。我的意思是将动作方法submit()放在BookBean中,让命令按钮指向它,最后在该动作方法中完成数据库工作。 - BalusC
@McDowell:这意味着我的BookBean数据库逻辑需要移动到SearchBean才能使用this.input。或者,我是否完全误解了您的评论?-:) - ChuongPham
@BalusC:我理解,那么我需要在BookBean中复制getInputsetInput方法以及Submit方法。 - ChuongPham
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接