随笔-34  评论-1965  文章-0  trackbacks-0

上一篇文章,我介绍了通过JBoss Tools的向导生成一个简单的Seam工程。Seam的中文意思就是“缝合线, 衔接口, 接缝”,所以大家可以将Seam当成一条能将EJB3、JSF等框架有机地结合起来的纽带。如下图所示。

由上图可以看出Seam会涉及很多技术,不过大家不必惊慌,因为其中有些技术不是必须的。然而要学好Seam,掌握JSF是必不可少的。Seam基于JSF作了一些扩展,使JSF更易用。另外,在上图中JSF上层有JSP、Facelets和Portal这三个框框,这三种技术是JSF的视图(View)技术,三者可任选其一。现在JSF默认是使用JSP作为视图技术,不过我早前在TSS上看过一篇关于JSF 2.0的文章,这方面会有所改变——Facelets将会取而代之。因为Facelets对比JSP要优越许多:

  1. Facelets使用XHTML规范,省却了一大堆JSP的<f:verbatim />;
  2. 更强的性能;
  3. Facelets实现模板(Template)功能,这个可以称得上是杀手锏功能。因为几乎每个应用都要使用这个功能;
  4. Facelets还可以方便地创建自定义标签和EL函数。

所以Facelets成为Seam的不二之选。通过上面的讲述,我想大家应该了解Seam、JSF与Facelets的关系,故我介绍使用Facelets作为视图技术的JSF。

基本的XHTML构成

如果大家可以通过上一篇文章可以顺利创建Seam工程,可以在WebContent文件夹下看到一些XHTML文件。不过,这些XHTML都并不是独立的,需要依赖模板页面。下面让我们来看一个完整的XHTML:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
    
<head>
        
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
        
<title>
            Hello World
        
</title>
    
</head>
    
<body>
        
<h1><h:outputText value="Hello World!" /></h1>
    
</body>
</html>

这个文件的构成很简单,与普通的XHTML区别就是引入了“http://java.sun.com/jsf/html”命名空间。这个URI正是JSF常用的组件(Component,在JSF里的称呼,可以理解为JSP中的标签)的URI,<h:outputText />就是其中之一。

另外,需要指出的是上述文件并没有<f:viewRoot />。这个在以JSP作为视图技术的JSF的页面中是必需的。因为JSF的页面其实在内存中模型就是一棵树,如下图所示。理解这点非常重要,所以是必须有根节点。Facelets的FaceletViewHandler会自动创建一个UIViewRoot,如果XHTML中没有定义的话。

常用的JSF组件

常用的JSF组件可以分为以下几大类:表单输入组件、命令组件、输出组件、数据组件和辅助组件。

除了辅助组件之外,有些属性是组件共有的:

  1. id属性,正如我前边所说“JSF的页面其实在内存中模型就是一棵树”,每个组件对应一个节点。每个节点都有一个唯一标识,这就是id属性。如果你没有显式地设置id,JSF会自动帮你生成一个。
  2. binding属性,只能设置一个EL为值,它作用是可以将组件对应的对象绑定到后台的Managed Bean。当我们拿到这个对象后,我们可以通过JSF的API改变其行为。这个会在以后文章详细讲述。
  3. rendered属性,用于指定该组件是否会被输出到页面中。

下面我分别对每类组件进行概述。

常用的表单输入组件

对于表单输入组件,都会有一个叫value的属性,通常被设置为一个EL表达式,如#{myBean.myProperty}。在JSF中有一个概念叫双向绑定,即是在提交表单的时候,JSF通过EL将用户输入的值绑定到后台的Managed Bean中;同样地请求完成后渲染页面时,JSF亦会通过EL将Managed Bean的值输出相应的位置。

常用的表单输入组件有如下 :

  • h:inputText
  • h:inputSecret
  • h:inputTextarea
  • h:selectBooleanCheckbox
  • h:selectManyCheckbox
  • h:selectOneRadio
  • h:selectOneListbox
  • h:selectManyListbox
  • h:selectOneMenu
  • h:selectManyMenu

在这,我就不一一介绍这些组件的详细用法,大家可以找一下《Core JavaServer Faces, 2nd Edition》来看一下。

命令组件

JSF的命令组件有<h:commandButton />和<h:commandLink />,分别输出一个<input type="submit" />和<a />。它们都有两个属性action和actionListener,可以绑定到Managed Bean的事件处理方法。例如:

    <h:commandButton action="#{myBean.myEvent}" value="Click Me" />
    
<h:commandButton actionListener="#{myBean.myActionListener}" value="Click Me" />

对应的JAVA代码:

    public String myEvent() {
        
return null;
    }
    
    
public void myActionListener(ActionEvent event) {
        
    }

常用的输出组件

这些组件输出一些常用的HTML元素,如<span />、<a />、<div />和<table />等。其中最常用的应该是<h:outputText />、<h:panelGroup />和<h:panelGrip />。

  • h:outputText,当id、style和styleClass等属性不为空时,它会输出<span />包住value。另外,它还有一个属性叫escape,用于指示是否需要对值进行HTML编码,默认为true。对值进行HTML可以从一定程序上防止XSS(Cross Site Scripting,跨站脚本)攻击。
  • h:panelGroup,当id、style和styleClass行属性不为空,且layout不为block时,它输出<span />。而当上述属性不为空,且layout为block时,它会输出<div />。不过,当上述属性为空时,它将什么也不输出。可能有的朋友会问,如果什么不输出,那要它何用?这个问题稍后再答。
  • h:panelGrid,输出<table />。它的用法有点奇怪,它有属性叫columns,默认为1。它将包含在其内的JSF组件,分别放到<td />元素输出。有时,我可能需要将两个或多个JSF组件放到同一个td中定位,就需要使用到h:panelGroup了。此时,我们不用对<h:panelGroup/>设置任何属性。这就是上个问题的答案。<h:panelGroup />用于将两个或多个JSF组件当作一个使用,统一设置它们是否rendered等。例如:
            <h:panelGrid columns="2">
                
    <h:outputText value="1" />
                
    <h:outputText value="2" />
                
    <h:panelGroup>
                    
    <h:outputText value="3" />
                    
    <h:outputText value="-" />
                    
    <h:outputText value="4" />
                
    </h:panelGroup>
                
    <h:outputText value="5" />
            
    </h:panelGrid>
    的输出如下图所示:

常用的数据组件

JSF的数据组件有<h:dataTable />,它的使用相对比较简单,可以将绑定到集合类型。如

<h:dataTable value="#{myBean.myProps}" var="_prop">
    
<h:column>
        
<f:facet name="header">
            
<h:outputText value="Header" />
        
</f:facet>
        
<h:outputText value="#{_prop.myProp}" />
    
</h:column>
</h:dataTable>

常用的辅助组件

这些组件一般不能单独使用,而是作为辅助用在不同的组件中,其作用也有所不同。它们的命名空间是xmlns:f="http://java.sun.com/jsf/core",通常以f为前缀,如f:facet、f:param。

小结

本文大概地介绍了一下JSF的组件。虽然JSF默认已经有这么多的组件,但是对于时下盛行的富客户端的浏览器应用而言还是杯水车薪。因此许多软件厂商都开发各式各样的第三方组件,以方便大家构建AJAX应用,如Richfaces、IceFaces等。至于这些组件的详细用法,大家可以在日后的学习中慢慢熟悉。

posted on 2009-03-31 00:10 Max 阅读(5656) 评论(7)  编辑  收藏 所属分类: Seam系列

评论:
# re: 基于Facelets的JSF 2009-04-01 17:34 | cx
看到 Seam系列二 ,高兴 !
写系列专题不容易, 这里表示 支持!!!!!  回复  更多评论
  
# re: 基于Facelets的JSF 2009-04-02 17:48 | Max
@cx
谢谢,的确有点难,我会坚持的。  回复  更多评论
  
# re: 基于Facelets的JSF 2009-04-09 00:03 | koumei
You are indeed a J-Guru !  回复  更多评论
  
# re: 基于Facelets的JSF 2009-04-09 14:58 | koumei
Happy Easter day bro.  回复  更多评论
  
# re: 基于Facelets的JSF 2009-06-09 20:09 | paopao
max 期待你写一篇JSF+SEAM+EJB整合文章 目前仿佛还没有...  回复  更多评论
  
# re: 基于Facelets的JSF 2009-07-24 13:37 | seam初学者
读了颇有收获 辛苦了 呵呵  回复  更多评论
  
# re: 基于Facelets的JSF 2009-07-24 13:41 | seam初学者
我是初学者 希望加我为好友 qq:348234691 十分期待你的到来  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: