凌枫佳境
风霜凌绝顶,红枫绚佳境

      相信很多人在使用JSF做开发的时候都有这种需求, 在渲染一个页面时, 执行一个动作,这里我们就称之为Page Actions。记得一年前用JSF做个项目也需要这种action, 当时的实现就是在该页面最上方添加一个属性方法调用,确保在其他组件渲染之前来调用该动作, 这种方式看起来真的不是很美观。其实要实现Facelets的Page Actions 有以下三种方式

     1、 而现在在Seam的pages.xml我们可以直接指定一个page action, 但是也许我们的项目并不需要seam这么强大的框架呢, 不能仅仅为了一个page action就大动干戈吧。

     2、Shale框架通过faces-config.xml映射一个实现了 ViewController 接口的managed bean到一个view id也可以实现page action(http://shale.apache.org/shale-view/index.html ), 但是这样需要多谢点代码。

     3、(http://www.ninthavenue.com.au/blog/easy-page-actions-with-facelets)上提供了一种使用Facelets简单实现page action的方式, 我们来看看如何实现的吧:(一下为部分文章内容翻译)

使用 Facelets TagHandlers。

首先使用 TagHandlers 来实现page actions有2个好处:

  1. 在组件树建构期间它只执行一次,所以不用担心剩下的生命周期也不会引起该表单时执行多次。
  2. 由于TagHandler直接放在view的模板中,所以不再需要一个view id和handler之间的映射了。

该TagHandler的实现非常简单:

/**

* This tag evaluates a method expression, so it can be used to implement

* 'page actions' since it is only executed when the view is built.

*/

public class ActionHandler extends TagHandler {

private final TagAttribute method;



public ActionHandler(TagConfig config) {

super(config);

this.method = this.getRequiredAttribute("method");

}



/** evaluate the method expression */

public void apply(FaceletContext ctx, UIComponent parent) {

method.getMethodExpression(ctx, null, new Class[] {}).

invoke(ctx.getFacesContext().getELContext(), null);

}

}

要使用该 action,你需要把放在 facelets taglib中:

...

<tag>

<tag-name>action</tag-name>

<handler-class>furnace.core.tags.ActionHandler</handler-class>

</tag>

然后把它放在你需要的模板中, e.g.:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:fc="http://www.ninthavenue.com.au/furnace/core">



<!-- merge the user into the current persistence context -->

<fc:action method="${modules.forums.mergeUser}"/>



<!-- then show their profile -->

<h:outputText value="${user.name}"/>

...

</ui:composition>

你应该主意,在一个postback中该 TagHandlers 并不会执行, 如果这是你需要的行为的话, 你需要使用一个 PhaseListener, 或者 Seam 和Shale .

上面的代码将会在 Seamless的下一个版中中出现, 并将重新命名为'Furnace'.

编者注: Seamless为一个JSF的个人扩展库,好像是有http://www.ninthavenue.com.au公司使用的,在上面有介绍,里面包含了一些JSF的特殊扩展。 感兴趣的可以去了解下。

posted on 2009-02-27 15:43  凌枫  阅读(391)  评论(0编辑  收藏  举报