【问题标题】:get <h:outputText> as ManagedProperty in backing bean在支持 bean 中获取 <h:outputText> 作为 ManagedProperty
【发布时间】:2013-02-13 18:23:54
【问题描述】:

首先我想说我是 JSF 的新手。

我想创建简单的复合组件,可用于编辑文章。它应该以这种方式工作:

  1. 复合组件看起来像这样&lt;my:article article="#{interestedBean.article}" /&gt;
  2. ArticleBean负责处理复合组件的数据(这里是save方法)
  3. 每个想要使用文章的页面都需要添加复合组件到视图和Article对象到后台bean
  4. Article 对象将被传递给复合组件,其值将在 ArticleBean 中更改

问题是我不知道如何通过视图将实体(Article 对象)从一个 bean(感兴趣的 bean)传递到另一个(ArticleBean)。

示例(伪代码;假设 Article 实体是简单的 String 对象,因此我们不需要使用转换器):

// input bean
public class HomePageBean {
    private Article article;
    @PostConstruct
    public void init() {
        this.article = new Article();
        this.article.setText("welcome on home page");
    }
    public void setArticle(Article article) {
        this.article = article;
    }
    public Article article() {
        return article; // on real page article will be taken from database
    }
}

// view
<h:form>
    <h:outputText value="#{articleBean.article.text}">
        <f:attribute name="value" value="#{homePageBean.article.text}" />
    </h:outputText>
</h:form>

// output bean
public class ArticleBean {
    private Article article;
    public void setArticle(Article article) {
        this.article = article;
    }
    public Article getArticle() {
        return article;
    }
    public void save() {
         // save article data to database
    }
}

// entity
public class Article {
    private article text;
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
}

问题是SecondBean.entity.text 值没有设置。如何从视图将参数传递给支持 bean?我试图使用@ManagedProperty(value="#{param.article}") 设置Article 值,但&lt;h:outputText&gt; 的形式是这样,所以该值作为randomformname:article 传递。

对不起我的英语

【问题讨论】:

  • 欢迎来到stackoverflow!在继续讨论复合组件之前,请务必了解 JSF 的基本功能和框架中的通信。 Java EE tutorialBalusC tutorial 是一个非常有价值的资产,它们本质上是对许多 JSF 特性的概述。

标签: java jsf-2 managed-bean


【解决方案1】:

实际上这个问题需要澄清。所以我对你可能想做的事情有两个基本的想法。

在一个视图上简单共享信息

如果您想在同一个视图上共享信息,您可以使用@ManagedProperty 在彼此之间注入托管 bean。请记住,注入的 bean 的作用域不会比它注入的 bean 小。实际上,如果您只需要一个文章对象,那么我看不出在您的情况下使用两个托管 bean 的原因,但您仍然可以使用

@ManagedBean
@RequestScoped
public class BaseBean {

    private Article article;

    @ManagedProperty(value="#{injectedBean}")
    private InjectedBean injectedBean;

}

要初始化您希望相同的托管 bean 的两个属性,您可以使用带有 @PostConstruct 注释的 init 方法(但有很多替代方法),就像这里一样

@PostConstruct
public void init() {
    Article article = new Article("Welcome");
    this.article = article;
    injectedBean.setArticle(article);
}

在视图之间共享信息

在这种情况下,用户在第一个视图中选择他想要编辑的文章,然后将其传递到第二个视图。在这种情况下,用户在一个页面 (welcome.xhtml) 上选择了他想要操作的文章,而实际操作发生在另一页面 (manipulation.xhtml) 上。

通常的做法是每个页面都由自己的 bean 备份,因此在上述设置中,“基础 bean”将失去其注入。因此,welcome.xhtml 视图将使用 一些 从某处弹出在该页面上的文章对象,并将其传递给按钮单击时的第二个视图进行操作。

bean 将与 article 对象的 reagrd 相同。

@ManagedBean
@RequestScoped
public class BaseBean {

    private Article article;

}

@ManagedBean
@RequestScoped
public class InjectedBean {

    private Article article;

}

实际的传递将发生在按钮单击期间,就像在

    <h:form>
        <h:commandButton value="Manipulation" action="manipulation.xhtml">
            <f:setPropertyActionListener target="#{injectedBean.article}" value="#{baseBean.article}"/>
        </h:commandButton>
    </h:form>

在代码中,属性操作侦听器方法正在为第二个视图实例化一个 bean,并将其属性设置为基础 bean 的属性。

使用get参数进行页面加载

有时不包含触发导航到下一个视图的命令按钮会更有意义,而是提供编辑页面的简单链接。它可以通过使用&lt;f:param&gt; 标签来实现。在 JSF 中有两种处理参数的基本方法:使用页面操作/preRenderView 事件或使用 @ManagedProperty 将它们直接注入托管 bean。

  1. 使用页面操作/preRenderView 事件

工作将由目标视图完成

<f:metadata>
    <f:viewParam id="articleId" name="articleId" value="#{injectedBean.id}" />
    <f:event type="preRenderView" listener="#{injectedBean.initEvent}" />
</f:metadata>

对于preRenderView事件和

<f:metadata>
    <f:viewParam id="articleId" name="articleId" value="#{injectedBean.id}" />
    <f:viewAction action="#{injectedBean.initEvent}" />
</f:metadata>

用于页面操作。托管 bean(InjectedBean 对象)将具有以下 init 方法

public void initEvent() {
    if (id == null) {
        String message = "No id specified in request";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
        return;
    }
    //use your service method to load the article
    //article = articleService.findById(id);
    //and add messages appropriately
}
  1. 使用@ManagedProperty注解

这项工作将通过以下bean方法完成,使用@PostConstruct进行注释,并进行参数依赖注入。请记住,要使设置正常工作,bean 必须是 @RequestScoped,但对于其他 bean 范围还有解决方法。

@ManagedProperty(value="#{param.articleId}")
private Integer id;

@PostConstruct
public void initPostConstruct() {
    if (id == null) {
        String message = "No id specified in request";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
        return;
    }
    //use your service method to load the article
    //article = articleService.findById(id);
    //and add messages appropriately
}

bean 将在下一个视图期间以任何方式初始化 (manipulation.xhtml)。 BalusC 提供的这两种方式的非常有用的比较,可以找到here

可以通过简单的&lt;h:link&gt; 来处理到该视图的导航,例如

<h:link value="Manipulate" outcome="manipulation.xhtml" >
    <f:param name="articleId" value="#{baseBean.article.id}" />
</h:link>

【讨论】:

  • 感谢您的帮助! @skuntsel,我认为&lt;f:setPropertyActionListener/&gt; 会帮助我。我现在正在工作,所以我回家时会检查一下。简而言之,我将有很多将使用文章的 bean,我不想在每个 bean 中注入 ArticleBean。我认为只注入Article 实体会更容易,所以最好的解决方案是复制Article 实体。给你点!
  • 不客气!顺便说一句,如果对您有帮助,您可以随时接受答案。
  • 作为旁注,您可能还想在 ajax 请求上重新渲染您的复合组件和/或制作文章列表并制作许多“操作”按钮以在新的/当前视图。
猜你喜欢
  • 2017-06-14
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 2023-03-07
  • 2012-08-27
  • 1970-01-01
  • 2013-02-04
  • 1970-01-01
相关资源
最近更新 更多