相信很多人在使用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个好处:
- 在组件树建构期间它只执行一次,所以不用担心剩下的生命周期也不会引起该表单时执行多次。
- 由于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的特殊扩展。 感兴趣的可以去了解下。