Facelets介绍,第二部分

原文:http://blog.csdn.net/leeshaoqun/article/details/1126484

Facelets文章系列的第二篇,Facelets是用来建立JSF应用程序时的一个可供选择的表现层技术。第一篇文章提供了Facelets的介绍。在这篇文章中,Jacob将会告诉你如何在JSF应用中开始使用Facelets。


准备开始

Facelets是作为JSF的一个ViewHandler实现的,可以被简便的配置到你的应用程序中。使用Facelets很简单,确保Facelets Jar(jsf-facelets.jar)在你项目的classpath中,并且对你的faces-config.xml文件做一个简单的修改就可以了。
<faces-config>
  <application>
    <!-- tell JSF to use Facelets -->
    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
  </application>
</faces-config>

JavaServer Faces默认使用JSP文件定义视图(*.jsp)。你需要在你的WEB-INF/web.xml中修改该类型。

<context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.xhtml</param-value>
</context-param>

依照上面定义的context-param,你就可以开始写Facelets并且将他们保存为以.xhtml类型的文档。你现在可以开始使用Facelets了。

内建类库

Facelets使用JavaServer Faces API 中所有UIComponents的方法和你在JSP中使用的方法一样。这就意味着你可以在线的JSF的tag类库文档

也有一个简单的JSTL的核心库提供给你<c:forEach/> 和 <c:if/>。

最后,Facelets内建了一个UI标签库提供了模板化和重用性。关于这方面更多的资料在本文的第三篇文章中。

建立一个Facelet

Facelets仅仅需要严格的XML格式。他们不依赖于XHTML语法,可以被使用到VML,SVG,甚至SOAP中。使用JSP,你通常反复的引用标签库,而Facelets只需要在编译期间找到命名空间即可,和JSPX类似。这里是一个XHTML文档的开始部分:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" 
        content="text/html; charset=iso-8859-1" />
<title>My First Facelet</title>
</head>
<body>
	  <!-- body content goes here -->
	  Hello #{param.name}!
</body>
</html>

你可以把这段代码保存为test.xhtml然后即刻请求test.jsf?name=Jacob(如果你的FacesServlet被map到*.jsf)。这是一个很好的用来确保你已经正确设置Facelets的测试。

使用EL

Facelets使用JSF中新的EL-API规范。这就意味着你可以交替使用${ } 或者 #{ },而不像是JSP。如上例所示,表达式可以内嵌正则文本。

如果你使用JSF1.2,你可以添加你自己定义的ELResolvers来整合诸如Spring,EJB,JNDI等等。--全部都可以如果你需要的话。你甚至可以拥有适合你应用程序对象的ELResolvers。

EL-API是JSP2.1规范的一部分,但是不依赖于JSP或者JSF。这就意味着它可以和Facelets一起被应用到任何部署中。

使用组件

在上面的test.xhtml实例中,你发现了额外的命名空间被申明。这些和JavaServer Faces API中内建的JSP标签库的命名空间相同。再次,Facelets期望建立在常见的领域和文档之外。

当你使用Facelets中内建的JSF组件,有一个标签库文档是一件很好的事。

既然我们已经有了test.xhtml作为开始,让我们来创建一个简单的表单。将下面的代码加入你页面的body中:

<h:form>
    <h:inputText value="#{person.name}"/>
    <h:commandButton action="#{person.action}"/>
</h:form>

下面的步骤将是创建你自己的backingbean(BB)并修改faces-config.xml。

别名组件(jsfc)

前面的方法使用了特殊的标签,而使得他们在一个HTML编辑器工具(比如Dreamweaver)中不是特别好看。Facelets提供了一种不同的方法,使用标准HTML元素的jsfc属性来指定你页面中的组件(非常类似于Tapestry 和 Struts Shale 的 Clay plugin)

Facelets编译器寻找文档中所有组件的jsfc属性。jsfc属性的值是页面设计者用来在该页面中取代此元素值的别名。

<input type="text" jsfc="h:inputText" value="#{foo.bar}"/>

Facelets在编译的时候将会生成一个h:inputText组件,同时将会自动配置所有合适的属性。

别名组件允许设计工具看到正常的HTML input标签,而编程人员可以将之看成是一个在jsfc属性中定义的JSF组件。

Facelet 编译

第一篇文中提到的,Facelets只编译规范的XML。这些文件可以只有一行或者三行,唯一的要求就是它必须是合法的XML文档。

Facelets使用SAX来将文档编译成拥有TagHandlers的无状态树包含在一个Facelet对象中。Facelets是线程安全的并且可以被简单的应用在一次多请求的大规模部署中。Facelets在编译期间提供在JSF中使用到类库及视图操作的警告消息和报告。

执行Facelets编译是简单的,如下所示:

// grab our FaceletFactory and create a Facelet  
FaceletFactory factory = FaceletFactory.getInstance();  
Facelet f = factory.getFacelet(viewToRender.getViewId());    
// populate UIViewRoot  
f.apply(context, viewToRender);

更多关于Facelet的体系架构将会在稍后的文章中提供。

Exceptions & Debugging

Facelets注重了错误操作的解决。举个例子,有次你不小心的打错了一个属性的表达式,Facelets将会在编译期间自动生成一条如下的错误信息:

greeting.xhtml @18,97 <input action="#{success[}"> Error Parsing: #{success[}

正如你所看到的,Facelets为你提供了错误消息来告诉你什么文件哪一行哪一列发生了错误。它甚至提供了发生错误的元素及属性。

Facelets也使用java.util.logging包来打印出排错消息。你可以阅读这里来了解如何在你的JRE中设置日值。

自定义组件

Facelets允许你使用一个XML文件或者Java代码来自定义你自己的组件库,但是在此篇文中我将只会涉及使用XML配置,因为XML配置是更好的选择。

<facelet-taglib>    
		<namespace>http://www.mycompany.com/jsf</namespace>
		<tag>     
			 <tag-name>bar</tag-name>
		  <component>        
				<component-type>javax.faces.Data</component-type>     
          <renderer-type>com.mycompany.Bar</renderer-type>
	 		</component>    
		</tag>
</facelet-taglib>

这就是你整合你的组件到Facelets中所要做的全部工作。这些XML文档可以使用下面两种方法参考。
(译注:关于在Facelets中如何使用Tomahawk组件,可在此查阅

  1. Reference them in a ";" delimitted list within your web.xml under the init-param "facelets.LIBRARIES". These files are relative to your application, just like referencing Struts configuration files.
    在你的web.xml的init-param?facelets.LIBRARIES?中引用,使用?;?分隔不同XML配置文件。这些文档和你的应用程序有关,就如同引用Struts的配置文件一样。
  2. Package them in your JAR's META-INF folder with a file extension of ".taglib.xml". Facelets will automatically pick these up for compilation just as with JSP tld files.
    将它们打包到你的JAR文件中的META-INF文件夹中,使用一个以?.taglib.xml?结尾的文件。Facelets将会自动将这些读入编译,就好像JSP的tld文件。

在facelet-taglib文件中,你也可以指定转换器,验证器,和自定义的TagHandler来获取文件处理的的最终控制。

自定义验证器和转换器

验证器和转换器可以在Facelet中通过同一个facelet-taglib文档描述。

<facelet-taglib>    
		<namespace>http://www.jsfcentral.com/public</namespace>    
		<tag>      
				<tag-name>validateRegExp</tag-name>  
			    <validator>
					<validator-id>foo.bar.RegExp</validator-id>     
	        </validator>    
		</tag>    
		<tag>     
				 <tag-name>convertUtilDate</tag-name>
           <converter>        
              <converter-id>foo.bar.UtilDate</converter-id>
           </converter>    
     </tag>  
</facelet-taglib>

再次,由于Facelets和JavaServer Faces的API整合的很紧密,这些就是你所要定义的全部。Facelets将会自动装配这些属性到你的Converter或者是Validator对象中。

自定义组件

好的,我还没有想到但是你想在Facelets中添加你的自定义组件。这就包含了你想要为UIComponents,Validators,Converters装配各自的属性。

Facelets提供了许多基本类来使得你的工作更简单。让我们来看看<c:if>的源码,或许能给你一些好主意:

public final class IfHandler extends TagHandler 
{        
		protected final TagAttribute test;      
		protected final TagAttribute var; 
       
     public IfHandler(TagConfig config) 
     {          
        super(config);          
        this.test = this.getRequiredAttribute("test");          
        this.var = this.getAttribute("var");     
      }       

     public void apply(FaceletContext ctx, UIComponent parent)              
           throws IOException, FacesException, ELException 
      {          
         boolean b = this.test.getBoolean(ctx);          
         if (this.var != null) 
         {             
              ctx.setAttribute(var.getValue(ctx), new Boolean(b));        
          }          
         if (b) 
         {              
              this.nextHandler.apply(ctx, parent);         
         }      
       }  
}

这就是了!你将发现当文档被编译的时候Facelets使用了?好居民?法则和构造函数注入的方法。Facelets和全部标签都是无状态的,而不像JSP(添加入了tag handler对象)。更多技术方面的细节将会在一篇不同的文档中提供,所以现在酒描述tag里面是如何进行的。

TagHandler,<c:if> 继承的,是一个很好的让你可以使用开发自定义标签的基本类示例。将TagHandler想象成JSP的TagSupport或者BodyTagSupport。

在构造函数中,该Tag的表现被传递,转达了该文档的结构包含的:位置,子标签,和属性。

TagAttributes是XML文档中属性的表现。他们有众多方法来处理EL表达式和高压方法到你需要的类型中。他们也是无状态的,他们的方法必须要传递到FaceletContext中以提供当前的状态。

最后一点比较有趣的就是子元素被部分变量nextHandler表现。你可以在<c:if>的情况下添加任意多的子元素或者根本不添加。

我们自定义的组件已经写了出来,你可以继续将它添加到facelet-taglib文档中:

<facelet-taglib>    
      <namespace>http://www.jsfcentral.com/public</namespace>    
           <tag>      
              <tag-name>if</tag-name>      
              <handler-class>com.jsfcentral.IfHandler</handler-class>    
           </tag>  
</facelet-taglib>

总结

这仅仅是使用Facelets框架的一个简短介绍。接下来将会有更多关于模板化,特色和定制Facelets的详细文章。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值