﻿<?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-JAVA牛棚-文章分类-struts</title><link>http://www.blogjava.net/chinajox/category/4111.html</link><description>我们爱JAVA</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 14:13:30 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 14:13:30 GMT</pubDate><ttl>60</ttl><item><title>[Struts]处理表单中值为空的日期类型字段 转自《博客园》八进制  </title><link>http://www.blogjava.net/chinajox/articles/16885.html</link><dc:creator>JAVA牛棚</dc:creator><author>JAVA牛棚</author><pubDate>Wed, 26 Oct 2005 08:01:00 GMT</pubDate><guid>http://www.blogjava.net/chinajox/articles/16885.html</guid><wfw:comment>http://www.blogjava.net/chinajox/comments/16885.html</wfw:comment><comments>http://www.blogjava.net/chinajox/articles/16885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chinajox/comments/commentRss/16885.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chinajox/services/trackbacks/16885.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width=447 border=0>
<TBODY>
<TR>
<TD colSpan=2 height=29><FONT size=2><STRONG>作者：</STRONG></FONT><FONT size=3>tendre<BR></FONT></TD></TR>
<TR>
<TD style="WORD-BREAK: break-all" colSpan=2><FONT size=2>在示范中心项目中，我们把ActionForm中日期类型的字段指定为String类型，而在对应的JavaBean中指定为java.sql.Date类型。当用户提交表单的时候，在Action里使用BeanUtils.copyProperties()方法从ActionForm构造JavaBean对象（详见利用BeanUtils在对象间复制属性）。这个方法在大部分时候都很好，但有一个问题，就是当用户没有填写日期类型字段时（而该字段并非必填），validator不会提出警告，而在copyProperties()时会报类型转换异常，原因是这时ActionForm中的该字段的值是空字符串（""），负责字符串向Date转换的SqlDateConverter类调用Date.valueOf("")方法，显然""是无法转换为日期的，所以会抛出异常。<BR><BR>通过查看代码和资料，我发现这个问题的解决方法其实非常简单。只要把带缺省值参数的SqlDateConverter重新注册一下，覆盖原有的注册信息就可以了，这个注册语句一般是写在系统初试化的地方，对于Struts应用程序，当然做在PlugIn里最方便。代码如下：<BR><BR><BR>package&nbsp;etc;<BR><BR>import&nbsp;javax.servlet.ServletException;<BR>import&nbsp;org.apache.commons.beanutils.ConvertUtils;<BR>import&nbsp;org.apache.commons.beanutils.converters.SqlDateConverter;<BR>import&nbsp;org.apache.struts.action.ActionServlet;<BR>import&nbsp;org.apache.struts.action.PlugIn;<BR>import&nbsp;org.apache.struts.config.ModuleConfig;<BR><BR>public&nbsp;class&nbsp;ConverterPlugIn&nbsp;implements&nbsp;PlugIn{<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init(ActionServlet&nbsp;servlet,&nbsp;ModuleConfig&nbsp;config)&nbsp;throws&nbsp;ServletException&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConvertUtils.register(new&nbsp;SqlDateConverter(null),java.sql.Date.class);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;destroy()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConvertUtils.deregister();<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>注意SqlDateConverter的构造方法是带有参数null的，这表示遇到不能解析的字符串就返回空值。而deregister()方法的作用是恢复ConvertUtils的缺省注册表。为了使这个PlugIn起作用，要在struts-config.xml里增加一句话：<BR><BR>&lt;plug-in&nbsp;className="etc.ConverterPlugIn"&nbsp;/&gt;<BR>日期字段往往会给我们的开发带来麻烦，其实在Struts应用程序里，只要把这些转换类搞熟了，总可以找到很方便的办法。常见的问题还有如何指定日期输入格式，怎样处理java.util.Date的转换，等等，在这个链接里有解决这些问题的方法，道理都是一样的。</FONT></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/chinajox/aggbug/16885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chinajox/" target="_blank">JAVA牛棚</a> 2005-10-26 16:01 <a href="http://www.blogjava.net/chinajox/articles/16885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java框架研究——JSF与Struts的异同 [转自赛迪网]  </title><link>http://www.blogjava.net/chinajox/articles/16884.html</link><dc:creator>JAVA牛棚</dc:creator><author>JAVA牛棚</author><pubDate>Wed, 26 Oct 2005 07:58:00 GMT</pubDate><guid>http://www.blogjava.net/chinajox/articles/16884.html</guid><wfw:comment>http://www.blogjava.net/chinajox/comments/16884.html</wfw:comment><comments>http://www.blogjava.net/chinajox/articles/16884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chinajox/comments/commentRss/16884.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chinajox/services/trackbacks/16884.html</trackback:ping><description><![CDATA[<P><FONT size=2>作者：RKIND</FONT></P>
<P><FONT size=2>Struts和JSF/Tapestry都属于表现层框架，这两种分属不同性质的框架，后者是一种事件驱动型的组件模型，而Struts只是单纯的MVC模式框架，老外总是急吼吼说事件驱动型就比MVC模式框架好，何以见得，我们下面进行详细分析比较一下到底是怎么回事？</FONT></P>
<P><FONT size=2>首先事件是指从客户端页面（浏览器）由用户操作触发的事件，Struts使用Action来接受浏览器表单提交的事件，这里使用了Command模式，每个继承Action的子类都必须实现一个方法execute。</FONT></P>
<P><FONT size=2>在Struts中，实际是一个表单Form对应一个Action类(或DispatchAction)，换一句话说：在Struts中实际是一个表单只能对应一个事件，Struts这种事件方式称为application event，application event和Component event相比是一种粗粒度的事件。</FONT></P>
<P><FONT size=2>Struts重要的表单对象ActionForm是一种对象，它代表了一种应用，这个对象中至少包含几个字段，这些字段是Jsp页面表单中的input字段，因为一个表单对应一个事件，所以，当我们需要将事件粒度细化到表单中这些字段时，也就是说，一个字段对应一个事件时，单纯使用Struts就不太可能，当然通过结合JavaScript也是可以转弯实现的。</FONT></P>
<P><FONT size=2>而这种情况使用JSF就可以方便实现 <BR>&nbsp;</FONT></P>
<P><FONT size=2>&lt;h:inputText id="userId" value="#{login.userId}"&gt;<BR>&lt;f:valueChangeListener type="logindemo.UserLoginChanged" /&gt;<BR>&lt;/h:inputText&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>#{login.userId}表示从名为login的JavaBean的getUserId获得的结果，这个功能使用struts也可以实现，name="login" property="userId" </FONT></P>
<P><FONT size=2>关键是第二行，这里表示如果userId的值改变并且确定提交后，将触发调用类UserLoginChanged的processValueChanged(...)方法。 </FONT></P>
<P><FONT size=2>JSF可以为组件提供两种事件：Value Changed和 Action. 前者我们已经在上节见识过用处，后者就相当于struts中表单提交Action机制，它的JSF写法如下： </FONT></P>
<P><BR><FONT size=2>&lt;h:commandButton id="login" commandName="login"&gt;<BR>&lt;f:actionListener type=”logindemo.LoginActionListener” /&gt;<BR>&lt;/h:commandButton&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2>从代码可以看出，这两种事件是通过Listerner这样观察者模式贴在具体组件字段上的，而Struts此类事件是原始的一种表单提交Submit触发机制。如果说前者比较语言化（编程语言习惯做法类似Swing编程）；后者是属于WEB化，因为它是来自Html表单，如果你起步是从Perl/PHP开始，反而容易接受Struts这种风格。</FONT></P>
<P><FONT size=2>基本配置</FONT></P>
<P><FONT size=2>Struts和JSF都是一种框架，JSF必须需要两种包JSF核心包、JSTL包（标签库），此外，JSF还将使用到Apache项目的一些commons包，这些Apache包只要部署在你的服务器中既可。</FONT></P>
<P><FONT size=2>JSF包下载地址：</FONT><A href="http://java.sun.com/j2ee/javaserverfaces/download.html"><FONT size=2>http://java.sun.com/j2ee/javaserverfaces/download.html</FONT></A><FONT size=2>选择其中Reference Implementation。</FONT></P>
<P><FONT size=2>JSTL包下载在</FONT><A href="http://jakarta.apache.org/site/downloads"><FONT size=2>http://jakarta.apache.org/site/downloads</FONT></A><FONT size=2> /downloads_taglibs-standard.cgi</FONT></P>
<P><FONT size=2>所以，从JSF的驱动包组成看，其开源基因也占据很大的比重，JSF是一个SUN伙伴们工业标准和开源之间的一个混血儿。 <BR>&nbsp;</FONT></P>
<P><FONT size=2>上述两个地址下载的jar合并在一起就是JSF所需要的全部驱动包了。与Struts的驱动包一样，这些驱动包必须位于Web项目的WEB-INF/lib，和Struts一样的是也必须在web.xml中有如下配置：</FONT></P>
<P><BR><FONT size=2>&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; <BR>　　&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>&nbsp;&nbsp;&nbsp; &lt;/web-app&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>这里和Struts的web.xml配置何其相似，简直一模一样。 </FONT></P>
<P><FONT size=2>正如Struts的struts-config.xml一样，JSF也有类似的faces-config.xml配置文件： </FONT></P>
<P><BR><FONT size=2>&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>　&nbsp; &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; <BR>　　&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>&nbsp;&nbsp;&nbsp; &lt;/faces-config&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2>在Struts-config.xml中有ActionForm Action以及Jsp之间的流程关系，在faces-config.xml中，也有这样的流程，我们具体解释一下Navigation：</FONT></P>
<P><FONT size=2>在index.jsp中有一个事件：</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>&lt;h:commandButton label="Login" action="login" /&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>Action的值必须匹配form-outcome值，上述Navigation配置表示：如果在index.jsp中有一个login事件，那么事件触发后下一个页面将是welcome.jsp </FONT></P>
<P><FONT size=2>JSF有一个独立的事件发生和页面导航的流程安排，这个思路比struts要非常清晰。 </FONT></P>
<P><FONT size=2>managed-bean类似Struts的ActionForm，正如可以在struts-config.xml中定义ActionForm的scope一样，这里也定义了managed-bean的scope为session。 </FONT></P>
<P><FONT size=2>但是如果你只以为JSF的managed-bean就这点功能就错了，JSF融入了新的Ioc模式/依赖性注射等技术。 <BR>&nbsp;<BR>&nbsp;</FONT></P>
<P><FONT size=2>对于Userbean这样一个managed-bean，其代码如下： </FONT></P>
<P><BR><FONT size=2>public class UserBean {<BR>　　private String name;<BR>　　private String password;</FONT></P>
<P><FONT size=2>　　// PROPERTY: name<BR>　　public String getName() { return name; }<BR>　　public void setName(String newValue) { name = newValue; }</FONT></P>
<P><FONT size=2>　　// PROPERTY: password<BR>　　public String getPassword() { return password; }<BR>　　public void setPassword(String newValue) { password = newValue; }<BR>&nbsp;&nbsp;&nbsp; }</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp; &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;</FONT></P>
<P><FONT size=2>　　&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;</FONT></P>
<P><FONT size=2>　　&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>&nbsp;&nbsp;&nbsp; &lt;/managed-bean&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2>faces-config.xml这段配置其实是将"me"赋值给name，将secret赋值给password，这是采取Ioc模式中的Setter注射方式。</FONT></P>
<P><FONT size=2>Backing Beans</FONT></P>
<P><FONT size=2>对于一个web form，我们可以使用一个bean包含其涉及的所有组件，这个bean就称为Backing Bean， Backing Bean的优点是：一个单个类可以封装相关一系列功能的数据和逻辑。</FONT></P>
<P><FONT size=2>说白了，就是一个Javabean里包含其他Javabean，互相调用，属于Facade模式或Adapter模式。</FONT></P>
<P><FONT size=2>对于一个Backing Beans来说，其中包含了几个managed-bean，managed-bean一定是有scope的，那么这其中的几个managed-beans如何配置它们的scope呢？</FONT></P>
<P><BR><FONT size=2>&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>&nbsp;</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>这里配置了一个Backing Beans中有一个setVisit方法，将这个visit赋值为session中的visit，这样以后在程序中我们只管访问visit对象，从中获取我们希望的数据（如用户登陆注册信息），而visit是保存在session还是application或request只需要配置既可。 </FONT></P>
<P><FONT size=2>UI界面 </FONT></P>
<P><FONT size=2>JSF和Struts一样，除了JavaBeans类之外，还有页面表现元素，都是是使用标签完成的，Struts也提供了struts-faces.tld标签库向JSF过渡。 </FONT></P>
<P><FONT size=2>使用Struts标签库编程复杂页面时，一个最大问题是会大量使用logic标签，这个logic如同if语句，一旦写起来，搞的JSP页面象俄罗斯方块一样，但是使用JSF标签就简洁优美： </FONT></P>
<P><BR><FONT size=2>&lt;jia:navigatorItem name="inbox" label="InBox"<BR>　　icon="/images/inbox.gif"<BR>　　action="inbox"<BR>　　disabled="#{!authenticationBean.inboxAuthorized}"/&gt;<BR>&nbsp;</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P>
<P><FONT size=2>如果authenticationBean中inboxAuthorized返回是假，那么这一行标签就不用显示，多干净利索！ </FONT></P>
<P><FONT size=2>先写到这里，我会继续对JSF深入比较下去，如果研究过Jdon框架的人，可能会发现，Jdon框架的jdonframework.xml中service配置和managed-bean一样都使用了依赖注射，看来对Javabean的依赖注射已经迅速地成为一种新技术象征，如果你还不了解Ioc模式，赶紧补课。 <BR>&nbsp;<BR></FONT></P><img src ="http://www.blogjava.net/chinajox/aggbug/16884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chinajox/" target="_blank">JAVA牛棚</a> 2005-10-26 15:58 <a href="http://www.blogjava.net/chinajox/articles/16884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>