使用JSF开发:视图(一)

前言
        MVC几乎是Java Web framework的结构总纲,不过纷乱的框架各有巧妙,实现各有不同。

Struts、Webwork、Spring MVC  
        基于C/S模式的设计结构,不隐藏基于请求/响应通讯协议内容的思维模式,早期的Web开发者,都已经习惯这样思考,学习曲线比较平滑,比较容易入门,而且Struts从诞生至今,抢占了不少市场,有大量的用户群。现在Struts和Webwork双剑合璧衍生出的Struts2是这种结构的最强代表,在普遍的企业系统中都可以胜任,是开发不错的选择。

Tapestry、Wicket、JSF
        基于组件的设计结构,亮点在于转变Web应用开发的思维模式,不能说新颖,但是很具特色,也已经被开发人员所接受,Tapestry诞生的比较早,在非官方的市场风光无限,个人也非常喜欢,但是3.0和4.x版本中都有一些令人不太愉快的地方,5.0目前还没有发布正式版本(莫非要等到零八奥运。。。)。三者之中Wicket的入门最快,学习曲线最低,而且笔者提供的组件相当丰富,是一个非常优秀的轻量级框架,一些比较小的企业系统中,强烈推荐使用。

Other
        还有一些其他的框架,如Echo2,Conoon,Shale,Tuibine等等,这些产品中有的自成体系,有的是其他产品的补充,虽然各有亮点,但是很难撼动前面两者的地位了。

    (Java的Web Framework真是让人火大,一陀一驼的!如MS的一家言大家不买账,这种百花齐放也让人牢骚不少~~~T.T)

郁闷的JSF
        同样的设计结构,Tapesty和Wicket诞生就伴随着很多的赞美,可是JSF却冷落了很多,批评和泼冷水的人居然占大多数(难道JSF是后妈生的…)。所有的JSR定义,实现由厂商来玩,基于接口编程的思维,定义与实现分离,这是不错的拆分解藕的设计,可是由于JSF定义本身不够完善合理,厂商初期的不太买账,开源的实现又不够稳定放心等等原因,果然导致JSF一片骂声。JSF真的有这么差,偶倒是觉得,见仁见智!

视图
        JSF说到底MVC结构,我们就先来解决诟病最多的视图(View)层。JSF的缺省视图技术是JSP(不可能要求SUN自抽耳光,抛弃JSP是不可能滴),也是大家骂声最多的,诸如Taglib是失败的技术,不能所见即所得可视化编辑,缺少优秀的IDE支持,代码侵入严重,程序和美工不能良好分离。

View之一JSP
        JSP作为J2EE中标准的视图技术,是相当稳定和强悍的。Taglib并不是一项失败的技术,不过它的确是一项学习曲线比较高的技术,在稳定的团队中有良好的表现,但是在流水的阵营中,学习和维护的成本可能真的是不太能接受的。
        关于JSP和Taglib的指南,几乎使用Java开发Web应用的人都有涉猎,而且互联网上的教程例子一陀一陀的,就不说了。
        引用一句老兄的话,无论多么优秀的语言,都可以写出糟糕的代码。JSP+Taglib是一项成熟和稳定技术,代码一样可以写的很优雅,不过对程序员和美工的要求都稍微都高了一点(#>.<)。

View之二Facelets
        Facelets模板框架是目前JSF优秀的视图解决技术,基于标准的XML技术,让JSF的开发效率有了很大的提升。
模板
        使用Facelets的具体步骤

  1. 下载Facelets的最新发行包
  2. 引入jsf-facelets.jar到项目依赖库
  3. 配置web.xml文件
    <context-param>
            <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
            <param-value>.xhtml</param-value>
        </context-param>
  4. 配置faces-config.xml文件
    <application>   
            <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
    </application>

index.xhtml 代码        到此为止,Facelets的准备工作已经OK,正式开工!

         步骤一:创建布局页面 template.xhtml

<!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:ui="http://java.sun.com/jsf/facelets">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title><ui:insert name="title">Default Title</ui:insert>
        </title>
        <style type="text/css">
        body {
            font-family: Verdana, Arial, Helvetica, sans-serif;
            font-size: small;
        }
    </style>
    </head>
    <body>
        <div id="head">
            <ui:insert name="head">Default Head</ui:insert>
        </div>
        <hr />
        <div id="header">
            <ui:insert name="body">Default Body</ui:insert>
        </div>
        <hr />
        <div id="header">
            <ui:insert name="foot">Default Foot!</ui:insert>
        </div>
    </body>
</html>

         
                 步骤二:使用布局模板index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:d="http://demo.phoenixup.org/jsf">  
    <ui:composition template="/WEB-INF/template/template.xhtml">
        <ui:define name="title">
            This is a demo application!   
          </ui:define>
        <ui:define name="head">
            <div id="head">
                <h2>
                    This is HEAD!
                </h2>
            </div>
        </ui:define>
        <ui:define name="body">
            【略】
        </ui:define>
        <ui:define name="foot">
            <div id="foot">
                <h2>
                    This is FOOT!
                </h2>
            </div>
        </ui:define>
    </ui:composition>
</html>

标签内容

  • ui:insert 标记定义逻辑区域
  • ui:composition调用模板
  • ui:define 填充区域内容

        具体的标签的教程可以参考Facelets的官方文档,使用很简单

使用JSFC
       
jsfc的灵感来自Tapestry,使用转义标签,可以在不破坏页面的可视编辑的前提的下,优雅的解决了程序与视图分离,代码侵入的问题,令程序员和美工都很Happy。

显示
       
使用Maven2管理项目的组织结构,关于Maven2的使用,可以参考官方网站的文档,在命令行键入下面命令:
        mvn jetty:run
   
    访问地址:localhost:8080/helloworld/,可以看到显示内容,不贴图了!

组件
        使用厂商组件
       
Facelets与使用已完场的组件是非常容易的,以tomahawk为例

  1. 创建 Facelets 标记文件(/WEB-INF/taglibs/ tomahawk.taglib.xml文件,太长了不贴了!
  2. 在 web.xml 中声明标记库
    <context-param>
            <param-name>facelets.LIBRARIES</param-name>
            <param-value>
                /WEB-INF/taglibs/tomahawk.taglib.xml
            </param-value>
    </context-param>
    <!--引入多个文件以分号(;)分割 -->
  3. 用命名空间导入标记文件。
    index.xhtml 代码
     
    1. <html xmlns="http://www.w3.org/1999/xhtml"  
    2.     xmlns:ui="http://java.sun.com/jsf/facelets"  
    3.     xmlns:h="http://java.sun.com/jsf/html"  
    4.     xmlns:t="http://myfaces.apache.org/tomahawk"
    5.     xmlns:d="http://demo.phoenixup.org/jsf">  
  4. 使用组件
    index.xhtml 代码
     
    1. <input type="text" id="startDate" jsfc="t:inputCalendar"   
    2. value="#{helloworld.start}" renderAsPopup="true"  
    3. popupDateFormat="yyyy-MM-dd" renderPopupButtonAsImage="true" required="true" />  
 开发JSF组件
        说真的JSF的组件开发,并不是一件很容易的事情,但是也绝不困难,下面就是一个最经典和老土的HelloWorld的例子,这个组件例子在JSF1.2定义的基础上开发,在JSF  RI1.2.04和MyFaces1.20中都能良好运行,如果有兴趣的可以看看Sun的官方文档,还有参照一下Myfaces1.20的实现。

JSF的组件生命周期
 

        这个图(图是别人的)是从请求至响应中组件解码与编码,调用,渲染,等等一系列的动作过程。有了对JSF生命周期的理解,组件的开发就很清晰了。
        1.    创建Component          
LabelComponent.java代码
  1. package demo;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.faces.component.UIOutput;  
  6. import javax.faces.context.FacesContext;  
  7. import javax.faces.context.ResponseWriter;  
  8.   
  9. public class LabelComponent extends UIOutput {  
  10.     @Override  
  11.     public String getFamily() {  
  12.         return "demo.component.Label";  
  13.     }  
  14.   
  15.     @Override  
  16.     public String getRendererType() {  
  17.         return "demo.renderer.Label";  
  18.     }  
  19. }  
         
        只覆盖了两个方法,确定了组件和渲染器的关键字。
        2.    创建Renderer      
LabelRenderer.java 代码
 
  1. package demo;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.faces.component.UIComponent;  
  6. import javax.faces.component.UIInput;  
  7. import javax.faces.component.UIOutput;  
  8. import javax.faces.context.FacesContext;  
  9. import javax.faces.context.ResponseWriter;  
  10. import javax.faces.render.Renderer;  
  11.   
  12. public class LabelRenderer extends Renderer {  
  13.   
  14.     @Override  
  15.     public void encodeBegin(FacesContext context, UIComponent component)  
  16.             throws IOException {  
  17.         FacesContext.getCurrentInstance().getExternalContext().log("Start.");  
  18.         ResponseWriter writer = context.getResponseWriter();  
  19.         UIOutput ui = (UIOutput) component;  
  20.           
  21.         writer.startElement("label", component);  
  22.         Object style = ui.getAttributes().get("style");  
  23.         if (null != style)  
  24.             writer.writeAttribute("style", style.toString(), null);  
  25.         Object value = ui.getAttributes().get("value");  
  26.         if (null != value)  
  27.             writer.write(value.toString());  
  28.         writer.endElement("label");  
  29.         writer.flush();  
  30.     }  
  31.   
  32.     @Override  
  33.     public void encodeEnd(FacesContext context, UIComponent component)  
  34.             throws IOException {  
  35.         FacesContext.getCurrentInstance().getExternalContext().log("The end.");  
  36.     }  
  37. }  

        具体的内容实现。
        3.    创建Taglib     
LabelTag.java 代码
 
  1. package demo;  
  2.   
  3. import javax.el.ValueExpression;  
  4. import javax.faces.component.UIComponent;  
  5. import javax.faces.webapp.UIComponentELTag;  
  6.   
  7. public class LabelTag extends UIComponentELTag {  
  8.   
  9.     private ValueExpression value;  
  10.     private ValueExpression style;  
  11.   
  12.     public void setValue(ValueExpression value) {  
  13.         this.value = value;  
  14.     }  
  15.   
  16.     public void setStyle(ValueExpression style) {  
  17.         this.style = style;  
  18.     }  
  19.   
  20.     @Override  
  21.     protected void setProperties(UIComponent component) {  
  22.         if(component ==null || !(component instanceof LabelComponent))  
  23.             throw new IllegalArgumentException("Component is not deom.component.LabelComponent");  
  24.         LabelComponent comp=(LabelComponent)component;  
  25.         super.setProperties(component);  
  26.         if(value!=null)  
  27.             comp.setValueExpression("value", value);  
  28.         if(style!=null)  
  29.             comp.setValueExpression("style", style);  
  30.           
  31.     }  
  32.   
  33.     @Override  
  34.     public String getComponentType() {  
  35.         return "demo.component.Label";  
  36.     }  
  37.   
  38.     @Override  
  39.     public String getRendererType() {  
  40.         return "demo.renderer.Label";  
  41.     }  
  42.   
  43. }  

        继承UIComponentELTag,指定组件和渲染器。       
demo.tld 代码
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2.     PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"   
  3.     "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >  
  4. <taglib>  
  5.     <tlib-version>1.0 tlib-version>  
  6.     <jsp-version>2.0 jsp-version>  
  7.     <short-name>demo short-name>  
  8.     <uri>http://demo.phoenixup.org/jsf uri>  
  9.     <tag>  
  10.         <name>label name>  
  11.         <tag-class>demo.LabelTag tag-class>  
  12.         <attribute>  
  13.             <name>value name>  
  14.             <required>true required>  
  15.          attribute>  
  16.         <attribute>  
  17.             <name>style name>  
  18.          attribute>  
  19.      tag>  
  20. taglib>  

        4.    编辑faces-config.xml、配置Facelets
faces-config.xml 代码
 
  1. <component>  
  2.     <component-type>demo.component.Label component-type>  
  3.     <component-class>demo.LabelComponent component-class>  
  4. component>  
  5. <render-kit>  
  6.     <renderer>  
  7.         <component-family>demo.component.Label component-family>  
  8.         <renderer-type>demo.renderer.Label renderer-type>  
  9.         <renderer-class>demo.LabelRenderer renderer-class>  
  10.      renderer>  
  11. render-kit>  
demo.taglib.xml 代码
 
  1. <tag>  
  2.     <tag-name>label tag-name>  
  3.     <component>  
  4.         <component-type>demo.component.Label component-type>  
  5.         <renderer-type>demo.renderer.Label renderer-type>  
  6.      component>  
  7. tag>  

        5.    使用
index.xhtml 代码
 
  1. <html xmlns="http://www.w3.org/1999/xhtml"  
  2.     xmlns:ui="http://java.sun.com/jsf/facelets"  
  3.     xmlns:h="http://java.sun.com/jsf/html"  
  4.     xmlns:t="http://myfaces.apache.org/tomahawk"  
  5.     xmlns:d="http://demo.phoenixup.org/jsf">  
  6.   
  7.     <label jsfc="d:label" value="#{helloworld.title}" style="color: red; size: 12" />  

        组件只是简单的接受两个参数value和style,作为显示的内容,和显示格式。

复合组件
        Facelets还有一种复合组件的功能,下面这个例子有个演示
        1.    创建复合组件
calendar.xhtml 代码
 
  1. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"  
  2.     xmlns:ui="http://java.sun.com/jsf/facelets"  
  3.     xmlns:h="http://java.sun.com/jsf/html"  
  4.     xmlns:t="http://myfaces.apache.org/tomahawk">  
  5.     <ui:composition>      
  6.         <input type="text" jsfc="t:inputCalendar" id="${id}"  
  7.                         value="${backingbean}" renderAsPopup="true"  
  8.                         popupDateFormat="${dateformat}" renderPopupButtonAsImage="true"  
  9.                         required="true" />  
  10.      ui:composition>  
  11. html>  

       
        2.    定义复合组件
<tag>
        <tag-name>calendar</tag-name>
        <source>source/calendar.xhtml</source>
</tag>

 

 

 

 

http://www.javaeye.com/topic/123728

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值