﻿<?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-钢铁是璐璐炼成的-随笔分类-Structs</title><link>http://www.blogjava.net/lulu/category/9764.html</link><description>快乐的学习，快乐的生活</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 03:05:00 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 03:05:00 GMT</pubDate><ttl>60</ttl><item><title>JSF与Struts的异同-参考</title><link>http://www.blogjava.net/lulu/archive/2006/04/12/40734.html</link><dc:creator>lulu</dc:creator><author>lulu</author><pubDate>Wed, 12 Apr 2006 13:35:00 GMT</pubDate><guid>http://www.blogjava.net/lulu/archive/2006/04/12/40734.html</guid><wfw:comment>http://www.blogjava.net/lulu/comments/40734.html</wfw:comment><comments>http://www.blogjava.net/lulu/archive/2006/04/12/40734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lulu/comments/commentRss/40734.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lulu/services/trackbacks/40734.html</trackback:ping><description><![CDATA[
		<h3 align="center">JSF与Struts的异同(转）</h3>
		<p align="left">－题记：与友人聊天提及JSF的概念，转载一篇文章供日后参考</p>
		<p>　　Struts和JSF/Tapestry都属于表现层框架，这两种分属不同性质的框架，后者是一种事件驱动型的组件模型，而Struts只是单纯的MVC模式框架，老外总是急吼吼说事件驱动型就比MVC模式框架好，何以见得，我们下面进行详细分析比较一下到底是怎么回事？</p>
		<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> </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模式，赶紧补课。</p>
<img src ="http://www.blogjava.net/lulu/aggbug/40734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lulu/" target="_blank">lulu</a> 2006-04-12 21:35 <a href="http://www.blogjava.net/lulu/archive/2006/04/12/40734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>