﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-风之语-随笔分类-JSF</title><link>http://www.blogjava.net/gf7/category/3533.html</link><description>&lt;script language="JavaScript" type="text/JavaScript" src="http://union.3721.com/v2/news.js?a=2073&amp;b=1005&amp;p=1007&amp;nt=10400&amp;m=404045" charset="gb2312"&gt; &lt;/script&gt;
</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 17:21:34 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 17:21:34 GMT</pubDate><ttl>60</ttl><item><title>web开发框架——JSF开发实战二</title><link>http://www.blogjava.net/gf7/archive/2005/12/23/25253.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Dec 2005 10:37:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/12/23/25253.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/25253.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/12/23/25253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/25253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/25253.html</trackback:ping><description><![CDATA[　JSF开发实战的第一篇(jsf开发实战一)演示了如何建立一个最简单的JSF应用，从那个例子中我们可以观察到JSF的页面组件是如何与后台的javabean绑定的，也看到了JSF标签的最基本使用。在本文中我们会演示一个更加复杂的应用，它包含了更丰富的JSF标签。<BR>　　<BR>　　要开发的例子是一个用户管理程序，管理员输入帐号与密码登陆，然后它可以看到所有用户的列表，并且可以修改或者删除其中的一些数据。利用myeclipse所带的jsf-config.xml设计器，页面流程如下：<BR>　　 
<CENTER>　<IMG src="http://java.chinaitlab.com/imgfiles/2005.10.28.10.54.23.7.1.jpg"></CENTER><BR>　　可以看出，这个应用设计到的业务逻辑有：<BR>　　<BR>　　用户登陆、修改用户信息、增加新用户、删除用户<BR>　　<BR>　　我们在后台的数据库操作中使用hibernate框架来辅助开发，相关的技术细节请自行查阅文档。<BR>　　<BR>　　首先建立pojo文件：User.java，它包含几个基本属性：<BR>　　<BR>　　private int id;<BR>　　private String name;<BR>　　private String password;<BR>　　private int power;<BR>　　<BR>　　请自行完成set/get方法，并且编写对应的hbm.xml文件。<BR>　　<BR>　　我们的主要工作之一，是要建立好供jsf页面组件使用的javabean，把它命名为UMDelegater.java。它会调用UserManager来完成业务逻辑，这里是一个代理模式。UserManager的内容只是简单的增/删/查/改的操作，这里不再具体列出。UMDelegater的内容是：<BR>　　package org.bromon.jsf.control;<BR>　　<BR>　　import java.util.List;<BR>　　<BR>　　import javax.faces.model.DataModel;<BR>　　import javax.faces.model.ListDataModel;<BR>　　<BR>　　import org.bromon.jsf.model.UserManager;//自行建立的工具类，负责所有的hibernate操作<BR>　　import org.bromon.jsf.model.pojo.User;//pojo对象<BR>　　<BR>　　public class UMDeletager {<BR>　　private UserManager um=new UserManager();//所有具体的方法都由它来实现<BR>　　private User user=new User();<BR>　　private DataModel allUsers=new ListDataModel();//JSF的内置对象，用来封装html中table的数据<BR>　　<BR>　　//----------set/get方法---------------------<BR>　　public DataModel getAllUsers() {<BR>　　return allUsers;<BR>　　}<BR>　　<BR>　　public void setAllUsers(List list) {<BR>　　allUsers.setWrappedData(list);<BR>　　}<BR>　　public UserManager getUm() {<BR>　　return um;<BR>　　}<BR>　　public void setUm(UserManager um) {<BR>　　this.um = um;<BR>　　}<BR>　　public User getUser() {<BR>　　return user;<BR>　　}<BR>　　public void setUser(User user) {<BR>　　this.user = user;<BR>　　}<BR>　　<BR>　　//-----功能方法---------<BR>　　public String login()<BR>　　{<BR>　　String s=um.login(this.getUser());<BR>　　if(s.equals("ok"))<BR>　　{<BR>　　this.setAllUsers(um.loadAll());//如果登陆成功，就取出所有的用户信息<BR>　　return "login:ok";<BR>　　}else<BR>　　{<BR>　　swapper.setLoginFailInfo(s);<BR>　　return "login:fail";<BR>　　}<BR>　　}<BR>　　<BR>　　public String edit()<BR>　　{<BR>　　this.user=(User)allUsers.getRowData();//页面中的table自动返回含有id的user对象<BR>　　this.user=um.loadById(user.getId());<BR>　　if(user!=null)<BR>　　{<BR>　　return "edit";<BR>　　}else<BR>　　{<BR>　　return "error";<BR>　　}<BR>　　}<BR>　　<BR>　　public String update()<BR>　　{<BR>　　um.update(this.getUser());<BR>　　this.setAllUsers(um.loadAll());//重新取一次数据，目的是更新缓存<BR>　　return "update:ok";<BR>　　}<BR>　　<BR>　　public String addNew()<BR>　　{<BR>　　this.setUser(new User());//生成一个新的user对象，不含任何数据，它会被自动映射成一个没有数据的form<BR>　　return "add";<BR>　　}<BR>　　<BR>　　public String add()<BR>　　{<BR>　　um.add(this.getUser());<BR>　　this.setAllUsers(um.loadAll());//重新取一次数据，目的是更新缓存<BR>　　return "add:ok";<BR>　　}<BR>　　}<BR>　　<BR>　　在jsf-config.xml中声明这个bean：<BR>　　<BR>　　＜managed-bean＞<BR>　　＜managed-bean-name＞UMDelegater＜/managed-bean-name＞<BR>　　＜managed-bean-class＞org.bromon.jsf.control.UMDeletager＜/managed-bean-class＞<BR>　　＜managed-bean-scope＞session＜/managed-bean-scope＞<BR>　　＜/managed-bean＞<BR>　　<BR>　　业务逻辑就设计完成了，下面可以开始编写jsf文件，首先是index.jsp:<BR>　　<BR>　　首先引入标签库，并且声明page属性：<BR>　　<BR>　　&lt;%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %&gt;<BR>　　&lt;%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %&gt;<BR>　　&lt;%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&gt;<BR>　　<BR>　　然后是构建页面：<BR>　　<BR>　　＜body＞<BR>　　＜f:view＞<BR>　　＜h:form＞<BR>　　＜h:panelGrid columns="3"＞<BR>　　＜h:outputLabel for="name" value="帐号:"/＞<BR>　　＜h:inputText id="name" value="#{UMDelegater.user.name}" required="true"/＞<BR>　　＜h:message for="name"/＞<BR>　　<BR>　　＜h:outputLabel for="password" value="密码:"/＞<BR>　　＜h:inputSecret id="password" value="#{UMDelegater.user.password}" required="true" /＞<BR>　　＜h:message for="password"/＞<BR>　　＜/h:panelGrid＞<BR>　　＜h:panelGroup＞<BR>　　＜h:commandButton value="登陆" action="#{UMDelegater.login}"/＞<BR>　　＜/h:panelGroup＞<BR>　　＜/h:form＞<BR>　　＜/f:view＞<BR>　　＜/body＞<BR>　　<BR>　　页面中声明了两个文本框，分别映射UMDelegater对象中user对象的name属性，和UMDelegater对象中user对象的password属性。一旦这个表单被提交，这两个文本框的值就会被自动赋给user对象，我们只需要从user中取数据就行了，不用再去执行麻烦的request.getParameter(“”)，更改编码，转换数据类型等操作。<BR>　　<BR>　　我们同时还声明了一个button，它与UMDelegater对象的login方法绑定，点击该按钮，系统会执行UMDelegater.login方法，该方法从user对象中取出name和password，和数据库中的记录进行比较。如果合法，那么就取出所有的数据，放到一个DataModel对象中，具体代码是：<BR>　　<BR>　　List userList=UserManager.getAllUser();//取得所有用户数据，放到一个List中<BR>　　DataModel allUser=new ListDataModel ();//DataModel是一个接口，ListDataModel是它的一个实现<BR>　　<BR>　　allUsers.setWrappedData(userList);//将数据填充进去备用<BR>　　<BR>　　使用DataModel意义何在呢？JSF中，我们可以把一个html页面上的table和一个DataModel绑定起来，这些数据会自动填充到table中，我们不必再自己去写循环，生成若干的&lt;tr&gt;、&lt;td&gt;来生成一个table。在list.jsp中我们会看到如何使用DataModel。<BR>　　<BR>　　放好数据之后，登陆成功的操作就完成了，返回一个login:ok，就可以重定向到list.jsp。如果用户登陆失败，那么会返回login:fail，重定向到error.jsp，它的内容就不叙说了。下面我们看看list.jsp里面有什么，下面是它的&lt;body&gt;代码：<BR>　　<BR>　　＜body＞<BR>　　＜f:view＞<BR>　　＜h:form＞<BR>　　＜h:dataTable id="users" value="#{UMDelegater.allUsers}" var="u" border="1" width="80%" ＞<BR>　　＜h:column＞<BR>　　＜f:facet name="header"＞<BR>　　＜h:outputText value="id"/＞<BR>　　＜/f:facet＞<BR>　　＜h:outputText value="#{u.id}"/＞<BR>　　＜/h:column＞<BR>　　<BR>　　＜h:column＞<BR>　　＜f:facet name="header"＞<BR>　　＜h:outputText value="帐号"/＞<BR>　　＜/f:facet＞<BR>　　＜h:commandLink action="#{UMDelegater.edit}"＞<BR>　　＜h:outputText value="#{u.name}"/＞<BR>　　＜/h:commandLink＞<BR>　　＜/h:column＞<BR>　　<BR>　　＜h:column＞<BR>　　＜f:facet name="header"＞<BR>　　＜h:outputText value="密码"/＞<BR>　　＜/f:facet＞<BR>　　＜h:outputText value="#{u.password}"/＞<BR>　　＜/h:column＞<BR>　　<BR>　　＜h:column＞<BR>　　＜f:facet name="header"＞<BR>　　＜h:outputText value="权限代码"/＞<BR>　　＜/f:facet＞<BR>　　＜h:outputText value="#{u.power}"/＞<BR>　　＜/h:column＞<BR>　　＜/h:dataTable＞<BR>　　＜p＞<BR>　　＜h:commandLink action="#{UMDelegater.addNew}" value="增加用户" /＞<BR>　　＜/p＞<BR>　　＜/h:form＞<BR>　　＜/f:view＞<BR>　　＜/body＞<BR>　　<BR>　　我们使用了一个h:dataTable标签，它是JSF独有的东西，它会被翻译为一个html的table，通过指定h:dataTable的value="#{UMDelegater.allUsers}"属性，它就与我们刚才生成的DataModel对象关联起来，数据会被自动填充。我们只需要声明dataTable中的每一列的表头，数据来自哪个字段就可以了，如下：<BR>　　＜h:column＞<BR>　　＜f:facet name="header"＞<BR>　　＜h:outputText value="id"/＞<BR>　　＜/f:facet＞<BR>　　＜h:outputText value="#{u.id}"/＞<BR>　　＜/h:column＞<BR>　　<BR>　　表格最后还有一个“增加用户”的按钮，它与UMDelegater.addNew绑定，它会把我们重定向到add.jsp。<BR>　　<BR>　　需要注意的是，每个用户名都是个超链接，点击之后可以重定向到edit.jsp，这个页面可以修改用户资料。这是通过如下代码实现的：<BR><img src ="http://www.blogjava.net/gf7/aggbug/25253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-12-23 18:37 <a href="http://www.blogjava.net/gf7/archive/2005/12/23/25253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用MyEclipse JSF开发实战(一)</title><link>http://www.blogjava.net/gf7/archive/2005/10/15/15565.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 15 Oct 2005 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/10/15/15565.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/15565.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/10/15/15565.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/15565.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/15565.html</trackback:ping><description><![CDATA[JSF开发实战(一)<BR><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;JSF将是J2EE5.0中所包含的web开发框架，这应该是第一个成为jcp标准，并且随j2eesdk一起发布的web框架，可以看出sun对它的期望很高。JSF最大的竞争对手是tapestry，是apache的产品，但是apache又弄出了个myfaces，是对jsf标准的一个实现。也许你也和我一样，在jsf和tapestry之间犹豫很久，将来从apache的态度上应该可以看出二者的走向。在tss上有一篇比较jsf&nbsp;1.0与tapestry&nbsp;3.0的文章，内容很扎实到位：<A href="http://www.theserverside.com/articles/article.tss?l=JSFTapestry">http://www.theserverside.com/articles/article.tss?l=JSFTapestry</A><BR>JSF的竞争对手不是struts/webwork之流，它们基本上已经是不同阶段上的东西了，放在一起比较意义不大。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;JSF的开发流程和asp.net中所倡导的code&nbsp;behind方式很相似，核心是事件驱动，组件和标签的封装程度非常高，很多典型应用已经不需要开发者去处理http。页面操作会被自动映射到对应的java&nbsp;bean中，后台逻辑只需要同java&nbsp;bean发生交互。整个过程是通过“依赖注入(DI)”来实现的，看来这是目前解偶合的最佳途径啊，spring的影响真是深远。不过正式因为jsf采用了这样的方式，导致开发工作和以前的jsp/struts等都有非常大的不同，需要一定的时间去学习。学习之前建议先对依赖注入有比较清楚的认识，可以参考我的learn&nbsp;Spring&nbsp;in&nbsp;spring系列的第一篇。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;本系列将以两个例子来讲解jsf的基本开发，第一个例子当然是hello&nbsp;world。目前可用的jsf&nbsp;ide不多，ibm要到06年才能放出支持jsf的wtp版本。所以我们的例子基本以手写为主，这样也能让我们有更清楚的认识，同时推荐目前最好的jsf开发工具：myeclipse&nbsp;4.0&nbsp;GA。后面的例子将会有jsf和hibernate的内容，它都能给予很好的支持。由于myeclipse并不免费，所以我们除了讲解在ide中如何操作外，还会叙述手动操作的具体内容，以免过于依赖开发工具。用什么服务器都可以，这里采用了jboss&nbsp;4.0.2。如果你的服务器是高版本的tomcat(5.5+)，那么必须要删除它自带的一些包才能很好的支持jsf，具体细节请查看它的文档。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;请自行下载jsf&nbsp;ri和JSTL&nbsp;1.1。<BR><BR>废话少说，开始了。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;在myeclipse&nbsp;4.0GA中新建一个web项目，命名为hello，为项目增加对JSTL的支持：<BR><BR><IMG src="http://blog.yam.com/bromon/94ed0325.jpg"><BR>&nbsp;<BR>在JSTL的版本中选择1.1。<BR>该操作实际上是把jstl.jar和standard.jar加到工程中。<BR><BR>采用类似的操作为项目添加对jsf的支持：myeclipse?add&nbsp;jsf&nbsp;capabilities<BR>如图：<BR>&nbsp;<BR><IMG src="http://blog.yam.com/bromon/7623ed1f.jpg"><BR><BR>其中的jsf&nbsp;implementation是选择使用哪中JSF实现，我们采用的是sun的jsf&nbsp;ri<BR>JSF&nbsp;config&nbsp;path是配置文件的位置，保持不变<BR>URL&nbsp;pattern是jsf&nbsp;servlet的映射方式，有两种选择，具体细节后面说明。<BR>以上操作上是为项目加入了jsf需要的jar和tld文件，并且创建了一个faces-config.xml的配置文件。涉及到的jar有：commons-beanutils.jar&nbsp;&nbsp;&nbsp;&nbsp;commons-collections.jar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;commons-digester.jar&nbsp;&nbsp;&nbsp;&nbsp;commons-logging.jar&nbsp;&nbsp;&nbsp;&nbsp;jsf-api.jar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jsf-impl.jar<BR>涉及到了jsf中所有的tld文件。<BR><BR>当前的faces-config.xml文件的内容是：<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;<BR>&lt;!DOCTYPE&nbsp;faces-config&nbsp;PUBLIC&nbsp;"-//Sun&nbsp;Microsystems,&nbsp;Inc.//DTD&nbsp;JavaServer&nbsp;Faces&nbsp;Config&nbsp;1.1//EN"&nbsp;"http://java.sun.com/dtd/web-facesconfig_1_1.dtd"&gt;<BR><BR>&lt;faces-config&gt;<BR><BR>&lt;/faces-config&gt;<BR><BR>环境已经建立好了，现在我们要建立一个程序，它的功能是让用户在表单中输入名字，提交后系统会返回一个问候。使用jsf的以后好处是，开发人员会很自然的把mvc各层分开，不会像使用strtus那样别扭，这一点在后面的开发中感觉得到。<BR><BR>首先开发model层，它是个很简单的bean：<BR>package&nbsp;org.bromon.jsf.model.hello;<BR><BR>public&nbsp;class&nbsp;SayHello&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;say(String&nbsp;name)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"你好,"+name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>在model层中你可以随意的实现业务的数据逻辑，不需要与web层有任何的关系。<BR><BR>下面开发控制层，它负责存取web层的数据，并且调用model层的逻辑：<BR>/**<BR>&nbsp;*&nbsp;jsf的控制层方法<BR>&nbsp;*&nbsp;@author&nbsp;bromon<BR>&nbsp;*/<BR>package&nbsp;org.bromon.jsf.control.hello;<BR><BR>import&nbsp;org.bromon.jsf.model.hello.*;<BR><BR>public&nbsp;class&nbsp;HelloDelegater&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;//------属性---------<BR>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;name;//表单中的文本框数据会传到这里<BR>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;result;//web页会从这里取得运行结果<BR>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;SayHello&nbsp;sayHello;//model层的对象,并不事例化,由系统注入<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;//-----set/get--------<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getName()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setName(String&nbsp;name)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name&nbsp;=&nbsp;name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;SayHello&nbsp;getSayHello()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sayHello;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setSayHello(SayHello&nbsp;sayHello)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.sayHello&nbsp;=&nbsp;sayHello;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getResult()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setResult(String&nbsp;result)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.result&nbsp;=&nbsp;result;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;//-----逻辑方法---------<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;say()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.setResult(sayHello.say(this.getName()));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"ok";<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>需要注意的是，属性的名字、set/get方法的名字必须严格按照java&nbsp;bean规范编写，因为它们要被注入依赖时使用。sayHello对象并没有被实例化，它会在运行时由系统注入。<BR><BR>这两个bean当然要在系统中申明，否则无法实现DI。在faces-config.xml文件中添加内容：<BR>&lt;managed-bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-name&gt;SayHello&lt;/managed-bean-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.bromon.jsf.model.hello.SayHello<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/managed-bean-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-scope&gt;request&lt;/managed-bean-scope&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/managed-bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-name&gt;HelloDelegater&lt;/managed-bean-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.bromon.jsf.control.hello.HelloDelegater<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/managed-bean-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-bean-scope&gt;request&lt;/managed-bean-scope&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;managed-property&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property-name&gt;sayHello&lt;/property-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;#{SayHello}&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/managed-property&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/managed-bean&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;在后一个bean中，它的sayHello属性被指定要在运行时注入一个org.bromon.jsf.model.hello.SayHello的实例。<BR><BR>下面要编写表示层的页面，只有一个index.jsp：<BR>需要引入两个标签库：<BR><BR>&lt;%@&nbsp;taglib&nbsp;uri="http://java.sun.com/jsf/html"&nbsp;prefix="h"&nbsp;%&gt;<BR>&lt;%@&nbsp;taglib&nbsp;uri="http://java.sun.com/jsf/core"&nbsp;prefix="f"&nbsp;%&gt;<BR>下面是构造jsf标签：<BR><BR>&lt;body&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;f:view&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:form&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:panelGrid&nbsp;columns="3"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:outputLabel&nbsp;for="name"&nbsp;value="姓名:"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:inputText&nbsp;id="name"&nbsp;value="#{HelloDelegater.name}"&nbsp;required="true"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:message&nbsp;for="name"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:outputLabel&nbsp;value="#{HelloDelegater.result}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/h:panelGrid&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:panelGroup&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h:commandButton&nbsp;action="#{HelloDelegater.say}"&nbsp;value="提交"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/h:panelGroup&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/h:form&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/f:view&gt;<BR>&nbsp;&nbsp;&lt;/body&gt;<BR><BR>页面中包含了一个文本框和一个label，他们分别被绑定到了HelloDelegater类的两个属性上，具体的绑定工作有系统通过翻转控制的方式调用对应的set/get方式实现。提交按钮被绑定到了HelloDelegater.say方法，该方法会把计算结果赋给result属性，它会在页面中显示出来。<BR><BR>因为我们在url&nbsp;pattern中选择了*.faces,所以我们应该访问如下地址来查看程序:<BR>http://localhost:8080/hello/index.faces<BR>相应的,如果你选择了/faces/*,那么就应该是:<BR>http://localhost:8080/hello/faces/index.jsp<BR><BR>程序执行结果如下：<BR><BR><IMG src="http://blog.yam.com/bromon/d3cf63f4.jpg"><BR>&nbsp;<BR>bromon原创<img src ="http://www.blogjava.net/gf7/aggbug/15565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-10-15 11:16 <a href="http://www.blogjava.net/gf7/archive/2005/10/15/15565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sun Java Studio Creator中使用数据绑定组件访问数据库(JSF)</title><link>http://www.blogjava.net/gf7/archive/2005/09/25/14034.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sun, 25 Sep 2005 14:41:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/25/14034.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/14034.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/25/14034.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/14034.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/14034.html</trackback:ping><description><![CDATA[在此演练中，您将在 Sun Java™ Studio Creator 应用程序开发环境 (IDE) 中创建和部署一个简单的 Web 应用程序<BR>"travel center"。向页面中添加两个组件，并将那些数据识别组件绑定到本地数据库。然后，生成应用程序并将其<BR>部署到本地应用服务器，在客户机 Web 浏览器上运行该应用程序。<BR>内容<BR>• 创建项目<BR>• 添加 Dropdown List 组件<BR>• 将组件连接到数据库<BR>• 运行 Web 应用程序<BR>• 添加 Data Table<BR>• 修改 SQL 查询<BR>• 控制显示的行<BR>要完成此演练，系统上应该已经安装了 IDE，并且您已经阅读了 Java Studio Creator 入门 教程。<BR>创建项目<BR>开发 Web 应用程序从创建项目开始。就像在入门教程中学习的那样，项目是 IDE 中的基本工作单元。项目包含<BR>组成应用程序的所有源代码和资源。<BR>1. 在“欢迎”屏幕上单击“创建新项目”。<BR>2. 在“新建项目”对话框的“名称”文本字段中，键入 TravelCenter。<BR>3. 选择“缺省 J2EE Web 应用程序”模板（如果尚未选定），然后单击“确定”。<BR>通过这些步骤会创建两个重要的文件，在本教程的其他部分中也将用到这两个文件。<BR>• Page1.jsp－JavaServer Pages™ 中包含组成 Web 应用程序的组件。最初，在应用程序中只有一个 JSP™<BR>页，但是随后您可以添加更多的页面。<BR>• Page1.java－包含页面状态并使其在不同的呈现中保持一致的 JavaBeans™ Bean。缺省情况下代码是不<BR>可见的，但是您可以通过右键单击页面，然后在上下文菜单中选择“查看 Page1 Java 类”来显示它。<BR>添加 Dropdown List 组件<BR>接下来，向页面中添加 Dropdown List 组件。<BR>1. 在组件面板中，选择“JSF”&gt;“JSF 标准组件”，然后将 Dropdown List 组件拖到页面上。<BR>Dropdown List 组件将出现在 Page1.jsp 页面上。您可以通过使用选择句柄来调整组件的大小，也可以<BR>1<BR>Sun Java Studio Creator<BR>将组件移动到新位置。<BR>2. 右键单击页面背景，然后在上下文菜单中选择“查看 Page1 Java 类”。<BR>会在源编辑器中打开页面的 JavaBeans 源代码。<BR>3. 在“选择类成员”下拉列表中选择 "dropdown1" 以导航到实例变量声明。（“选择类成员”下拉列表位于<BR>源编辑器工具栏中。）<BR>初始化 Dropdown List 组件的 Java 代码已添加到 Page1 类实现。<BR>private HtmlSelectOneMenu dropdown1 = new HtmlSelectOneMenu();<BR>将组件连接到数据库<BR>在此部分中，使 Dropdown List 组件可以从数据库表获得项。<BR>1. 单击源编辑器顶部的 Page1.jsp 标签以查看页面。<BR>2. 从“服务器导航”中，将“数据源”&gt; "Travel" &gt;“表”&gt; "PERSON" 节点拖放到 Dropdown List 组件的上<BR>面。<BR>将出现一个对话框，且 personRowSet 已添加到非可视组件托盘中。<BR>注如果 PointBase Embedded 数据库没有运行，则您将看到一个“错误”对话框，告诉您这一情况。如果看<BR>到此对话框，请关闭“错误”对话框，在“服务器导航”中右键单击“PointBase 数据库服务器”节点，<BR>然后在上下文菜单中选择“启动 PointBase”。然后，右键单击“数据源”&gt;<BR>"Travel"，并从上下文菜单中选择 “刷新”。现在，您应该能够定位到 "Travel" 数据源节点。<BR>3. 单击“填充列表”。<BR>因为 PERSON.NAME 列属于 SQL 类型 varchar，在 Dropdown List 组件中将显示文本 "abc"，指示所显<BR>示的数据是一个字符串。<BR>注如果没看到这个对话框，是因为 PERSON 节点没有被直接放到 Dropdown List 组件的上面。在这种情况<BR>下，在执行下一步时，请确保如图 1 所示选定了 PERSON.PERSONID 和 PERSON.NAME 列。<BR>4. 右键单击 Dropdown List 组件，然后从上下文菜单中选择“从数据库填充列表”。<BR>“值字段”被绑定到 PERSON.PERSONID 列，该列是 PERSON 表的主键。此字段提供由 JSF 组件的<BR>getValue() 方法返回的值。另一方面，“显示字段”被绑定到 PERSON.NAME 列，是组件运行时所显<BR>示的内容。<BR>5. 单击“确定”。<BR>运行 Web 应用程序<BR>现在，您可以部署和运行 Web 应用程序了。IDE 附带有一个已经安装的本地部署服务器：<BR>• Sun Java™ System Application Server Platform Edition 8<BR>部署服务器是作为“服务器导航”中“部署服务器”节点下的一个节点安装的。通过部署服务器的上下文菜单<BR>（可通过右键单击它进行访问），可以启动或停止它。<BR>部署和运行 Web 应用程序<BR>1. 单击工具栏中的“全部保存”按钮。<BR>2. 单击工具栏中的“运行项目”按钮。<BR>IDE 将生成、部署和运行 TravelCenter 应用程序。首先，“生成输出”窗口出现在 IDE 布局的底部。有关<BR>编译的信息和部署准备将输出到此窗口。（如果在生成时出现问题，请首先检查“生成输出”窗口。）接<BR>下来，将打开一个对话框，其中显示部署的状态。<BR>部署之后，将使用 URL <A href="http://localhost:18080/travelcenter/">http://localhost:18080/travelcenter/</A> 为应用程序打开一个新的 Web 浏览器<BR>窗口。使用 PERSON 表的 NAME 列中的数据填充下拉列表。<BR>添加 Data Table<BR>接下来，向应用程序中添加一个 Data Table 组件，并将该组件与数据库表相连。<BR>1. 在组件面板中，单击“JSF 标准组件”，将 Data Table 拖至页面，并将它放置在 Dropdown List 组件的下<BR>面。<BR>2. 拖动“数据源”&gt; "Travel" &gt;“表”&gt; "TRIP" 节点，并将其放在 Data Table 上。确保整个 Data Table 组件的轮<BR>廓为蓝色时放置节点。如果只有列或列标题的轮廓为蓝色，请将节点在组件内四处移动，直到整个组件的<BR>轮廓为蓝色。<BR>如果将节点放在列或列标题上，会出现“选择目标”对话框，而且 tripRowSet 已添加到非可视组件托<BR>盘中。确保选中了 "dataTable1" 单选按钮，然后单击“确定”关闭对话框。<BR>3. 右键单击 Data Table 组件，然后选择“表布局”。<BR>注如果没有选定 Data Table 组件，或者选定了它的其中一个子组件（在本例中是列），则在右键单击 Data<BR>Table 时，将出现另外的上下文菜单。在这种情况下，请选择 "dataTable1" &gt;“表布局”。您可以按 Esc<BR>键选择当前所选组件的父组件。<BR>出现“表布局”对话框。这两个列表表明哪些列可用于显示以及正在显示哪些内容。将 TRIP 表放在 Data<BR>Table 组件上时，将选择所有可用的列进行显示。<BR>4. 选择“显示”列表中的第一列 (TRIP.TRIPID)，然后单击 "&lt;" 按钮。<BR>将从“显示”列表中移除该列。<BR>5. 移除 TRIP.PERSONID 和 TRIP.TRIPTYPEID 列。<BR>仍然出现在“显示”列表中的三列：<BR>• TRIP.DEPDATE<BR>• TRIP.DEPCITY<BR>• TRIP.DESTCITY<BR>使用数据绑定组件访问数据库 ▪ <BR>Sun Java Studio Creator<BR>6. 单击“确定”。<BR>现在，Data Table 组件中有三个显示列。<BR>修改 SQL 查询<BR>在此部分中，将修改 TRIP 行集对象中的 SQL 查询，以便查询返回 TRIPTYPE 表中的数据。您还将修改 Data<BR>Table 组件以显示新列。<BR>1. 右键单击非可视组件托盘中的 tripRowSet，然后选择“编辑行集查询”。<BR>在编辑器窗格中将出现查询编辑器。标签的名称是 tripRowSet。<BR>2. 右键单击设计视图（见图 4），然后选择“添加表”。<BR>3. 选择 TRAVEL.TRIPTYPE 表，然后单击“确定”。<BR>将出现另一个表格图，在两个表格图之间有一个链接。<BR>4. 在指示的表中取消选中以下复选框：<BR>• TRIP 表中的 TRIPID<BR>• 两个表中的 TRIPTYPEID<BR>会从结果集中删除上述列。同时会修改源视图中的 SQL 查询以反映这些更改。<BR>4 使用数据绑定组件访问数据库 ▪ <BR>图 2 显示的列<BR>图 3 第 1 列处于选定状态的 Data Table<BR>Sun Java Studio Creator<BR>5. 选择 Page1.jsp 标签以返回到可视编辑器。<BR>6. 右键单击 Data Table，然后选择“表布局”。<BR>将出现“表布局”对话框。由于您已经更改了行集的 SQL 查询，因此有更多可以显示的列。<BR>7. 将 TRIPTYPE.DESCRIPTION 列添加到“显示”列表中。<BR>8. 单击“确定”。<BR>第四列将出现在 Data Table 组件中。<BR>控制显示的行<BR>在上一部分中将 TRIP 表放在 Data Table 组件上时，IDE 使用返回表中所有列的所有行的 SQL 查询创建了一个<BR>行集对象。如果此时部署应用程序，则数据表将包含 TRIP 表中的所有行程信息。<BR>假定您仅希望显示其名字出现在 Dropdown List 组件中人员的行程信息。您必须通过编辑 TRIP 行集对象的缺省查<BR>询，在 Dropdown List 组件和 Data Table 组件之间创建主从关系 (Master-Detail)。<BR>1. 双击 tripRowSet 对象打开查询编辑器。<BR>2. 在查询编辑器的设计网格（电子表格）中，右键单击设计网格 PERSONID 行中的“条件”单元格，然后<BR>选择“添加查询条件”。<BR>使用数据绑定组件访问数据库 ▪ <BR>图 4 查询编辑器<BR>设计视图<BR>设计网格<BR>源代码<BR>Sun Java Studio Creator<BR>3. 将“比较”下拉菜单设置为“=等于”，并选择“参数”单选按钮。<BR>4. 单击“确定”。<BR>在 PERSONID 的“条件”列中您会看到 "=?"，它在 SQL 查询中添加了以下 WHERE 子句：<BR>WHERE TRAVEL.TRIP.PERSONID = ?<BR>5. 通过选择 Page1.jsp 标签，返回到可视编辑器，然后双击 Dropdown List 组件。<BR>Page1 类的源代码在编辑器区域中打开，且光标位于 dropdown1_processValueChange() 方法主体<BR>内。此事件处理程序方法存根 (Stub) 是在您首次双击 Dropdown List 组件时创建的。<BR>6. 从“组件面板”&gt;“代码片段”&gt;“演示”拖动 Travel dropdown 代码片段，将其放在<BR>dropdown1_processValueChange() 方法体中。<BR>6 使用数据绑定组件访问数据库 ▪ <BR>图 5 “添加查询条件”对话框<BR>Sun Java Studio Creator<BR>public void dropdown1_processValueChange(ValueChangeEvent vce) {<BR>// User event code here...<BR>try {<BR>dataTable1Model.setObject(1, dropdown1.getValue());<BR>dataTable1Model.execute();<BR>} catch (Exception e) {<BR>log("person change exception", e);<BR>error(“Exception changing person id:”+e);<BR>} // end try catch<BR>}<BR>这段代码将下拉列表的值绑定到为 dataTable1Model 准备的 SQL 语句中的参数上。<BR>7. 在 Page1 类中找到 Page1() 构造函数。<BR>8. 从“组件面板”&gt;“代码片段”&gt;“演示”拖动 Travel initialization 代码片段，并将其放在 Page1() 构造<BR>函数实现的结尾处。<BR>public Page1() {<BR>// other lines of code omitted<BR>catch ( Exception e) {<BR>log("Page1 Initialization Failure", e);<BR>throw new FacesException(e);<BR>}<BR>// Additional user provided initialization code<BR>try {<BR>personRowSet.execute();<BR>personRowSet.next();<BR>dataTable1Model.setObject(1, personRowSet.getObject("PERSONID"));<BR>} catch (Exception ex) {<BR>throw new FacesException(ex);<BR>} // end try catch<BR>}<BR>这段代码将把下拉列表中当前选定 NAME 的 PERSONID 值绑定到为 dataTable1Model 准备的 SQL 语句<BR>中的参数上。<BR>9. 通过选择 Page1.jsp 标签返回到可视编辑器。<BR>10.右键单击 Dropdown List 组件，然后选择“更改时自动提交”。<BR>在属性表单中，以下代码将出现在 "Javascript" &gt; "onchange" 属性中：<BR>this.form.submit();<BR>现在，当用户在运行的 Web 应用程序中更改下拉列表选择时，将重新提交和更新页面。<BR>11.单击工具栏上的“全部保存”。<BR>12.单击工具栏上的“运行项目”。<BR>将重新生成和部署 Web 应用程序。在下拉列表中选择另一个名字，您会注意到更新了数据表。<BR>使用数据绑定组件访问数据库 ▪ 2004 6 年月 7<BR>Sun Java Studio Creator<BR>请参见<BR>• Java Studio Creator 入门<BR><BR><STRONG>本文下载地址：</STRONG><BR>&nbsp;<A href="http://mail.yl.gov.cn/ftp/yy/jscb2005.rar">http://mail.yl.gov.cn/ftp/yy/jscb2005.rar</A><img src ="http://www.blogjava.net/gf7/aggbug/14034.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-25 22:41 <a href="http://www.blogjava.net/gf7/archive/2005/09/25/14034.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>表现层框架Struts/Tapestry/JSF架构比较</title><link>http://www.blogjava.net/gf7/archive/2005/09/23/13872.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Sep 2005 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/23/13872.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/13872.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/23/13872.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/13872.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/13872.html</trackback:ping><description><![CDATA[JSF在很大程度上类似Struts，而不是类似Tapestry，可以说是一种Struts 2.0，都是采取标签库+组件的形式，只是JSF的组件概念没有象Struts那样必须继承ActionForm的限制；JSF在事件粒度上要细腻，不象Struts那样，一个表单一个事件，JSF可以细化到表单中的每个字段上。
<P>　　JSF只有在组件和事件机制这个概念上类似Tapestry，但是不似Tapestry那样是一个完全组件的框架，所以，如果你做一个对页面要求灵活度相当高的系统，选用Tapestry是第一考虑。</P>
<P>　　Struts/JSF则适合在一般的数据页面录入的系统中，对于Struts和JSF的选用，我目前个人观点是：如果你是一个新的系统，可以直接从JSF开始；如果你已经使用Struts，不必转换，如果需要切换，可以将JSF和Tapestry一起考虑。</P>
<P>　　另外，JSF/Tapestry不只是支持Html，也支持多种客户端语言如WML或XUI等。</P>
<P>　　这三者之间关系：如果说Struts是左派；那Tapestry则是右派；而JSF则是中间派，中庸主义是SUN联盟的一贯策略。</P>
<P>　　当然，你也可以发表你在实践中这三者任何一个的使用感受，以使得后来者有一个比较。<BR><BR></P>
<P align=left>我们通过下表来比较这 三种框架在实现上图各个功能时技术细节，从而得出他们的异同点和偏重点。</P>
<P>
<TABLE cellSpacing=1 cellPadding=1 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#cccccc>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD width="16%">&nbsp;</TD>
<TD width="29%">Struts</TD>
<TD width="33%">Tapestry3.0</TD>
<TD width="22%">JSF</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>在View显示的组件要求</TD>
<TD>
<P>组件必须继承ActionForm</P></TD>
<TD>分显式调用和隐式调用<BR>组件必须继承BaseComponent</TD>
<TD>普通POJO<BR>无需继承<BR>Managed Bean</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>组件在View显示粒度</TD>
<TD>View页面只能显示与表单对应的ActionForm，配置中Action ActionForm 页面一般只能1:1:1关系。</TD>
<TD>可将组件嵌入页面任何一行，对使用组件数量无限制。</TD>
<TD>同Tapestry</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>页面分区tiles</TD>
<TD>使用Tiles标签库实现，需要另外tiles-def.xml配置文件</TD>
<TD>组件有自己的视图页面，通过调用组件即直接实现多个页面组合。强大自然的页面组合是其特点。</TD>
<TD>通过组件+标签库实现Subview,但如需重用Layout,还要结合Tiles.</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>页面跳转</TD>
<TD>使用标签库html:link中写明目标URL，URL名称需要对照配置文件的path命名,与组件Action耦合。</TD>
<TD>URL名称是目标的组件名称，不涉及URL和路径等操作，方便稳固。</TD>
<TD>类似Struts，也需要在配置文件中查找,与组件分离。</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>参数传递</TD>
<TD>使用html:link时传递参数超过一个以上处理麻烦。</TD>
<TD>直接调用组件，直接赋予参数，没有参数个数限制</TD>
<TD>参数分离传递给组件</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>事件触发</TD>
<TD>通过表单提交submit激活，不能细化到表单里字段。</TD>
<TD>能够给于表单每个字段贴一个事件，事件组件必须实现PageListener接口</TD>
<TD><SPAN id=intelliTxt><CODE>同Tapestry，事件组件必须实习ActionListener 接口</CODE></SPAN></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></P><img src ="http://www.blogjava.net/gf7/aggbug/13872.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-23 22:28 <a href="http://www.blogjava.net/gf7/archive/2005/09/23/13872.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSF与Struts的区别 </title><link>http://www.blogjava.net/gf7/archive/2005/09/23/13868.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Sep 2005 14:17:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/23/13868.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/13868.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/23/13868.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/13868.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/13868.html</trackback:ping><description><![CDATA[Struts和JSF/Tapestry都属于表现层框架，这两种分属不同性质的框架，后者是一种事件驱动型的组件模型，而Struts只是单纯的MVC模式框架，老外总是急吼吼说事件驱动型就比MVC模式框架好，何以见得，我们下面进行详细分析比较一下到底是怎么回事？
<P>　　首先事件是指从客户端页面（浏览器）由用户操作触发的事件，Struts使用Action来接受浏览器表单提交的事件，这里使用了Command模式，每个继承Action的子类都必须实现一个方法execute。</P>
<P>　　在struts中，实际是一个表单Form对应一个Action类(或DispatchAction)，换一句话说：在Struts中实际是一个表单只能对应一个事件，struts这种事件方式称为application event，application event和component event相比是一种粗粒度的事件。</P>
<P>　　struts重要的表单对象ActionForm是一种对象，它代表了一种应用，这个对象中至少包含几个字段，这些字段是Jsp页面表单中的input字段，因为一个表单对应一个事件，所以，当我们需要将事件粒度细化到表单中这些字段时，也就是说，一个字段对应一个事件时，单纯使用Struts就不太可能，当然通过结合JavaScript也是可以转弯实现的。</P>
<P>　　而这种情况使用JSF就可以方便实现，</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>&lt;h:inputText id="userId" value="#{login.userId}"&gt;<BR>　　&lt;f:<STRONG>valueChangeListener</STRONG> type="logindemo.UserLoginChanged" /&gt;<BR>&lt;/h:inputText&gt;</TD></TR></TBODY></TABLE>
<P>　　#{login.userId}表示从名为login的JavaBean的getUserId获得的结果，这个功能使用struts也可以实现，name="login" property="userId" </P>
<P>　　关键是第二行，这里表示如果userId的值改变并且确定提交后，将触发调用类UserLoginChanged的processValueChanged(...)方法。</P>
<P>　　JSF可以为组件提供两种事件：Value Changed和 Action. 前者我们已经在上节见识过用处，后者就相当于struts中表单提交Action机制，它的JSF写法如下：</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>&lt;h:commandButton id="login" commandName="login"&gt;<BR>　　&lt;f:<STRONG>actionListener</STRONG> type=”logindemo.LoginActionListener” /&gt;<BR>&lt;/h:commandButton&gt;</TD></TR></TBODY></TABLE>
<P>　　从代码可以看出，这两种事件是通过Listerner这样观察者模式贴在具体组件字段上的，而Struts此类事件是原始的一种表单提交Submit触发机制。如果说前者比较语言化（编程语言习惯做法类似Swing编程）；后者是属于WEB化，因为它是来自Html表单，如果你起步是从Perl/PHP开始，反而容易接受Struts这种风格。</P>
<P><STRONG>基本配置</STRONG></P>
<P>　　Struts和JSF都是一种框架，JSF必须需要两种包JSF核心包、JSTL包（标签库），此外，JSF还将使用到Apache项目的一些commons包，这些Apache包只要部署在你的服务器中既可。</P>
<P>　　JSF包下载地址：<A href="http://java.sun.com/j2ee/javaserverfaces/download.html" target=_blank>http://java.sun.com/j2ee/javaserverfaces/download.html</A>选择其中<B>Reference Implementation。</B></P>
<P>　　JSTL包下载在<A href="http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi" target=_blank>http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi</A><BR><BR>　　所以，从JSF的驱动包组成看，其开源基因也占据很大的比重，JSF是一个SUN伙伴们工业标准和开源之间的一个混血儿。</P>
<P>　　上述两个地址下载的jar合并在一起就是JSF所需要的全部驱动包了。与Struts的驱动包一样，这些驱动包必须位于Web项目的WEB-INF/lib，和Struts一样的是也必须在web.xml中有如下配置：</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>&lt;web-app&gt;<BR>　　&lt;servlet&gt;<BR>　　　　&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<BR>　　　　&lt;servlet-class&gt;javax.faces.webapp.FacesServlet&lt;/servlet-class&gt;<BR>　　　　&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<BR>　　&lt;/servlet&gt; 
<P>　　&lt;servlet-mapping&gt;<BR>　　　　&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<BR>　　　　&lt;url-pattern&gt;*.faces&lt;/url-pattern&gt;<BR>　　&lt;/servlet-mapping&gt; <BR>&lt;/web-app&gt;</P></TD></TR></TBODY></TABLE>
<P>　　这里和Struts的web.xml配置何其相似，简直一模一样。</P>
<P>　　正如Struts的struts-config.xml一样，JSF也有类似的faces-config.xml配置文件：</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD><BR>&lt;faces-config&gt;<BR>　　&lt;navigation-rule&gt;<BR>　　　　&lt;from-view-id&gt;/index.jsp&lt;/from-view-id&gt;<BR>　　　　&lt;navigation-case&gt;<BR>　　　　　　&lt;from-outcome&gt;login&lt;/from-outcome&gt;<BR>　　　　　　&lt;to-view-id&gt;/welcome.jsp&lt;/to-view-id&gt;<BR>　　　　&lt;/navigation-case&gt;<BR>　　&lt;/navigation-rule&gt; 
<P>　　&lt;managed-bean&gt; <BR>　　　　&lt;managed-bean-name&gt;user&lt;/managed-bean-name&gt;<BR>　　　　&lt;managed-bean-class&gt;com.corejsf.UserBean&lt;/managed-bean-class&gt; <BR>　　　　&lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt; <BR>　　&lt;/managed-bean&gt;<BR>&lt;/faces-config&gt;</P>
<P>&nbsp;</P></TD></TR></TBODY></TABLE>
<P>　　在Struts-config.xml中有ActionForm Action以及Jsp之间的流程关系，在faces-config.xml中，也有这样的流程，我们具体解释一下Navigation：</P>
<P>　　在index.jsp中有一个事件：</P>
<P>&lt;h:commandButton label="Login" action="login" /&gt;</P>
<P>　　action的值必须匹配form-outcome值，上述Navigation配置表示：如果在index.jsp中有一个login事件，那么事件触发后下一个页面将是welcome.jsp</P>
<P>　　JSF有一个独立的事件发生和页面导航的流程安排，这个思路比struts要非常清晰。</P>
<P>　　managed-bean类似Struts的ActionForm，正如可以在struts-config.xml中定义ActionForm的scope一样，这里也定义了managed-bean的scope为session。</P>
<P>　　但是如果你只以为JSF的managed-bean就这点功能就错了，JSF融入了新的Ioc模式/依赖性注射等技术。</P>
<P><STRONG>Ioc模式</STRONG></P>
<P>　　对于Userbean这样一个managed-bean，其代码如下：</P>
<P>public class UserBean {<BR>　　private String name;<BR>　　private String password;</P>
<P>　　// PROPERTY: name<BR>　　public String getName() { return name; }<BR>　　public void setName(String newValue) { name = newValue; }</P>
<P>　　// PROPERTY: password<BR>　　public String getPassword() { return password; }<BR>　　public void setPassword(String newValue) { password = newValue; }<BR>}<BR></P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>
<P></P>
<P>&lt;managed-bean&gt;<BR>　　&lt;managed-bean-name&gt;user&lt;/managed-bean-name&gt;<BR>　　&lt;managed-bean-class&gt;com.corejsf.UserBean&lt;/managed-bean-class&gt;<BR>　　&lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt;<BR><BR>　　&lt;managed-property&gt;<BR>　　　　&lt;property-name&gt;name&lt;/property-name&gt;<BR>　　　　&lt;value&gt;me&lt;/value&gt;<BR>　　&lt;/managed-property&gt;<BR><BR>　　&lt;managed-property&gt;<BR>　　　　&lt;property-name&gt;password&lt;/property-name&gt;<BR>　　　　&lt;value&gt;secret&lt;/value&gt;<BR>　　&lt;/managed-property&gt;<BR>&lt;/managed-bean&gt;</P></TD></TR></TBODY></TABLE>
<P>　　faces-config.xml这段配置其实是将"me"赋值给name，将secret赋值给password，这是采取<A href="http://www.jdon.com/AOPdesign/Ioc.htm" target=_blank>Ioc模式中的Setter注射方式</A>。</P>
<P><STRONG>Backing Beans</STRONG></P>
<P>　　对于一个web form，我们可以使用一个bean包含其涉及的所有组件，这个bean就称为Backing Bean， Backing Bean的优点是：一个单个类可以封装相关一系列功能的数据和逻辑。</P>
<P>　　说白了，就是一个Javabean里包含其他Javabean，互相调用，属于Facade模式或Adapter模式。</P>
<P><BR>　　对于一个Backing Beans来说，其中包含了几个managed-bean，managed-bean一定是有scope的，那么这其中的几个managed-beans如何配置它们的scope呢？</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>&lt;managed-bean&gt;<BR>　　...<BR>　　&lt;managed-property&gt;<BR>　　　　&lt;property-name&gt;visit&lt;/property-name&gt;<BR>　　　　&lt;value&gt;#{sessionScope.visit}&lt;/value&gt;<BR>　　&lt;/managed-property&gt;<BR></TD></TR></TBODY></TABLE>
<P>　　这里配置了一个Backing Beans中有一个setVisit方法，将这个visit赋值为session中的visit，这样以后在程序中我们只管访问visit对象，从中获取我们希望的数据（如用户登陆注册信息），而visit是保存在session还是application或request只需要配置既可。</P>
<P><STRONG>UI界面</STRONG></P>
<P>　　JSF和Struts一样，除了JavaBeans类之外，还有页面表现元素，都是是使用标签完成的，Struts也提供了struts-faces.tld标签库向JSF过渡。</P>
<P>　　使用Struts标签库编程复杂页面时，一个最大问题是会大量使用logic标签，这个logic如同if语句，一旦写起来，搞的JSP页面象俄罗斯方块一样，但是使用JSF标签就简洁优美：</P>
<TABLE width="90%" bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD>
<P>&lt;jia:navigatorItem name="inbox" label="InBox"<BR>　　icon="/images/inbox.gif"<BR>　　action="inbox"<BR>　　disabled="#{!authenticationBean.inboxAuthorized}"/&gt;<BR></P></TD></TR></TBODY></TABLE>
<P>　　如果authenticationBean中inboxAuthorized返回是假，那么这一行标签就不用显示，多干净利索！</P>
<P>　　先写到这里，我会继续对JSF深入比较下去，如果研究过Jdon框架的人，可能会发现，Jdon框架的jdonframework.xml中service配置和managed-bean一样都使用了依赖注射，看来对Javabean的依赖注射已经迅速地成为一种新技术象征，如果你还不了解Ioc模式，赶紧补课。<BR>附Jsf核心教程一个JSF案例:<A href="http://www.jdon.com/idea/login.rar" target=_blank>login.rar</A><BR></P><img src ="http://www.blogjava.net/gf7/aggbug/13868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-23 22:17 <a href="http://www.blogjava.net/gf7/archive/2005/09/23/13868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于M7的NitroX 2.1的破解! </title><link>http://www.blogjava.net/gf7/archive/2005/09/23/13866.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Sep 2005 13:54:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/23/13866.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/13866.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/23/13866.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/13866.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/13866.html</trackback:ping><description><![CDATA[<DIV class=forumcontent>方法： 找到 jstudio.jar 包中， 反编译包中 com.m7.wide.A.G, com.m7.wide.A.N, com.m7.wide.eclipse.license.ui.LicenseUIManager 三个主要文件，再反编译 com.m7.wide.A.A.B 替换成 com.m7.wide.A.BB(在 com.m7.wide.A.G.java中的 B换成BB这样就可以编译了),上面三个主要文件中， G中public static H A(String s1,String s2,String s3) 和public static H B(String s, String s1, String s2)很重要，G用来据判断创建N，N为LICENSE的实现，在N中的P变量为限制日期, N中变量参考: L = "qcfqBUugu2D79g1ZJBDDqA==0000";<BR>A="0000"; <BR>I="02"; <BR>T="21";<BR>K="trial"; <BR>N="S-1-5-21-1078081533-436374069-1343024091";<BR>H= new Date();<BR>P=new Date(System.currentTimeMillis()+10*24*3600*1000l);<BR>C="__anonymoustrial__32847@m7.com";<BR>J=true; <BR>这是trial版本，对应G.A中来创建，如果不是G.B中创建(同时注意public static boolean G(Properties properties)为false), 在LicenseUIManager中verifyLicense直接修改成return true 这样启动时就不会检测，但要以用它前18行进行自己破解的检验. 祝大家好运.</DIV><img src ="http://www.blogjava.net/gf7/aggbug/13866.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-23 21:54 <a href="http://www.blogjava.net/gf7/archive/2005/09/23/13866.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NitroX JSF IDE </title><link>http://www.blogjava.net/gf7/archive/2005/09/23/13865.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Sep 2005 13:34:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/23/13865.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/13865.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/23/13865.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/13865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/13865.html</trackback:ping><description><![CDATA[<SPAN class=javascript id=text145732>NitroX for jsf ide 一个可做为Eclipse的插件,包括上下文敏感的源码编辑、支持即拖即放的所见即所得的设计、错误检测、debugging工具、以及一些其他的JSF开发的Eclipse视图，使用起来感觉还不错。<BR>下载地址<BR><A href="http://www.m7.com/m7secure/secure/ExpressNitroXStrutsJsfTrialInstall-463.zip?m7key5=458575972227127_747927165746785">http://www.m7.com/m7secure/secure/ExpressNitroXStrutsJsfTrialInstall-463.zip?m7key5=458575972227127_747927165746785</A><BR>关于如何破解，另见说明。</SPAN><img src ="http://www.blogjava.net/gf7/aggbug/13865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-23 21:34 <a href="http://www.blogjava.net/gf7/archive/2005/09/23/13865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现图形JSF组件</title><link>http://www.blogjava.net/gf7/archive/2005/09/23/13860.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Sep 2005 12:56:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/09/23/13860.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/13860.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/09/23/13860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/13860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/13860.html</trackback:ping><description><![CDATA[<SPAN class=h1b>实现图形JSF组件</SPAN><BR><B>--很简单地构建一个纯HTML无法轻松实现的图形Web应用程序组件</B><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD height=64>时间：2005-07-07<BR>作者：<A href="http://dev2dev.bea.com.cn/author/350.html">Marc Durocher</A><BR>浏览次数：
<SCRIPT language=JavaScript src="http://203.81.25.103/cgi-bin/beadevcount.cgi?d_id=484" type=text/JavaScript></SCRIPT>
 524 <BR>本文关键字：<A href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=JSF">JSF</A></TD>
<TD></TD></TR></TBODY></TABLE><!-- 提取技术文章 -->
<DIV class=beas><IMG height=1 alt="" src="http://dev2dev.bea.com.cn/images/dot6B6B6B.gif" width="100%"></DIV>
<P>　　开发人员认为，如果有合适的工具来创建交互式Web界面，他们就能将时间集中在核心需求和定制上，并在规定时间内及时得交付应用程序。与其他技术如JavaServer Pages或Apache Struts 相比，JavaServer Faces (JSF)技术为创建交互式Web应用程序带来了很多便利。JSF在程序逻辑和GUI表示之间划出一条清晰的界限，提高了对Web程序的维护能力，并为Web用户界面组件的开发和重用提供了一个框架。</P>
<P>　　如今，许多Web应用程序开发人员都在转而使用JSF，但是他们发现，预先定制的JSF UI组件受到基本DHTML窗口部件的限制。监管或业务流程监控之类的高级应用程序需要能与JSF框架兼容的高级可视化组件。JSF框架的标准化使它易于开发能够重用的自定义Web GUI组件。另外，Web组件开发商现在能提供更复杂的组件，并承诺Web应用程序开发人员能够轻松地使用这些组件。此类JSF用户界面组件必须集成并部署到JSF运行时框架中去，并在其中完全展开，还必须在设计时很好地集成到提供JSF支持的IDE中去。</P>
<P>　　尽管JSF带来了标准用户界面框架，但对于开发第一个自定义JSF组件而言，还是存在几个缺陷和漏洞。让我们看看怎样创建一个纯HTML无法轻松创建的图形JSF组件。图形JSF组件的特点不仅要求生成DHTML，而且还需要对图像生成和客户端交互提供补充支持。我们将以一个图形组件的例子来阐述这些特点。该图形组件能够提供曲线图，并为各种客户端导航和交互提供便利。我们还会了解到将该图形组件集成到JSF-enabled IDE中所需要的步骤。通过理解图形组件的设计方法，您将会更好地理解如何实现JSF组件，而这应该能使您开发出定制的JSF图形组件。</P>
<P><STRONG>什么是JSF？</STRONG></P>
<P>　　JSF是一种能够简化Web应用程序表示层结构的标准服务器端框架。定义JSF框架的JSR 127（参见参考资料）带有一个能提供基本UI组件（如输入栏和按纽）的参考实现。您可以将可重用用户界面组件集中起来创建Web页，将这些组件绑定到应用数据源上，并用服务器端事件控制程序处理客户端事件。根据说明书介绍，组件供应商能编写与JSF运行时框架集成的组件，并将其集成到在设计时与JSF兼容的IDE中去。</P>
<P>　　从很大程度上讲，JSF组件同在HTML 2.0技术要求下可用的HTML组件和标签直接相符合。对许多Web应用程序而言，这套相对简单的组件是够用的。然而，许多应用程序如监管或监控程序需要更复杂的数据显示与交互，比如制表、制图和映射。由于JSF组件在HTML中直接提交复杂图形小部件的能力有限，所以设计这些高级组件的能力并不突出。解决方案要求服务器端组件向客户传输图像，却会给自身带来问题，因为在基本HTML图像上进行交互要受到限制。最后，使用JavaScript时，必须能调用客户端交互来使用户能对数据进行导航和交互。</P>
<P>　　让我们看看开发一个简单的、将CSS输入HTML页面的JSF组件需要哪些步骤。当开发高级JSF图形组件时，这一简单组件的描述和代码样本会作为背景。图1显示了如何使用即将开发的组件，并显示将要得到的结果。使用这种组件的好处是能够通过改变某个JSF动作的组件值，来改变整个页面的外观。 </P>
<P><IMG height=239 src="http://dev2dev.bea.com.cn/images/wlworkshop/images05070604_01.jpg" width=300> </P>
<P>图1：显示了我们如何使用一个非常简单的JSF组件将CSS输入某个HTML页面并得出结果。</P>
<P><STRONG>开发组件</STRONG></P>
<P>　　JSF组件包含若干个Java类和配置文件。为创建一个自定义JSF组件，您需要开发一个扩展JSF基本组件类的Java类；为默认呈现软件包开发呈现程序；开发一个将在JSP页面中用于描述标签的Java类；编写一个标签库定义（TLD）文件；编写JSF配置文件。让我们更深入地了解这5个步骤。</P>
<P>　　开发组件Java类。组件类负责管理代表组件状态的属性。因此，我们必须根据组件的行为（如输入组件或输出组件），给组件选择适当的基类（参见清单1）。这里描述的组件可进行扩展javax.faces.component.UIOutput，以显示指向某个样式表文件的URL，或内联式样式表的内容。该组件可用于在JSF动作中将某个样式表转换成另一个样式表。关联属性规定着值的类型：要么是一个URL，要么是内联样式。该组件还必须能够在向服务器发送请求期间，使用经过JSF框架处理的对象，来存储并修复自己的状态。组件的状态由重建对象所需的重要属性值组成。JSF框架自动调用saveState()和restoreState()方法，我们可以在组件中实现这两种方法来达到这一目标。</P>
<P align=left><STRONG>清单</STRONG><STRONG>1. </STRONG>组件类管理显示组件状态的属性。可依据组件的行为，为其选择一个适当的基类。在本例中，该组件扩展javax.faces.component.UIOutput，以显示指向某个样式表文件的URL，或者某个内联式样式表的内容。<STRONG></STRONG></P><PRE class=code>import javax.faces.component.*;
public class CSSComponent extends UIOutput {
	private Boolean link; 
	public String getFamily() { 
		return "faces.CSSFamily"; 
	} 
	public boolean isLink() { 
		if (link != null) 
			return link.booleanValue(); 
			ValueBinding vb = getValueBinding("link"); 
	if (vb != null) { 
		Boolean bvb = (Boolean) vb.getValue(
			FacesContext.getCurrentInstance()); 
		if (bvb != null) 
			return bvb.booleanValue(); 
	} 
	return false; 
	} 
	public void setLink(boolean link) { 
		this.link = new Boolean(link); 
	} 
	public Object saveState(FacesContext context) { 
		return new Object[] { super.saveState(context), 
			link }; 
	} 
	public void restoreState(FacesContext context, 
	Object stateObj) { 
		Object[] state = (Object[]) stateObj; 
		super.restoreState(context, state[0]); 
		link = (Boolean) state[1]; 
	} 
}
</PRE>
<P><STRONG>开发呈现程序。</STRONG>呈现程序有两个作用。第一，呈现程序负责发送适当的HTML程序段，该程序段能在客户端中呈现组件。通常情况下，这个HTML程序段由一些适于呈现整个Web浏览器的HTML标签组成。此JSF生存周期称作编码阶段或呈现—响应阶段。该响应阶段还能发送增强客户端交互性的JavaScript代码。</P>
<P>　　呈现程序的第二个作用是解析来自客户端的数据，从而对服务器端的组件状态进行更新（如用户在文本字段输入的文本）。标准呈现程序软件包具有强制性，但也可以提供其他呈现程序软件包，用于提供可替换的客户端表示法或SVG之类的语言（参见参考资料）。通过检验组件的连接属性，您实现的呈现程序（参见清单2）将选择在HTML页面中发送的CSS样式。</P>
<P align=left><STRONG>清单</STRONG><STRONG>2. </STRONG>标准呈现程序软件包具有强制性，但是，您可以使用其他呈现程序软件包，来提供可替换的客户端表示法或语言。通过检验组件的连接属性，您实现的呈现程序将选择在HTML页面中发出的CSS样式。</P><PRE class=code>import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
public class CSSRenderer extends Renderer {
public void encodeEnd(FacesContext context,
UIComponent component)
	throws IOException {
		super.encodeEnd(context, component);
		if (component instanceof CSSComponent) {
			CSSComponent cssComponent  =
				(CSSComponent) component;
			String css = (String)cssComponent.getValue();
			boolean isLink = cssComponent.isLink();
			if (css != null) 
				if (isLink)  
				context.getResponseWriter().write(
				"&lt;link type='text/css' rel='stylesheet' 
				href='" + css + "'/&gt;");
			else 
				context.getResponseWriter().write(
					"&lt;style&gt;;\n" + css + "\n&lt;style/&gt;\n"); 
		}
	}
}
</PRE>
<P><STRONG>开发标签类。</STRONG>同样，JSF框架提供了用于扩展的基类，来编写与组件相关的标签。该标签类负责定义并呈现将在faces-config.xml文件中应用的组件样式（这种样式的描述很简短）。它还负责创建JSF组件（由JSF框架来处理），传递JSF标签中所包含的属性，该属性用于初始化组件（参见清单3）。</P>
<P align=left><STRONG>清单</STRONG><STRONG>3. </STRONG>该标签类定义了将在faces-config.xml文件中应用的组件的样式和组件呈现方式。</P><PRE class=code>import javax.faces.webapp.UIComponentTag;
public class CSSTag 
	extends UIComponentTag {
	private String value;
	private String link;
	public String getComponentType() {
		return "faces.CSSComponent";
	}
	public String getRendererType() {
		return “HTML.LinkOrInlineRenderer";
	}
	protected void setProperties(UIComponent component) {
		super.setProperties(component);
		Application app = 
			getFacesContext().getApplication();
		if (value != null)
			if (isValueReference(value)) 
				component.setValueBinding("value", 
				app.createValueBinding(value));
			else
				component.getAttributes().put("value", value);
		if (link != null) 
			if (isValueReference(link))
				component.setValueBinding("link",
				app.createValueBinding(link));
			else
				component.getAttributes().put("link",
				new Boolean(link));
	}
	public String getLink() {
		return link;
	}
	public void setLink(String link) {
		this.link = link;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
}
</PRE>
<P>　　该标签提供setter和getter来管理链接和值属性。组件一旦创建，便会调用setProperties()方法，对标签属性进行初始化。每个标签属性都无外乎两种：要么是文字值，要么是bean属性的一个绑定。</P>
<P><STRONG>编写标签库定义（TLD</STRONG><STRONG>）。</STRONG>TLD是一个XML文件，它通过将标签名与相应的Java类相关联来描述标签。TLD还描述了标签所允许的属性（参见清单4）。这个TLD定义了一个名为css的标签，该标签绑定到CSSTag类。它还声明了链接和值标签属性。</P>
<P align=left><STRONG>清单</STRONG><STRONG>4. </STRONG>TLD是一个通过将标签名与相应的Java类相关联来描述标签的XML文件。TLD定义了名为css的标签，使其与CSSTag类绑定。它还声明了链接和值标签属性。</P><PRE class=code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE taglib PUBLIC 
	"-//Sun Microsystems, Inc.//
	DTD JSP Tag Library  1.2//EN" 
	"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"&gt;
&lt;taglib&gt;
	&lt;tlib-version&gt;1.0&lt;/tlib-version&gt;
	&lt;jsp-version&gt;1.2&lt;/jsp-version&gt;
	&lt;short-name&gt;custom&lt;/short-name&gt;
	&lt;uri&gt;http://www.ilog.com/jviews/tlds/css.tld&lt;/uri&gt;
	&lt;description&gt;This tag library contains a tag for a 
		sample custom JSF Component.&lt;/description&gt;
	&lt;tag&gt;
		&lt;name&gt;css&lt;/name&gt;
		&lt;tag-class&gt;path.to.CSSTag&lt;/tag-class&gt;
		&lt;description&gt;A component that displays the style 
			inline or a link a to a css file&lt;/description&gt;
		&lt;attribute&gt;
			&lt;name&gt;id&lt;/name&gt;
			&lt;required&gt;false&lt;/required&gt;
			&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
			&lt;type&gt;java.lang.String&lt;/type&gt;
			&lt;description&gt;The id of this component.
			&lt;/description&gt;
		&lt;/attribute&gt;
		&lt;attribute&gt;
			&lt;name&gt;binding&lt;/name&gt;
			&lt;required&gt;false&lt;/required&gt;
			&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
			&lt;type&gt;java.lang.String&lt;/type&gt;
			&lt;description&gt;The value binding expression 
				linking this component to a property in a
				backing bean. If this attribute is set, the 
				tag does not create the component itself but
				retrieves it from the bean property. This
				attribute must be a value binding.
			&lt;/description&gt;
		&lt;/attribute&gt;
		&lt;attribute&gt;
			&lt;name&gt;value&lt;/name&gt;
			&lt;required&gt;true&lt;/required&gt;
			&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
			&lt;type&gt;java.lang.String&lt;/type&gt;
			&lt;description&gt;The inline css text or the url to 
				the css file to link.&lt;/description&gt;
		&lt;/attribute&gt;
		&lt;attribute&gt;
			&lt;name&gt;link&lt;/name&gt;
			&lt;required&gt;false&lt;/required&gt;
			&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
			&lt;type&gt;java.lang.String&lt;/type&gt;
			&lt;description&gt;Whether the value is a link or 
				the inline style.&lt;/description&gt;
		&lt;/attribute&gt;
	&lt;/tag&gt;
&lt;/taglib&gt;
</PRE>
<P><STRONG>编写JSF</STRONG><STRONG>配置文件。</STRONG>为了将某个JSF组件集成到框架中，您必须提供一个名为faces-config.xml的配置文件。该文件将组件类型和呈现程序类型（用于JSP定制标签处理程序）与对应的Java类关联起来。它还能描述与每个组件一同使用的呈现程序（参见清单5）。该文件定义了faces.CSSFamily组件家族。在本例中，该家族由faces.CSSComponent这一个组件类型（该类型与CSSComponent类绑定）组成。最后，HTML.LinkOrInlineRenderer类型的呈现程序（由CSSComponent类实现）要与faces.CSSFamily家族相关联。</P><STRONG>清单5. </STRONG>该文件将组件类型和呈现程序类型与对应的Java类联系起来，并描述与每个组件一同使用的呈现程序。它还定义了faces.CSSFamily组件家族。 <PRE class=code>&lt;!DOCTYPE faces-config PUBLIC 
	"-//Sun Microsystems, Inc.//
	DTD JavaServer Faces Config 1.0//EN" 
	"http://java.sun.com/dtd/web-facesconfig_1_0.dtd"&gt;
&lt;faces-config&gt;
	&lt;component&gt;
		&lt;component-type&gt;faces.CSSComponent
		&lt;/component-type&gt;
		&lt;component-class&gt;path.to.CSSComponent
		&lt;/component-class&gt;
		&lt;component-extension&gt;
			&lt;component-family&gt;faces.CSSFamily
			&lt;/component-family&gt;
			&lt;renderer-type&gt;HTML.LinkOrInlineRenderer
			&lt;/renderer-type&gt;
		&lt;/component-extension&gt;
	&lt;/component&gt;
	&lt;render-kit&gt;
		&lt;renderer&gt;
			&lt;component-family&gt;faces.CSSFamily
			&lt;/component-family&gt;
			&lt;renderer-type&gt; HTML.LinkOrInlineRenderer 
			&lt;/renderer-type&gt;
			&lt;renderer-class&gt;path.to.CSSRenderer
			&lt;/renderer-class&gt;
		&lt;/renderer&gt;
	/render-kit&gt;
&lt;/faces-config&gt;
</PRE>
<P><STRONG>开始制图 </STRONG></P>
<P>　　如果您希望将自己的组件集成到JSF-enabled IDE中，您还可以提供补充说明。比如说，除提供其他的设计时信息外，还可以提供一个名为sun-faces-config.xml的XML配置文件，用于描述应在IDE中公开的组件属性。 </P>
<P>　　既然已经看到如何创建一个简单的JSF组件，不妨再来看看怎样创建一个图形JSF组件。我们将遵循同样的基本步骤来设计一个高级JSF图形组件。让我们以一个图形组件（如ILOG JSF图形组件）为例，通过一组分类，该组件为数据值分布提供了可视化表示。该图形能够以条型统计图、圆形分格统计图和气泡式统计图等各种显示方法来显示数据集合。该JSF图形组件有两个初始设计限制：</P>
<P>　　我们已经拥有Java图形bean组件，它具备所有图形显示能力。该组件可以显示很多图形，而且可定制性很高。在理想情况下，我们希望利用bean组件，使用它的功能来构成我们的JSF组件的基础。 </P>
<P>　　普通JSF应用程序需要重新载入整个页面以更新视图。这种方法适合基于表单的应用程序，但在很多情况下却不适用于高度图形化的用户界面。因此，我们的JSF图形组件必须能在不更新整个页面的前提下处理某些简单的导航，以提供更好的用户体验。 </P>
<P>　　以下是满足这些需求的解决方案：该JSF图形组件将管理图形bean组件，包括创建图形bean、定制该bean以及使该bean可用于服务器端操作。呈现JSF组件将分为两个阶段完成。JSF呈现程序会产生一个&lt;img&gt;标签和一套JavaScript对象（参见图2）。客户端将请求服务器发回一张图像。这一请求由某个servlet完成，该servlet获得图形bean，并利用图形提供的方法生成一幅图像（参见图3）。任何只改变该图形外观的进一步用户交互（放大、扫视、更改样式表等）都会引起图形的一次增量更新。如果客户端不只是要求对图形图像进行更新，那么将提交该页面（参见图4）。</P>
<P><IMG height=150 src="http://dev2dev.bea.com.cn/images/wlworkshop/images05070604_02.jpg" width=300> </P>
<P>　　图2JSF图形组件管理图形bean组件，包括创建图形bean、对其进行定制，并使其可用于服务器端动作。JSF呈现程序生成一个&lt;img&gt;标签和一套JavaScript对象。</P>
<P><IMG height=168 src="http://dev2dev.bea.com.cn/images/wlworkshop/images05070604_03.jpg" width=336> </P>
<P>　　图3 客户机通过servlet要求服务器获得一张图像。该servlet获得图形bean，并通过由图形提供的方法生成一幅图像。 </P>
<P><IMG height=150 src="http://dev2dev.bea.com.cn/images/wlworkshop/images05070604_04.jpg" width=300> </P>
<P>　　图4如果客户端不只是要求对图形外观的进行更新，那么页面将被提交。</P>
<P>　　JSF图形组件还配有一套附加的JSF组件。<EM>overview</EM>可显示该图形整体视图，显示一个代表图形视图的长方形，还应允许用户扫描可视区域。<EM>legend</EM>组件可显示数据集合的相关信息，还能自行在图形中显示，依被显示数据的样式而定。也能提供客户端的<EM>interactors</EM>如扫描和放大，这些功能可看成是客户端交互，表示与图形的交互不会像一次正常的JSF交互那样重新载入整个页面。</P>
<P>　　要想呈现图形组件，只需使用chartView标签： </P>
<P>&lt;jvcf:chartView id="c" style="width:500px;height:300px" … /&gt; </P>
<P>　　该数据在HTML页面中作为图像显示。该图像由servlet创建，旨在响应一次HTTP请求（该请求包括指定结果图像、生成图像映射以及生成内联式图例等各种参数）。结果图像随之被嵌入客户端DOM，页面中只有图像自身这一部分被更新。</P>
<P><STRONG>应用程序核心部件</STRONG></P>
<P>　　让我们看看简单的定制JSF组件和高级图形组件之间的一些区别。JSF图形组件类很像一个标准组件，不过是多了一个可访问图形bean（该图形bean负责生成在HTML页面中显示的图像）的图形属性。JSF组件可以通过某个绑定值或在当前会话中对这个图形bean进行局部检索。当JSF图形组件成为某个应用程序的核心部件时，可选的JSF组件（如概览或图例）便与主图形相关联，来显示附加信息（见清单6）。</P>
<P align=left><STRONG>清单</STRONG><STRONG>6. </STRONG>当JSF图形组件成为某个应用程序的核心部件时，可选的JSF组件便与主图形相关联，来显示附加信息。</P><PRE class=code>&lt;jvcf:chartZoomInteractor id="chartZoomInteractor" 
	XZoomAllowed="true" 
	YZoomAllowed="true" /&gt; 
&lt;jvcf:chartView id="chartView" 
						 chart="#{myBean.chart}" 
					 servlet="demo.ImageMapServlet" 
			interactorId="chartZoomInteractor" 
						 width="500" 
						height="300" 
			 styleSheets="/data/line.css" 
			waitingImage="data/images/wait.gif" 
			 imageFormat="PNG"  /&gt;
&lt;jvcf:chartOverview id="chartOverview" 
					style="height:100;width:150px" 
						viewId="chartView" 
						lineWidth="3" 
						lineColor="red" /&gt;

&lt;jvcf:chartLegend id="legendView" 
							viewId="chartView" 
							 width="400" 
							height="180" 
							layout="vertical" 
				waitingImage="data/images/wait.gif" /&gt;

</PRE>
<P>　　呈现程序是实现这个JSF的一大难点。如前所述，呈现程序并不生成简单的HTML，而是生成由HTML（&lt;IMG&gt; tag）和JavaScript proxy（代理程序）组成的动态HTML（DHTML）。</P>
<P>　　Proxy是一个负责管理客户机组件图像显示的JavaScript类实例。该对象是服务器端Java组件类在客户端显示；它与组件类具有相同属性。页面上的每个组件、图形及其配件都有一个proxy实例。呈现JavaScript时，在每个可视的JavaScript变量上使用facesContext.getExternalContext().encodeNamespace(name)方法是个很好的实践。这样做在今后方便地将组件集成到到JSR 168-compliant端口环境中。</P>
<P>　　为举例说明客户机上的proxy，必须在页面上导入JavaScript支持库。为保持客户端尽量瘦，需要基于JavaScript库支持的proxy类，对JavaScript库进行模块化。因此，需要给每个proxy类输入一套不同的、有可能重叠的库。图形呈现的困难部分，出现在发送这些script库的阶段。每个组件的呈现程序都要声明自己需要哪个库，以及什么时候发送引用的库，必须认清已发送的库，以避免重复。仅在页面呈现期间的存在script管理器负责这项筛选工作。每当呈现程序想要发送整套库输入时，它都会向筛选出已发送库的script管理器提供列表。</P>
<P>　　客户端proxy的目的在于允许编写脚本，并避免不必要的页面更新。一旦呈现了图形，在客户端便可使用proxy，以便动态安装interactor，并显示或隐藏图像映射。Proxy对象也可供支持JavaScript鼠标事件处理的常规JSF组件使用。 </P><PRE class=code>&lt;jvcf:chartView id=
	"chartView" .. /&gt;
&lt;h:selectBooleanCheckbox id=
	"genImageMap" onclick=
	"chartView.setGenerateImageMap(
	this.checked ? true : false, 
 true);" /&gt;
</PRE>
<P>　　对组件客户端proxy进行局部修改的问题在于，其状态不再与服务器上的Java组件的状态同步。为解决这个问题，proxy使用一个隐藏的输入标签（&lt;INPUT TYPE="HIDDEN"&gt;）来保存客户机上的新状态。当执行某个标准JSF动作并提交页面时，呈现程序将解析该隐藏状态，使客户机与服务器同步。这种行为需要呈现程序类中有专门的破解行为。标准破解方法得以改进，以便解析来自客户机的状态，并更新服务器端组件的状态。</P>
<P><STRONG>测试实例</STRONG></P>
<P>　　图形及其相关组件之间的关联由标记引用与绑定来完成。为使页面设计具有灵活性，一个组件可以在呈现之前被引用。因此，在呈现时间内，如果某个组件属性引用另一个尚未呈现的组件，那么，将延迟发送依赖于客户机进行解决的JavaScript代码，直到呈现已引用的组件。此工作可由依赖性管理器完成。</P>
<P>为证实这一点，不妨看一个典型实例，该实例涉及某个概览，该概览引用一张图形。</P><PRE class=code>&lt;jvcf:overview viewId=
	"chart" [...] /&gt; 
&lt;jvcf:chartView id=
	"chart" [....] /&gt;</PRE>
<P>　　存在两种情况。被引用图形组件已经呈现，因此不存在任何问题</P><PRE class=code>JSP:
&lt;jvcf:chartView id=
	"chart" [....] /&gt;
&lt;jvcf:overview viewId=
	"chart" id="overview" [...] /&gt; 

render:
[...]
var chart = 
	new IlvChartViewProxy ( .. );
[...]

var overview= 
	new IlvFacesOverviewProxy (
	 .. );
overview.setView(chart);
[...]
</PRE>
<P>　　已引用图形的组件在依赖的概览组件之前不会呈现。既然如此，可在依赖性管理器上注册一个组件创建监视器。已引用图形组件最终呈现时，其呈现程序会通知自己创建的依赖性管理器。此时，将发送解决依赖性所需的代码：</P><PRE class=code>JSP:
&lt;jvf:overview viewId=
	"chart" id="overview" [...] /&gt; 
&lt;jvdf:chartView id=
	"chart" [....] /&gt;

render:
[...]
var overview = 
	new IlvFacesOverviewProxy (
	 .. );
[...]

var chart = 
	new IlvChartViewProxy ( .. );
overview.setView(chart);
[...]
</PRE>
<P>　　开发JSF组件的目的之一，是能够将它们应用于任何与JSF兼容的IDE。尽管如此，JSF兼容性并不足以保证这种设计时集成将会有效。下面是在开发JSF组件过程中，为了便于在今后与IDE集成需要注意的一些简单思想：</P>
<P>　　首先，定制JSF组件应该提供一个基本HTML呈现程序。在设计时，JSF IDE不能呈现请求有效数据或app服务器连接的动态图形组件。因此，带有复杂的或非传统的（比如不是HTML）呈现程序的组件，应该使用Beans.isDesignTime()来确定是提供一个基本HTML表示法，还是提供真正的组件呈现程序。</P>
<P>　　另一个设计时问题是组件的位置和大小。不同IDE使用不同的标志和属性。能够调整大小的组件（如一幅图像）应能处理定义大小的不同方式。</P>
<P>　　最后，为了与IDE集成，组件必须提供尚未被JSF说明定义的补充信息。遗憾的是，当前每个IDE都需要特殊处理程序来集成组件，即：在一种情况就需要XML文件，而在另一种情况下需要eclipse插件，如此等等。下一个JSF JSR（2.0版）的主要目的之一，将是指定附加的元数据格式。</P>
<P>　　如您所见，编写一个简单的JSF组件并不难，因为框架已经完成了大部分工作。JSF框架管理着组件状态、呈现程序等等。在本文中，我们已经扩展了这些基本概念，来设计一个能够显示复杂元数据、提供增量更新、支持大量客户端交互并与配套组件协作的高级图形JSF组件。支持这些特点需要对基本JSF组件的结构进行许多改进。当然，增量更新的概念今后对JSF框架将是一个很好的完善，因为它只允许呈现页面已改变的部分，避免了更新整个页面。按照JSF说明书工作往往不足以确保组件完全集成到JSF IDE中；一个新JSR应能及时解决这些难题。尽管存在缺陷，JSF框架仍能极大地加快Web组件开发速度、方便的融合来自各种资源的组件，以创建完整的、复杂的Web应用程序。</P>
<P><STRONG>参考资料</STRONG></P>
<UL>
<LI>developer.sun.com<BR>Java 工具<BR><A href="http://developers.sun.com/prodtech/javatools/jscreator/index.jsp" target=_blank>Sun Java Studio Creator</A><BR><A href="http://java.sun.com/developer/technicalArticles/GUI/JavaServerFaces" target=_blank>Developing Web Applications with JavaServer Faces</A> 
<LI>IBM <BR>Rational 软件<BR><A href="http://www-306.ibm.com/software/awdtools/developer/application/index.html" target=_blank>Rational Application Developer for WebSphere Software</A> 
<LI>Java Community Process <BR>Java Specification Requests <A href="http://jcp.org/en/jsr/detail?id=127" target=_blank>JSR 127: JavaServer Faces</A><BR><A href="http://jcp.org/en/jsr/detail?id=168" target=_blank>JSR 168: Portlet Specification</A> </LI></UL>
<P><STRONG>作者简介</STRONG></P>
<P>　　Marc Durocher是ILOG的一名软件架构师，ILOG是企业级软件组件和服务的主要提供商。Marc Durocher在ILOG负责开发ILOG JViews生产线上的JSF组件。可以通过<A href="mailto:mdurocher@ilog.fr">mdurocher@ilog.fr</A>联系Marc。</P>
<P><STRONG>原文出处</STRONG></P>
<P><A href="http://www.ftponline.com/weblogicpro/2005_03/magazine/features/mdurocher/" target=_blank>http://www.ftponline.com/weblogicpro/2005_03/magazine/features/mdurocher/</A></P><!--文章其他信息--><img src ="http://www.blogjava.net/gf7/aggbug/13860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-09-23 20:56 <a href="http://www.blogjava.net/gf7/archive/2005/09/23/13860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>