0

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

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

  1. 复合组件看起来像这样<my:article article="#{interestedBean.article}" />
  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?我试图设置Article值使用@ManagedProperty(value="#{param.article}")<h:outputText>形式,因此值作为randomformname:article.

对不起我的英语不好

4

1 回答 1

2

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

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

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

@ManagedBean
@RequestScoped
public class BaseBean {

    private Article article;

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

}

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

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

在视图之间共享信息

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

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

bean 将与 reagrd 到 article 对象相同。

@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 的属性。

使用获取参数进行页面加载

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

  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 提供的这两种方式的非常有用的比较。

例如,可以通过简单的 来处理到该视图的导航,<h:link>例如

<h:link value="Manipulate" outcome="manipulation.xhtml" >
    <f:param name="articleId" value="#{baseBean.article.id}" />
</h:link>
于 2013-02-14T07:48:36.163 回答