使用JSF开发:视图(一)
一.MVC几乎是Java Web framework的结构总纲,不过纷乱的框架各有巧妙,实现各有不同。 一.Struts、Webwork、Spring MVC
基于C/S模式的设计结构,不隐藏基于请求/响应通讯协议内容的思维模式,早期的Web开发者,都已经习惯这样思考,学习曲线比较平滑,比较容易入门,而且Struts从诞生至今,抢占了不少市场,有大量的用户群。现在Struts和Webwork双剑合璧衍生出的Struts2是这种结构的最强代表,在普遍的企业系统中都可以胜任,是开发不错的选择。
(1).Tapestry、Wicket、JSF
基于组件的设计结构,亮点在于转变Web应用开发的思维模式,不能说新颖,但是很具特色,也已经被开发人员所接受,Tapestry诞生的比较早,在非官方的市场风光无限,个人也非常喜欢,但是3.0和4.x版本中都有一些令人不太愉快的地方,5.0目前还没有发布正式版本(莫非要等到零八奥运。。。)。三者之中Wicket的入门最快,学习曲线最低,而且笔者提供的组件相当丰富,是一个非常优秀的轻量级框架,一些比较小的企业系统中,强烈推荐使用。
(2).Other
还有一些其他的框架,如Echo2,Conoon,Shale,Tuibine等等,这些产品中有的自成体系,有的是其他产品的补充,虽然各有亮点,但是很难撼动前面两者的地位了。
(3).郁闷的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>
到此为止,Facelets的准备工作已经OK,正式开工!
index.xhtml 代码
步骤一:创建布局页面 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。
组件
使用厂商组件
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的组件生命周期,图详参考:
http://www.iteye.com/topic/123728
这个图是从请求至响应中组件解码与编码,调用,渲染,等等一系列的动作过程。有了对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.1. PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
2. "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
3.<taglib>
4. <tlib-version>1.0tlib-version>
5. <jsp-version>2.0jsp-version>
6. <short-name>demoshort-name>
7. <uri>http://demo.phoenixup.org/jsfuri>
8. <tag>
9. <name>labelname>
10. <tag-class>demo.LabelTagtag-class>
11. <attribute>
12. <name>valuename>
13. <required>truerequired>
14. attribute>
15. <attribute>
16. <name>stylename>
17. attribute>
18. tag>
19.taglib>
4.编辑faces-config.xml、配置Facelets
faces-config.xml 代码
1.<component>
2. <component-type>demo.component.Labelcomponent-type>
3. <component-class>demo.LabelComponentcomponent-class>
4.component>
5.<render-kit>
6. <renderer>
7. <component-family>demo.component.Labelcomponent-family>
8. <renderer-type>demo.renderer.Labelrenderer-type>
9. <renderer-class>demo.LabelRendererrenderer-class>
10. renderer>
11.render-kit>
demo.taglib.xml 代码
1.<tag>
2. <tag-name>labeltag-name>
3. <component>
4. <component-type>demo.component.Labelcomponent-type>
5. <renderer-type>demo.renderer.Labelrenderer-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.iteye.com/topic/123728.