将<h:outputtext>作为托管bean中的ManagedProperty </h:outputtext>

时间:2013-02-13 18:23:54

标签: java jsf-2 managed-bean

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

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

  1. 复合组件看起来像<my:article article="#{interestedBean.article}" />
  2. ArticleBean负责处理复合组件的数据(此处为save方法)
  3. 每个想要使用文章的页面都需要将复合组件添加到视图中,并将Article对象添加到辅助bean
  4. Article对象将传递给复合组件,其值将在ArticleBean
  5. 中更改

    问题是我不知道如何通过视图将实体(Article对象)从一个bean(感兴趣的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值。如何从视图中将参数传递给backing bean?我尝试使用Article设置@ManagedProperty(value="#{param.article}")值,但<h:outputText>的形式为randomformname:article,因此值将传递为{{1}}。

    抱歉我的英文

1 个答案:

答案 0 :(得分:2)

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

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

如果要在同一视图上共享信息,可以使用@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绑定,因此在上面的设置中,'base bean'将失去注入。因此,welcome.xhtml视图将使用从某个地方在该页面上弹出的某些文章对象,并在按钮点击时将其传递给第二个视图。

bean与文章对象的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参数进行页面加载

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

  1. 使用Page actions / preRenderView events
  2. 作业将由目标视图

    完成
    <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注释
    2. 作业将通过以下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
      }
      

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

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

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