﻿<?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-VIRGIN FOREST OF JAVA-文章分类-STRUTS</title><link>http://www.blogjava.net/RR00/category/2502.html</link><description>不要埋头苦干，要学习，学习，再学习。。。。。
&lt;br&gt;
powered  by &lt;font color='orange'&gt;R.Zeus&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 22:36:37 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 22:36:37 GMT</pubDate><ttl>60</ttl><item><title>tiles</title><link>http://www.blogjava.net/RR00/articles/62793.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Thu, 10 Aug 2006 06:51:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/62793.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/62793.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/62793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/62793.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/62793.html</trackback:ping><description><![CDATA[&lt;%@ include file=".......Taglibs.jsp" %&gt;<br />虽然定义的body里有了tag，但是各自的页面还要加，因为这是动态编译以后加载,所以每个页面都应该有！<img src ="http://www.blogjava.net/RR00/aggbug/62793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2006-08-10 14:51 <a href="http://www.blogjava.net/RR00/articles/62793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActionMessages</title><link>http://www.blogjava.net/RR00/articles/62543.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Wed, 09 Aug 2006 04:36:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/62543.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/62543.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/62543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/62543.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/62543.html</trackback:ping><description><![CDATA[ ActionMessages msgs = new ActionMessages();<br />        msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(strMsg, <font color="#ff1493">args</font>));<br />                                                                                                 //关于args，如果ApplicationMessages.properties                                                                                               中有，就取对应的值；如果没有，就用这个args值<br /><img src ="http://www.blogjava.net/RR00/aggbug/62543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2006-08-09 12:36 <a href="http://www.blogjava.net/RR00/articles/62543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts 2个配置文件</title><link>http://www.blogjava.net/RR00/articles/62414.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Tue, 08 Aug 2006 11:35:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/62414.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/62414.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/62414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/62414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/62414.html</trackback:ping><description><![CDATA[
		<p>&lt;init-param&gt;<br />            &lt;param-name&gt;config&lt;/param-name&gt;<br />            &lt;param-value&gt;/WEB-INF/config/struts/struts-config.xml&lt;/param-value&gt;<br />        &lt;/init-param&gt;</p>
		<p>        &lt;init-param&gt;<br />                                  //这里表示所有以account开头的*.do都使用下面的配置文件，而在配置文件的<br />                                       Actionmapping不用加上account。<br />                                    <br />            &lt;param-name&gt;<font style="BACKGROUND-COLOR: #ffffff" color="#ff1493">config/account</font>&lt;/param-name&gt;<br />            &lt;param-value&gt;/WEB-INF/config/struts/struts-config-account.xml&lt;/param-value&gt;<br />        &lt;/init-param&gt;<br /><br /><font style="BACKGROUND-COLOR: #ffc0cb">&lt;action-mappings&gt;<br />        &lt;action path="/searchAccount" type="com.suzsoft.demo.account.web.AccountAction"<br />                name="AccountForm" scope="request"&gt;<br />            &lt;forward name="success" path="/../WEB-INF/jsp/account/searchList.jsp"/&gt;<br />            &lt;forward name="failure" path="/../WEB-INF/jsp/loginSuccess.jsp"/&gt;<br />        &lt;/action&gt; </font><font style="BACKGROUND-COLOR: #ffffff">                                  //注意..,表示上一层目录，因为已经在account下，所以要回去<br />                                                              用tiles就不需要了！</font></p>
		<p>
				<br />
				<font style="BACKGROUND-COLOR: #ffc0cb">    &lt;/action-mappings&gt;</font>
		</p>
<img src ="http://www.blogjava.net/RR00/aggbug/62414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2006-08-08 19:35 <a href="http://www.blogjava.net/RR00/articles/62414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>三级级联下拉菜单实现</title><link>http://www.blogjava.net/RR00/articles/14936.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 07 Oct 2005 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/14936.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/14936.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/14936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/14936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/14936.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD class=title1 align=middle width="100%" bgColor=#eeeeee colSpan=3 height=40><B>三级级联下拉菜单实现</B></TD></TR>
<TR>
<TD align=middle width="100%" bgColor=#eeeeee><A href="http://www.javaresearch.org/profile.jsp?user=17168">zhangv</A> 原创&nbsp; (参与分：15623，专家分：1020)&nbsp;&nbsp; 发表：2005-05-28 13:31 &nbsp;&nbsp;版本：1.0 &nbsp;&nbsp;阅读：<B>1490</B>次 </TD></TR></TBODY></TABLE></TD></TR><!-- end of article title -->
<TR>
<TD vAlign=top align=middle width="100%"><!--start of article content -->
<TABLE width="98%" border=0>
<TBODY>
<TR>
<TD class=text align=left width="100%"><BR>三级级联下拉菜单实现(xml+js+struts)<BR>derekzhangv.at.hotmail.com<BR><BR>好不容易实现的一个三级级联菜单,喜欢把复杂的问题简单化,所以从网上的一些方法中提取出一种相对清爽的方法&nbsp;-&nbsp;<BR><BR>jsp页面里只多了2行代码.(不过多了两个文件)<BR><BR>项目是用struts,所以jsp为例(其实这个实现应该在任何情况下都是可以用的,无论asp,php...)生成:"1个form里含2组3级级<BR><BR>联菜单"&nbsp;<BR>从某省某市某县<BR>到某省某市某县<BR><BR>步骤:<BR>1.xml数据源,也就是保存省市地名层次信息.<BR>如果没有这个文件可能需要自己做一个,从数据库或者文本里提取一个xml文件出来应该不算难事吧.<BR>再说这样的文件保存在xml文件里迟早会有用处的.<BR>本例为:<BR>(city.xml)<BR>==========================<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="gb2312"?&gt;<BR>&lt;provinces&gt;<BR>&nbsp;&nbsp;&lt;province&nbsp;name="吉林"&nbsp;shortname="吉"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;city&nbsp;name="长春"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name=""&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="双阳"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="农安"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/city&gt;<BR>&nbsp;&nbsp;&lt;/province&gt;<BR>&nbsp;&nbsp;&lt;province&nbsp;name="北京"&nbsp;shortname="京"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;city&nbsp;name=""&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name=""&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="北京"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="东城"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="西城"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/city&gt;<BR>&nbsp;&nbsp;&lt;/province&gt;<BR>&nbsp;&nbsp;&lt;province&nbsp;name="山西"&nbsp;shortname="晋"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;city&nbsp;name="太原"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name=""&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="古交"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="阳曲"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="清徐"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="娄烦"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/city&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;city&nbsp;name="大同"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name=""&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="天镇"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;county&nbsp;name="灵丘"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/city&gt;<BR>&nbsp;&nbsp;&lt;/province&gt;<BR>&lt;/provinces&gt;<BR>==========================<BR><BR>2.javascript(小弟的js学的不好,还请各位写个更好更简洁的方法)<BR>(selectCity.js)<BR>==========================<BR>var&nbsp;from=["province","city","county"];<BR>var&nbsp;to=["toprovince","tocity","tocounty"];<BR>function&nbsp;selectFrom(num){<BR>if(num==3)&nbsp;return;<BR>var&nbsp;i,j,arrTemp=[];<BR>&nbsp;for(i=0;i&lt;num;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arrTemp[i]=document.all(from[i]).options[document.all(from[i]).selectedIndex].text<BR>&nbsp;with(document.all(from[num])){<BR>&nbsp;&nbsp;length=0<BR>&nbsp;&nbsp;var&nbsp;obj=document.all.xmlData.XMLDocument.childNodes[1];<BR>&nbsp;&nbsp;for(i=0;i&lt;num;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj=obj.selectSingleNode(from[i]+'[@name="'+arrTemp[i]+'"]');<BR>&nbsp;&nbsp;for(i=0;i&lt;obj.childNodes.length;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options[length++].text=obj.childNodes[i].getAttribute("name");<BR>&nbsp;&nbsp;onchange=new&nbsp;Function("selectFrom("+(num+1)+")");<BR>&nbsp;&nbsp;onchange();<BR>&nbsp;}<BR>}<BR>function&nbsp;selectTo(num){<BR>if(num==3)&nbsp;return;<BR>var&nbsp;i,j,arrTemp=[];<BR>&nbsp;for(i=0;i&lt;num;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arrTemp[i]=document.all(to[i]).options[document.all(to[i]).selectedIndex].text<BR>&nbsp;with(document.all(to[num])){<BR>&nbsp;&nbsp;length=0<BR>&nbsp;&nbsp;var&nbsp;obj=document.all.xmlData.XMLDocument.childNodes[1];<BR>&nbsp;&nbsp;for(i=0;i&lt;num;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj=obj.selectSingleNode(from[i]+'[@name="'+arrTemp[i]+'"]');<BR>&nbsp;&nbsp;for(i=0;i&lt;obj.childNodes.length;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options[length++].text=obj.childNodes[i].getAttribute("name");<BR>&nbsp;&nbsp;onchange=new&nbsp;Function("selectTo("+(num+1)+")");<BR>&nbsp;&nbsp;onchange();<BR>&nbsp;}<BR>}<BR>==========================<BR><BR>3.页面文件:(这里是struts,--这个应该没有关系)<BR>(test.jsp)<BR><BR>==========================<BR>&nbsp;&nbsp;&lt;script&nbsp;src="selectCity.js"&gt;&lt;/script&gt;<BR>&nbsp;&nbsp;&lt;xml&nbsp;id=xmlData&nbsp;src="city.xml"&nbsp;/&gt;<BR>&lt;body&nbsp;onload="selectFrom(0);selectTo(0);"&gt;<BR>&lt;html:form&gt;<BR>从&lt;html:select&nbsp;property="province"&nbsp;&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="province"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;html:select&nbsp;property="city"&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="city"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;html:select&nbsp;property="county"&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="county"/&gt;&lt;br/&gt;<BR>到&nbsp;&lt;html:select&nbsp;property="toprovince"&nbsp;&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="toprovince"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;html:select&nbsp;property="tocity"&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="tocity"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;html:select&nbsp;property="tocounty"&gt;&lt;/html:select&gt;&lt;html:errors&nbsp;property="tocounty"/&gt;<BR>&lt;/html:form&gt;<BR>&lt;/body&gt;<BR>==========================<BR><BR>这样的三步就构造了一个"1个form里含2组3级级联菜单",其实还是满麻烦的.之前还见过一种是在js里建一个三维数组,<BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/14936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-10-07 16:35 <a href="http://www.blogjava.net/RR00/articles/14936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用struts,ibaits和JSTL开发简便通用的文件上传系统</title><link>http://www.blogjava.net/RR00/articles/13963.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Sat, 24 Sep 2005 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/13963.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/13963.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/13963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/13963.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/13963.html</trackback:ping><description><![CDATA[<P><BR>文件上传也是一个老生常谈的问题了。struts提供了很方便的文件上传组件，利用struts，很容易开发文件上传的系统。本文结合ibatis和JSTL开发一个简便而通用的文件上传系统。通过本文，你可以学到如何在struts里配置文件上传功能、struts1.1的动态form配置和使用、如果简单的使用ibatis，如果简单使用的JSTL。<BR><BR>首先我们要在struts-config里加上一句，来指定临时目录以及限制大小。<BR><BR>&lt;controller&nbsp;maxFileSize="2M"&nbsp;tempDir="d:/temp"/&gt;&nbsp;<BR><BR>然后只要在form中加上enctype="multipart/form-data"&nbsp;就可以实现struts的上传了，十分简单吧？<BR><BR>下面我们在数据库中建立一张表。<BR><BR>create&nbsp;sequence&nbsp;Attachment_seq;<BR>DROP&nbsp;TABLE&nbsp;ATTACHMENT;<BR>create&nbsp;table&nbsp;Attachment<BR>(<BR>AttachID&nbsp;INT&nbsp;not&nbsp;null,&nbsp;--自动增长号&nbsp;AttachFilename&nbsp;VARCHAR2(250)&nbsp;null,&nbsp;--文件名&nbsp;AttachFileSize&nbsp;INT&nbsp;not&nbsp;null,&nbsp;--文件大小&nbsp;AttachMimeType&nbsp;VARCHAR2(70)&nbsp;null,&nbsp;--文件类型&nbsp;AttachDesc&nbsp;VARCHAR2(250)&nbsp;null,&nbsp;--说明&nbsp;AttachCreationIP&nbsp;VARCHAR2(20)&nbsp;not&nbsp;null,&nbsp;--上传的IP&nbsp;AttachCreationDate&nbsp;TIMESTAMP&nbsp;not&nbsp;null,&nbsp;--创建时间&nbsp;AttachModifiedDate&nbsp;TIMESTAMP&nbsp;not&nbsp;null,&nbsp;--文件保存路径&nbsp;ATTACHFILEPATH&nbsp;VARCHAR2&nbsp;(250)&nbsp;NOT&nbsp;NULL,<BR>primary&nbsp;key&nbsp;(AttachID)<BR>);<BR>create&nbsp;or&nbsp;replace&nbsp;trigger&nbsp;Attach_trig_autoinc<BR>before&nbsp;insert&nbsp;on&nbsp;Attachment<BR>for&nbsp;each&nbsp;row<BR>begin<BR>if&nbsp;(:new.AttachID&nbsp;is&nbsp;null)&nbsp;then&nbsp;<BR>select&nbsp;Attachment_seq.nextval&nbsp;into&nbsp;:new.AttachID&nbsp;from&nbsp;dual;<BR>end&nbsp;if;<BR>end;<BR><BR><BR>字段的内容都很简单。<BR><BR>下面建立ibatis的SQL&nbsp;map文件。建立标准的insert、update、delete和find的SQL。相信看过前面系列文章的朋友对此已经很熟悉了。<BR><BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;&lt;!DOCTYPE&nbsp;sql-mapPUBLIC&nbsp;"-//iBATIS.com//DTD&nbsp;SQL&nbsp;Map&nbsp;1.0//EN""http://www.ibatis.com/dtd/sql-map.dtd";&gt;&lt;sql-map&nbsp;name="attachment"&gt;&lt;!--&nbsp;=============================================&nbsp;mapped-statement&nbsp;insert&nbsp;=============================================&nbsp;--&gt;&lt;dynamic-mapped-statement&nbsp;name="insertattachmentDao"&nbsp;&gt;&nbsp;insert&nbsp;into&nbsp;ATTACHMENT&nbsp;(&nbsp;&lt;dynamic&nbsp;prepend=""&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHID"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHID"&nbsp;&gt;&nbsp;ATTACHID&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILENAME"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILENAME"&nbsp;&gt;&nbsp;ATTACHFILENAME&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;&nbsp;ATTACHFILEPATH&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;&nbsp;ATTACHFILESIZE&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;&nbsp;ATTACHMIMETYPE&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHDESC"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHDESC"&nbsp;&gt;&nbsp;ATTACHDESC&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;&nbsp;ATTACHCREATIONIP&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;&nbsp;ATTACHCREATIONDATE&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;&nbsp;&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;&nbsp;ATTACHMODIFIEDDATE&nbsp;&lt;/isNotNull&gt;&nbsp;&lt;/isPropertyAvailable&gt;&nbsp;&lt;/dynamic&gt;&nbsp;)&nbsp;valueS&nbsp;(<BR>&lt;dynamic&nbsp;prepend=""&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHID"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHID"&nbsp;&gt;<BR>#ATTACHID#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>#ATTACHFILENAME#<BR>&lt;/isNotNull&gt;&nbsp;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>#ATTACHFILEPATH#<BR>&lt;/isNotNull&gt;&nbsp;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>#ATTACHFILESIZE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>#ATTACHMIMETYPE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>#ATTACHDESC#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>#ATTACHCREATIONIP#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>#ATTACHCREATIONDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>#ATTACHMODIFIEDDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;)<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;update&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;dynamic-mapped-statement&nbsp;name="updateattachmentDao"&nbsp;&gt;<BR>update&nbsp;ATTACHMENT<BR>&lt;dynamic&nbsp;prepend="set"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#ATTACHFILEPATH:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;dynamic&nbsp;prepend="where"&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#ATTACHFILEPATH:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;updateByPrimaryKey&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;dynamic-mapped-statement&nbsp;name="updateByPrimaryKeyattachmentDao"&nbsp;&gt;<BR>update&nbsp;ATTACHMENT<BR>&lt;dynamic&nbsp;prepend="set"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#ATTACHFILEPATH:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP:VARCHAR#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend=","&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR><BR>&lt;dynamic&nbsp;prepend="where"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;delete&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;dynamic-mapped-statement&nbsp;name="deleteattachmentDao"&nbsp;result-class="java.util.HashMap"&gt;<BR>delete&nbsp;from&nbsp;ATTACHMENT<BR>&lt;dynamic&nbsp;prepend="where"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHID"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="&nbsp;ATTACHFILEPATH"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="&nbsp;ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#&nbsp;ATTACHFILEPATH#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;deleteByPrimaryKey&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;mapped-statement&nbsp;name="deleteByPrimaryKeyattachmentDao"&nbsp;&gt;<BR>delete&nbsp;from&nbsp;ATTACHMENT<BR>where<BR>ATTACHID=#ATTACHID#<BR><BR>&lt;/mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;find&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;dynamic-mapped-statement&nbsp;name="findattachmentDao"&nbsp;result-class="java.util.HashMap"&gt;<BR>select&nbsp;*&nbsp;from&nbsp;ATTACHMENT<BR>&lt;dynamic&nbsp;prepend="where"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHID"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#ATTACHFILEPATH#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;dynamic&nbsp;prepend="order&nbsp;by&nbsp;"&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="sortOrder"&nbsp;&gt;<BR>$sortOrder$<BR>&lt;/isNotNull&gt;<BR>&lt;isNull&nbsp;prepend=""&nbsp;property="sortOrder"&nbsp;&gt;<BR>&lt;/isNull&gt;<BR>&lt;/dynamic&gt;<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;findByPrimaryKey&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;mapped-statement&nbsp;name="findByPrimaryKeyattachmentDao"&nbsp;result-class="java.util.HashMap"&gt;<BR>select&nbsp;*&nbsp;from&nbsp;ATTACHMENT<BR>where<BR>ATTACHID=#ATTACHID#<BR>&lt;/mapped-statement&gt;<BR><BR>&lt;!--&nbsp;=============================================<BR>mapped-statement&nbsp;findcount&nbsp;<BR>=============================================&nbsp;--&gt;<BR>&lt;dynamic-mapped-statement&nbsp;name="findattachmentDaoCount"&nbsp;result-class="java.lang.Integer"&gt;<BR>select&nbsp;count(1)&nbsp;from&nbsp;ATTACHMENT<BR>&lt;dynamic&nbsp;prepend="where"&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHID"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHID"&nbsp;&gt;<BR>ATTACHID=#ATTACHID#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILENAME"&nbsp;&gt;<BR>ATTACHFILENAME=#ATTACHFILENAME#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILEPATH"&nbsp;&gt;<BR>ATTACHFILEPATH=#ATTACHFILENAME#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;&nbsp;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHFILESIZE"&nbsp;&gt;<BR>ATTACHFILESIZE=#ATTACHFILESIZE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMIMETYPE"&nbsp;&gt;<BR>ATTACHMIMETYPE=#ATTACHMIMETYPE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHDESC"&nbsp;&gt;<BR>ATTACHDESC=#ATTACHDESC#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONIP"&nbsp;&gt;<BR>ATTACHCREATIONIP=#ATTACHCREATIONIP#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHCREATIONDATE"&nbsp;&gt;<BR>ATTACHCREATIONDATE=#ATTACHCREATIONDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;isPropertyAvailable&nbsp;prepend="and"&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>&lt;isNotNull&nbsp;prepend=""&nbsp;property="ATTACHMODIFIEDDATE"&nbsp;&gt;<BR>ATTACHMODIFIEDDATE=#ATTACHMODIFIEDDATE#<BR>&lt;/isNotNull&gt;<BR>&lt;/isPropertyAvailable&gt;<BR>&lt;/dynamic&gt;<BR>&lt;/dynamic-mapped-statement&gt;<BR><BR>&lt;/sql-map&gt;<BR><BR><BR>下一小就是建立数据操作层的类代码<BR><BR>/*&nbsp;*&nbsp;Created&nbsp;on&nbsp;2003-10-11&nbsp;*&nbsp;*&nbsp;To&nbsp;change&nbsp;the&nbsp;template&nbsp;for&nbsp;this&nbsp;generated&nbsp;file&nbsp;go&nbsp;to&nbsp;*&nbsp;Window&nbsp;-&nbsp;Preferences&nbsp;-&nbsp;Java&nbsp;-&nbsp;Code&nbsp;Generation&nbsp;-&nbsp;Code&nbsp;and&nbsp;Comments&nbsp;*/package&nbsp;com.ewuxi.champion.persistence.dao;<BR>import&nbsp;java.util.HashMap;<BR>import&nbsp;java.util.List;<BR>import&nbsp;com.ewuxi.champion.exception.DaoException;<BR>import&nbsp;com.ibatis.db.sqlmap.SqlMap;<BR>/**<BR>*&nbsp;@author&nbsp;champion<BR>*<BR>*attachment数据库操作对象<BR>*/<BR>public&nbsp;class&nbsp;AttachDb&nbsp;{<BR>/**<BR>*&nbsp;@param&nbsp;vo<BR>*&nbsp;@throws&nbsp;DaoException<BR>*&nbsp;插入一条记录<BR>*/<BR>public&nbsp;void&nbsp;insert(HashMap&nbsp;vo)&nbsp;throws&nbsp;DaoException&nbsp;{<BR>try&nbsp;{<BR>SqlMap&nbsp;sqlMap&nbsp;=&nbsp;DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>sqlMap.executeUpdate("insertattachmentDao",&nbsp;vo);<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>throw&nbsp;new&nbsp;DaoException(e);<BR>}<BR>}<BR>/**<BR>*&nbsp;@param&nbsp;vo<BR>*&nbsp;@throws&nbsp;DaoException<BR>*&nbsp;删除一条记录<BR>*/<BR>public&nbsp;void&nbsp;delete(HashMap&nbsp;vo)&nbsp;throws&nbsp;DaoException&nbsp;{<BR>try&nbsp;{<BR>SqlMap&nbsp;sqlMap&nbsp;=&nbsp;DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>sqlMap.executeUpdate("deleteByPrimaryKeyattachmentDao",&nbsp;vo);<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>throw&nbsp;new&nbsp;DaoException(e);<BR>}<BR>}<BR>/**<BR>*&nbsp;@param&nbsp;vo<BR>*&nbsp;@throws&nbsp;DaoException<BR>*&nbsp;修改一条记录<BR>*/<BR>public&nbsp;void&nbsp;update(HashMap&nbsp;vo)&nbsp;throws&nbsp;DaoException&nbsp;{<BR>try&nbsp;{<BR>SqlMap&nbsp;sqlMap&nbsp;=&nbsp;DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>sqlMap.executeUpdate("updateByPrimaryKeyattachmentDao",&nbsp;vo);<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>throw&nbsp;new&nbsp;DaoException(e);<BR>}<BR>}<BR>/**<BR>*&nbsp;@param&nbsp;vo<BR>*&nbsp;@return<BR>*&nbsp;@throws&nbsp;DaoException<BR>*&nbsp;查找一条记录<BR>*/<BR>public&nbsp;HashMap&nbsp;findByPk(HashMap&nbsp;vo)&nbsp;throws&nbsp;DaoException&nbsp;{<BR>try&nbsp;{<BR>SqlMap&nbsp;sqlMap&nbsp;=&nbsp;DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>return&nbsp;(HashMap)&nbsp;sqlMap.executeQueryForObject(<BR>"findByPrimaryKeyattachmentDao",<BR>vo);<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>throw&nbsp;new&nbsp;DaoException(e);<BR>}<BR>}<BR>public&nbsp;List&nbsp;find(Object&nbsp;vo)&nbsp;throws&nbsp;DaoException&nbsp;{<BR>try&nbsp;{<BR>SqlMap&nbsp;sqlMap&nbsp;=&nbsp;DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>return&nbsp;(List)&nbsp;sqlMap.executeQueryForList("findattachmentDao",&nbsp;vo);<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>throw&nbsp;new&nbsp;DaoException(e);<BR>}<BR>}<BR>}<BR><BR><BR><BR>这一层的代码也是多次见到的老朋友了。事实上对于大多数数据库操作，我们都只需要上面这么一点代码。然后我们建立add的action方法<BR><BR>public&nbsp;ActionForward&nbsp;add(<BR>ActionMapping&nbsp;mapping,<BR>ActionForm&nbsp;form,<BR>HttpServletRequest&nbsp;request,<BR>HttpServletResponse&nbsp;response)<BR>throws&nbsp;Exception&nbsp;{<BR>try&nbsp;{<BR><BR>Service.initSet();<BR>if&nbsp;(form&nbsp;instanceof&nbsp;DynaActionForm)&nbsp;{<BR><BR>DynaActionForm&nbsp;fm&nbsp;=&nbsp;(DynaActionForm)&nbsp;form;<BR>FormFile&nbsp;ff&nbsp;=&nbsp;(FormFile)&nbsp;fm.get("upload");<BR>if&nbsp;(ff&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;ff.getFileSize()&gt;0)&nbsp;{<BR>String&nbsp;fileName&nbsp;=<BR>Service.getPath().substring(<BR>0,<BR>Service.getPath().length()<BR>-&nbsp;"/WEB-INF/classes".length())<BR>+&nbsp;"file/"<BR>+&nbsp;ff.getFileName();<BR>HashMap&nbsp;map&nbsp;=&nbsp;new&nbsp;HashMap();<BR>map.put(Constattachment.ATTACHDESC,&nbsp;fm.get("desc"));<BR>map.put(Constattachment.ATTACHFILENAME,&nbsp;ff.getFileName());<BR>map.put(<BR>Constattachment.ATTACHMIMETYPE,<BR>ff.getContentType());<BR>map.put(Constattachment.ATTACHCREATIONDATE,&nbsp;new&nbsp;Date());<BR>map.put(Constattachment.ATTACHMODIFIEDDATE,&nbsp;new&nbsp;Date());<BR>map.put(<BR>Constattachment.ATTACHFILESIZE,<BR>String.valueOf(ff.getFileSize()));<BR>map.put(<BR>Constattachment.ATTACHFILEPATH,<BR>"/file/"&nbsp;+&nbsp;ff.getFileName());<BR>map.put(<BR>Constattachment.ATTACHCREATIONIP,<BR>request.getRemoteAddr());<BR>FileManager.saveFile(fileName,&nbsp;ff);<BR>AttachDb&nbsp;attachDb&nbsp;=&nbsp;new&nbsp;AttachDb();<BR><BR>DaoCommon.startTransaction();<BR>attachDb.insert(map);<BR>DaoCommon.commit();<BR>request.setAttribute("url",&nbsp;fm.get("url"));<BR>request.setAttribute(<BR>"fileName",<BR>"/file/"&nbsp;+&nbsp;ff.getFileName());<BR>log.info(ff.getFileName());<BR>return&nbsp;mapping.findForward("success");<BR>}<BR>}<BR>ActionErrors&nbsp;errors&nbsp;=&nbsp;new&nbsp;ActionErrors();<BR>errors.add(<BR>ActionErrors.GLOBAL_ERROR,<BR>new&nbsp;ActionError("errors.general",&nbsp;"请选择一个文件!"));<BR>saveErrors(request,&nbsp;errors);<BR>return&nbsp;mapping.findForward("false");<BR>}&nbsp;catch&nbsp;(DaoException&nbsp;e)&nbsp;{<BR>log.error(e,&nbsp;e);<BR>DaoCommon.rollBack();<BR>ActionErrors&nbsp;errors&nbsp;=&nbsp;new&nbsp;ActionErrors();<BR>errors.add(<BR>ActionErrors.GLOBAL_ERROR,<BR>new&nbsp;ActionError("errors.general",&nbsp;"数据库操作错误!"));<BR>saveErrors(request,&nbsp;errors);<BR>return&nbsp;mapping.findForward("false");<BR>}&nbsp;catch&nbsp;(FileNotFoundException&nbsp;e)&nbsp;{<BR>log.error(e,&nbsp;e);<BR>ActionErrors&nbsp;errors&nbsp;=&nbsp;new&nbsp;ActionErrors();<BR>errors.add(<BR>ActionErrors.GLOBAL_ERROR,<BR>new&nbsp;ActionError("errors.general",&nbsp;"文件保存错误!"));<BR>saveErrors(request,&nbsp;errors);<BR>return&nbsp;mapping.findForward("false");<BR>}&nbsp;catch&nbsp;(IOException&nbsp;e)&nbsp;{<BR>log.error(e,&nbsp;e);<BR>ActionErrors&nbsp;errors&nbsp;=&nbsp;new&nbsp;ActionErrors();<BR>errors.add(<BR>ActionErrors.GLOBAL_ERROR,<BR>new&nbsp;ActionError("errors.general",&nbsp;"文件操作错误!"));<BR>saveErrors(request,&nbsp;errors);<BR>return&nbsp;mapping.findForward("false");<BR>}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>log.error(e,&nbsp;e);<BR>ActionErrors&nbsp;errors&nbsp;=&nbsp;new&nbsp;ActionErrors();<BR>errors.add(<BR>ActionErrors.GLOBAL_ERROR,<BR>new&nbsp;ActionError("errors.general",&nbsp;"意外错误!"));<BR>saveErrors(request,&nbsp;errors);<BR>return&nbsp;mapping.findForward("false");<BR>}<BR><BR>}<BR><BR><BR><BR>从上面可以看出，文件的保存工作很简单，只有三句<BR><BR>DynaActionForm&nbsp;fm&nbsp;=&nbsp;(DynaActionForm)&nbsp;form;&nbsp;<BR>FormFile&nbsp;ff&nbsp;=&nbsp;(FormFile)&nbsp;fm.get("upload");<BR>FileManager.saveFile(fileName,&nbsp;ff);&nbsp;<BR><BR>此处有一个DynaActionForm，通过DynaActionForm我们可以节省一个ActionForm的工作了。当然，这也多了一个配置工作。在struts-conifg.xml里加一个<BR><BR><BR>&lt;!--&nbsp;upload&nbsp;form&nbsp;bean&nbsp;--&gt;<BR>&lt;form-bean&nbsp;name="uploadForm"<BR>type="org.apache.struts.action.DynaActionForm"&gt;&nbsp;<BR>&lt;form-property&nbsp;name="upload"&nbsp;type="org.apache.struts.upload.FormFile"/&gt;&nbsp;<BR>&lt;form-property&nbsp;name="url"&nbsp;type="java.lang.String"/&gt;<BR>&lt;form-property&nbsp;name="desc"&nbsp;type="java.lang.String"/&gt;<BR>&lt;/form-bean&gt;&nbsp;<BR><BR>这样，struts在页面提交以后会自动去找upload、rul和&nbsp;desc这三个输入&nbsp;，并将它转成相应的数据类型。<BR>所以我们很容易得到一个FormFile对象，而这个对象就包含了上传文件的所有信息。因此，我们的数据表相应的信息也有了<BR><BR>map.put(Constattachment.ATTACHFILENAME,&nbsp;ff.getFileName());&nbsp;<BR>map.put(&nbsp;Constattachment.ATTACHMIMETYPE,&nbsp;ff.getContentType());<BR>map.put(&nbsp;Constattachment.ATTACHFILESIZE,&nbsp;String.valueOf(ff.getFileSize()));&nbsp;<BR>map.put(&nbsp;Constattachment.ATTACHFILEPATH,&nbsp;"/file/"&nbsp;+&nbsp;ff.getFileName());&nbsp;<BR><BR>最后我们只要简单的调用函数插入数据库<BR><BR>DaoCommon.startTransaction();<BR>attachDb.insert(map);&nbsp;<BR>DaoCommon.commit();&nbsp;<BR><BR>核心技术基本讲解完毕。下面讲一下实现的流程。大家可以先看一下demo。首先是一个index页面，可以选择一个上传一个图片文件直接显示出来。也可以把内容显示在input框中。<BR><BR><BR>&lt;form&nbsp;name="form1"&gt;&lt;img&nbsp;name="image1"&nbsp;src=""&gt;<BR>&lt;input&nbsp;type="text"&nbsp;name="txt"&gt;<BR>&lt;/form&gt;<BR>&lt;input&nbsp;type="button"&nbsp;value="检测"&nbsp;onclick="alert(image1.src)"&gt;<BR>&lt;input&nbsp;type="button"&nbsp;value="上传文件"&nbsp;onclick="popUpWindow(´&lt;c:url&nbsp;value="/upload.do?m=list&amp;url=document．image1.src"/&gt;´)"&gt;<BR>&lt;input&nbsp;type="button"&nbsp;value="上传文件(文件名到输入框)"&nbsp;onclick="popUpWindow(´&lt;c:url&nbsp;value="/upload.do?m=list&amp;url=document．form1.txt.value"/&gt;´)"&gt;<BR><BR><BR><BR>index.jsp的主要内容如上：主要特别的一点的地方就是&lt;c:url&gt;，是JSTL的url的tag,通过它可以得到相对路径的URL。两个按钮的弹出框都是upload.do，方法是list.list的方法很少<BR><BR>AttachDb&nbsp;attachDb&nbsp;=&nbsp;new&nbsp;AttachDb();&nbsp;<BR>DaoCommon.startTransaction();<BR><BR>request.setAttribute("fileslist",&nbsp;attachDb.find(new&nbsp;HashMap()));<BR><BR>DaoCommon.rollBack();<BR><BR><BR><BR>主要就是列出表中所有文件。放到fileslist这个对象中去。然后指到attachlist.jsp这个jsp文件去。作为view层，attachlist很简单的。<BR><BR>&lt;a&nbsp;href="attach.jsp?url=&lt;c:out&nbsp;value="${param[´url´]}"/&gt;"&gt;添加文件&lt;/a&gt;<BR>&lt;table&nbsp;width="100%"&nbsp;border="1"&gt;<BR>&lt;tr&gt;<BR>&lt;td&gt;名称&lt;/td&gt;<BR>&lt;td&gt;格式&lt;/td&gt;<BR>&lt;td&gt;文件&lt;/td&gt;<BR>&lt;td&gt;选择&lt;/td&gt;<BR>&lt;/tr&gt;<BR>&lt;c:forEach&nbsp;var="i"&nbsp;items="${fileslist}"&gt;<BR>&lt;tr&gt;<BR>&lt;td&gt;&lt;c:out&nbsp;value="${i[´ATTACHDESC´]}"/&gt;&lt;/td&gt;<BR>&lt;td&gt;&lt;c:out&nbsp;value="${i[´ATTACHMIMETYPE´]}"/&gt;&lt;/td&gt;<BR>&lt;td&gt;&lt;c:out&nbsp;value="${i[´ATTACHFILEPATH´]}"/&gt;&lt;/td&gt;<BR>&lt;td&gt;&lt;a&nbsp;href="#"&nbsp;onclick="selectone(´&lt;c:url&nbsp;value="/${i[´ATTACHFILEPATH´]}"/&gt;´);"&gt;选择&lt;/a&gt;&nbsp;&lt;a&nbsp;href="&lt;c:url&nbsp;value="upload.do?m=del"&gt;&lt;c:param&nbsp;name="url"&nbsp;value="${param[´url´]}"/&gt;&lt;c:param&nbsp;name="ATTACHID"&nbsp;value="${i[´ATTACHID´]}"/&gt;&lt;/c:url&gt;"&gt;删除&lt;/a&gt;&lt;/td&gt;<BR><BR>&lt;/tr&gt;<BR>&lt;/c:forEach&gt;<BR>&lt;/table&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR>&lt;script&gt;&nbsp;<BR>function&nbsp;selectone(value){&nbsp;<BR>opener.&lt;c:out&nbsp;value="${param[´url´]}"/&gt;=value&nbsp;<BR>window.close();<BR>}<BR>&lt;/script&gt;&nbsp;<BR><BR><BR>首先我们可以看看怎么显示表格&nbsp;&lt;c:forEach&nbsp;var="i"&nbsp;items="${fileslist}"&gt;通过forEach这个tag.得到fieslist里的对象。&nbsp;&lt;c:out&nbsp;value="${i[´ATTACHDESC´]}"/&gt;，通过这一句也可以看到jstl显示HashMap的数据是多么容易。&nbsp;下面就是参数化的URL,看下面的URL。<BR><BR>&lt;a&nbsp;href="&lt;c:url&nbsp;value="upload.do?m=del"&gt;&lt;c:param&nbsp;name="url"&nbsp;value="${param[´url´]}"/&gt;&lt;c:param&nbsp;name="ATTACHID"&nbsp;value="${i[´ATTACHID´]}"/&gt;&lt;/c:url&gt;"&gt;这里有两个参数，一个是url，是从前面的param，也就是前一页的参数取来的。另一个参数是从javaBean对象中取得。ATTACHID就是唯一键，删除的时候就只要这一个参数就可以了。<BR><BR>删除的代码也简单，把ATTACHID放入hashMap,然后执行删除(注，文件没有实际删除，不过要实现文件删除的代码也很简单。)。最后也是读取所有的文件，再返回到本页<BR><BR><BR>AttachDb&nbsp;attachDb&nbsp;=&nbsp;new&nbsp;AttachDb();&nbsp;<BR>DaoCommon.startTransaction();<BR>HashMap&nbsp;delMap&nbsp;=&nbsp;new&nbsp;HashMap();<BR>delMap.put(<BR>Constattachment.ATTACHID,<BR>request.getParameter("ATTACHID"));<BR>attachDb.delete(delMap);<BR><BR>request.setAttribute("fileslist",&nbsp;attachDb.find(new&nbsp;HashMap()));<BR><BR>DaoCommon.commit();<BR><BR><BR>添加文件指向attach.jsp。这个文件是上传的主要文件，实现一个实际的上传界面。<BR><BR>&lt;a&nbsp;href="&lt;c:url&nbsp;value="/upload.do?m=list"&gt;&lt;c:param&nbsp;name="url"&nbsp;value="${param[´url´]}"/&gt;&lt;/c:url&gt;"&gt;文件管理器&lt;/a&gt;<BR>&lt;p&gt;<BR>&lt;html:form&nbsp;action="/upload"&nbsp;enctype="multipart/form-data"&nbsp;onsubmit="return&nbsp;validate(this);"&gt;<BR>说明：&nbsp;&lt;input&nbsp;name="desc"&nbsp;type="input"&nbsp;size="30"&gt;&nbsp;&lt;br&gt;<BR>文件：&lt;input&nbsp;name="upload"&nbsp;type="file"&nbsp;id="upload"&nbsp;size="50"&gt;&lt;br&gt;<BR>&lt;input&nbsp;name="url"&nbsp;type="hidden"&nbsp;value="&lt;c:out&nbsp;value="${param[´url´]}"/&gt;"&gt;<BR>&lt;input&nbsp;name="m"&nbsp;type="hidden"&nbsp;value="add"&gt;<BR>&lt;input&nbsp;type="submit"&nbsp;name="Submit"&nbsp;value="上传"&gt;&nbsp;<BR><BR>&lt;/html:form&nbsp;&gt;<BR>&lt;/p&gt;<BR>&lt;/body&gt;&nbsp;<BR><BR>提交以后执行前面所说的add方面。然后转到success.jsp。其内容就是把前面的fileName转到index页面，同时关闭自己。<BR><BR>&lt;script&gt;&nbsp;<BR>opener.&lt;c:out&nbsp;value="${url}"/&gt;="&lt;c:url&nbsp;value="/${fileName}"/&gt;";&nbsp;<BR><BR>window.close();<BR><BR>&lt;/script&gt;&nbsp;<BR></P><img src ="http://www.blogjava.net/RR00/aggbug/13963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-09-25 00:20 <a href="http://www.blogjava.net/RR00/articles/13963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts Recipes: Hibernate and Struts</title><link>http://www.blogjava.net/RR00/articles/13308.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Sun, 18 Sep 2005 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/13308.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/13308.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/13308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/13308.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/13308.html</trackback:ping><description><![CDATA[&nbsp;
<P>
<H1 align=center>Struts Recipes: Hibernate and Struts</H1>
<H3 align=center>Add the power of Hibernate to your Struts application</H3>
<P></P><!--<BLOCKQUOTE><STRONG>Summary</STRONG><BR>-->
<BLOCKQUOTE><STRONG>Summary</STRONG><BR>In this excerpt from <EM>Struts Recipes,</EM> (Manning Publications, December 2004) authors George Franciscus and Danilo Gurovich illustrate how to use Hibernate in a Struts application. They also show how to create a Struts plug-in to improve performance. (<EM>2,200 words;</EM> <STRONG>January 24, 2005</STRONG>) </BLOCKQUOTE><!--</BLOCKQUOTE>--><A href="http://www.javaworld.com/feedback" target=Feedback><STRONG>By George Franciscus and Danilo Gurovich </STRONG></A><BR><BR>
<P><IMG height=29 alt=P src="http://www.javaworld.com/javaworld/abcs/P.gif" width=24 align=left>ersistence is a fundamental piece of an application. Obviously, without persistence all work would be lost. However, persistence means different things to different people. The length of time something must be persisted is a fundamental qualifier in choosing a persistence storage medium. For example, the HTTP session may be suitable when the life of a piece of data is limited to the user's session. In contrast, persistence over several sessions, or several users, requires a database. The volume of data is another important qualifier. For example, best practices suggest large amounts of data should not be stored in an HTTP session. In those circumstances, you need to consider a database. In this recipe we target persistence in a database. 
<P>The type of database you choose has an important influence on your architecture and design. As object-oriented developers, we tend to represent data as an interconnected web of objects as a means to describe the business problem at hand—this is often called a domain model. However, the most common storage medium is based on a relational paradigm. Unless our object model mirrors a relational structure, the in-memory representation of our data is at odds with the means to persist it. This problem is called the <EM>mismatch paradigm</EM>. One of the most popular tools to address the mismatch problem is a category of tools called object-relational mappers. An object-relational mapper is software used to transform an object view of the data into a relational one, and provide persistence services, such as create, read, update, and delete (CRUD). Many good papers have been written on object-relational mappers, but in essence, they all speak to the Data Mapper pattern. One of the most popular object-relational mappers is the open source Hibernate project. 
<P>In this recipe, we show you how to employ Hibernate in a Struts application. In addition, we will show you how to create a Struts plug-in to give your Hibernate-powered Struts applications a performance boost. 
<P><FONT size=+1><STRONG>Recipe</STRONG></FONT><BR>In this recipe, we use an example to illustrate everything you need to do to use Hibernate in a Struts application. We create an application to retrieve and display elements from the chemical periodic table. The application offers the user a search page to look for an element by element symbol. The application responds by searching the database for an element matching the symbol name and returns information about the element. 
<P>We'll start by showing you how to get the Hypersonic database server up and running. With the database server started, we create the table and data required to exercise the application. Once the database is ready to go, we'll create all the Hibernate artifacts required to execute this application by using the Hypersonic database server. The next step is to respond to search requests by calling upon Hibernate to handle database access from inside our <CODE>Action</CODE>. Because creating Hibernate factory objects is expensive, we'll create a Struts plug-in to create the factory and store it in context. 
<P>Let's start by bringing up the Hypersonic database server. You need to download Hypersonic from http://hsqldb.sourceforge.net/. Place <CODE>hsqldb.jar</CODE> in your classpath and launch Hypersonic by entering the following command in your DOS prompt: 
<P><CODE>
<P><CODE>java org.hsqldb.Server </CODE>
<P></CODE>
<P>Although the server's response varies from one version of Hypersonic to another, the following response is a typical indication that Hypersonic is ready to serve database requests. 
<P><CODE>
<P><CODE>Server 1.6 is running<BR>Press [Ctrl]+{c} to abort </CODE>
<P></CODE>
<P>With the database server up and running, we are ready to create the elements table and populate it with data, as shown in Listing 1. 
<P><STRONG>Listing 1. Create and populate elements tables</STRONG> 
<P><CODE>
<P><CODE>create table elements (id integer(3) IDENTITY,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name char(30),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; number char(30),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mass char(30),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; symbol char(2));<BR><BR>CREATE UNIQUE INDEX ui_elements_pk ON elements (symbol)<BR><BR>insert into elements ( name, number, mass, symbol) values ('Manganese','25','55','Mn');<BR>insert into elements ( name, number, mass, symbol) values ('Zinc','30','65','Zn');<BR>insert into elements ( name, number, mass, symbol) values ('Thulium','69','169','Tm');<BR>insert into elements ( name, number, mass, symbol) values ('Californium','98','251','Cf');<BR>insert into elements ( name, number, mass, symbol) values ('Gold','79','197','Au');<BR>insert into elements ( name, number, mass, symbol) values ('Ytterbium','70','173','Yb');<BR>insert into elements ( name, number, mass, symbol) values ('Molybdenum','42','96','Mo');<BR>insert into elements ( name, number, mass, symbol) values ('Palladium','46','106','Pd'); </CODE>
<P></CODE>
<P>Listing 1 presents the SQL commands necessary to create the elements table, create a unique index on <CODE>symbol</CODE>, and insert data We have only presented a few of the periodic elements. We'll leave it to you to dust off your high school chemistry textbook to create data for the remaining elements. 
<P>Listing 2 presents the <CODE>Element</CODE> JavaBean used to store data retrieved from the database. 
<P><STRONG>Listing 2. Element JavaBean</STRONG> 
<P><CODE>
<P><CODE>package com.strutsrecipes.hibernate.beans;<BR><BR>public class Element {<BR>&nbsp;&nbsp; private String name;<BR>&nbsp;&nbsp; private String symbol;<BR>&nbsp;&nbsp; private String number;<BR>&nbsp;&nbsp; private String mass;<BR>&nbsp;&nbsp; private int id;<BR><BR>&nbsp;&nbsp; public Element() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super();<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public Element(String name, String symbol, String number, String mass) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name = name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.symbol = symbol;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.number = number;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.mass = mass;<BR><BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public int getId() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return id;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setId(int id) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.id = id;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public String getMass() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mass;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public String getName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return name;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public String getNumber() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return number;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public String getSymbol() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return symbol;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setMass(String mass) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.mass = mass;<BR><BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setName(String name) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name = name;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setNumber(String number) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.number = number;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setSymbol(String symbol) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.symbol = symbol;<BR>&nbsp;&nbsp; }<BR>} </CODE>
<P></CODE>
<P>Hibernate is an object-relational mapping tool. Its job is to map objects to relational tables and vice versa. Therefore, we must tell Hibernate how to map the columns in the "elements" table to the properties of the <CODE>Elements</CODE> JavaBean. This is done using the <CODE>Element.hbm.xml</CODE> file. The information embodied in this file is required to empower Hibernate to copy data from the table to the <CODE>Elements</CODE> JavaBean. If we were using Hibernate to update data, the information in the <CODE>Element.hbm.xml</CODE> file would be used to extract data from the <CODE>Elements</CODE> JavaBean to generate SQL update statements. Listing 3 presents <CODE>Element.hbm.xml</CODE>. 
<P><STRONG>Listing 3. Element.hbm.xml</STRONG> 
<P><CODE>
<P><CODE>&lt;?xml version="1.0"?&gt;<BR>&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"<BR>&nbsp;&nbsp; "http://hibernate.sf.net/hibernate-mapping-2.0.dtd"&gt;<BR><BR>&lt;hibernate-mapping&gt;<BR>&nbsp;&nbsp; &lt;class name="com.strutsrecipes.hibernate.beans.Element" table="elements"&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id name="id" column="id"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="native"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/id&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="name" column="name"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="number" column="number"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="mass" column="mass"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="symbol" column="symbol"/&gt;<BR>&nbsp;&nbsp; &lt;/class&gt;<BR>&lt;/hibernate-mapping&gt; </CODE>
<P></CODE>
<P>Let's step through Listing 3 
<P>We declare the full package name of the class to be associated with the "elements" table. We then declare the name of the table associated with that class. Next, we declare the mapping from the <CODE>id</CODE> JavaBean property to the <CODE>id</CODE> column. Because the property and column names have the same value, we could have omitted the column attribute, but we have explicitly declared the column for clarity purposes. The <CODE>&lt;id&gt;</CODE> tag is a special tag. It is used to declare the primary key for the table. The enclosing <CODE>&lt;generator&gt;</CODE> tag instructs Hibernate to generate the key in whichever way is most appropriate for the database implementation. You should consult Hibernate documentation for more information on the <CODE>&lt;id&gt;</CODE> tag. Finally, we declare mapping for the remaining JavaBean properties. Once again the <CODE>column</CODE> attribute is declared for clarification purposes. 
<P>Once the mapping file has been broken down in detail, it's all rather straightforward. It simply describes which table maps to which class and which JavaBean properties map to which column names. Later on we will tell you where to place this file. 
<P>Next, we configure Hibernate by declaring environmental information. In Listing 4, we present the <CODE>hibernate.cfg.xml</CODE> file. 
<P><STRONG>Listing 4. hibernate.cfg.xml</STRONG> 
<P><CODE>
<P><CODE>&lt;?xml version='1.0' encoding='utf-8'?&gt;<BR>&lt;!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"<BR>&nbsp;&nbsp; "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"&gt;<BR><BR>&lt;hibernate-configuration&gt;<BR>&nbsp;&nbsp; &lt;session-factory&gt;<BR>&nbsp;&nbsp; &lt;property name="dialect"&gt;net.sf.hibernate.dialect.HSQLDialect&lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name="connection.driver_class"&gt;org.hsqldb.jdbcDriver&lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name="connection.username"&gt;sa&lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name="connection.password"&gt;&lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name="connection.url"&gt;jdbc:hsqldb:hsql://127.0.0.1&lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name="show_sql"&gt; &lt;/property&gt;<BR>&nbsp;&nbsp; &lt;property name=""&gt;true&lt;/property&gt;<BR><BR>&nbsp;&nbsp; &lt;mapping resource="/com/strutscookbook/hibernate/beans/Element.hbm.xml"/&gt;<BR>&lt;/session-factory&gt;<BR>&lt;/hibernate-configuration&gt; </CODE>
<P></CODE>
<P>Let's step through Listing 4. 
<P>We start by specifying the database implementation dialect that allows Hibernate to take advantage of implementation-specific features. We declare the Hypersonic dialect. You should consult the Hibernate documentation to choose the appropriate dialect for your database. We then declare the database driver. You must ensure this driver is in your application's classpath. We then declare the database username, the database password, and the database connection URL. Next, we instruct Hibernate to display the SQL generated at runtime in the log. 
<P>The <CODE>hibernate.cfg.xml</CODE> file must be placed in your classpath. 
<P>The procedure to use Hibernate within your application requires the following steps: 
<P>
<OL>
<LI>Create a Hibernate configuration object 
<P></P>
<LI>Use the Hibernate configuration object to create a Hibernate factory object 
<P></P>
<LI>Use the Hibernate factory object to create a Hibernate session object 
<P></P>
<LI>Use the Hibernate session object to start a transaction (optional) 
<P></P>
<LI>Employ the Hibernate session object to create, read, update, and delete data on the database 
<P></P>
<LI>Commit the transaction (optional) 
<P></P>
<LI>Close the session</LI></OL>
<P>A Hibernate best practice is to create and cache the Hibernate factory to enhance performance. Therefore, we will create a Struts plug-in to perform Steps 1 and 2 and cache the Hibernate factory in the servlet context, as shown in Listing 5. 
<P><STRONG>Listing 5. HibernatePlugin.java</STRONG> 
<P><CODE>
<P><CODE>package com.strutsrecipes.hibernate.plugin;<BR><BR>import java.net.URL;<BR>import javax.servlet.ServletException;<BR><BR>import net.sf.hibernate.HibernateException;<BR>import net.sf.hibernate.MappingException;<BR>import net.sf.hibernate.SessionFactory;<BR>import net.sf.hibernate.cfg.Configuration;<BR><BR>import org.apache.commons.logging.Log;<BR>import org.apache.commons.logging.LogFactory;<BR>import org.apache.struts.action.ActionServlet;<BR>import org.apache.struts.action.PlugIn;<BR>import org.apache.struts.config.ModuleConfig;<BR><BR>public class HibernatePlugin implements PlugIn {<BR>&nbsp;&nbsp; private Configuration config;<BR>&nbsp;&nbsp; private SessionFactory factory;<BR>&nbsp;&nbsp; private String path = "/hibernate.cfg.xml";<BR>&nbsp;&nbsp; private static Class clazz = HibernatePlugin.class;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static final String KEY_NAME = clazz.getName();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private static Log log = LogFactory.getLog(clazz);<BR><BR>&nbsp;&nbsp; public void setPath(String path) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.path = path;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void init(ActionServlet servlet, ModuleConfig modConfig)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws ServletException {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL url = HibernatePlugin.class.getResource(path);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; config = new Configuration().configure(url);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; factory = config.buildSessionFactory();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet.getServletContext().setAttribute(KEY_NAME, factory);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (MappingException e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("mapping error", e);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ServletException();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (HibernateException e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("hibernate error", e);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ServletException();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void destroy() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; factory.close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (HibernateException e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("unable to close factory", e);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp; }<BR>}</CODE> 
<P></CODE>
<P>Creating a Struts plug-in requires only two steps. First, create a class implementing <CODE>org.apache.struts.action.PlugIn</CODE> (Listing 5). Second, define a <CODE>&lt;plug-in&gt;</CODE> tag in the <CODE>struts-config.xml</CODE> file (Listing 6). 
<P>Let's step through Listing 5. 
<P>We create a constant to hold the name of the servlet context attribute key. We have chosen to use the <CODE>HibernatePlugin</CODE> class name. Notice the constant is static public final. We use the <CODE>HibernatePlugin</CODE> class to access the key name in the <CODE>Action</CODE> (Listing 7). We define the path property. By default, the <CODE>Hibernate-Plugin</CODE> looks for the Hibernate configuration file at <CODE>/hibernate.cfg.xml</CODE>. You can use this property to load the Hibernate configuration file from another filename and directory anywhere on the classpath. Next, we use the classloader to find the Hibernate configuration file and then we create the Hibernate configuration object. We use the Hibernate configuration object to create a Hibernate factory object and then we store the Hibernate factory object in the servlet context. The factory is now available to any code with a reference to the servlet. 
<P>As a good practice, we close the factory in the destroy method. 
<P>Listing 6 presents the application struts-config. The only thing out of the ordinary here is the <CODE>&lt;plug-in&gt;</CODE> tag. This is where we declare the Hibernate plug-in, which creates and caches the Hibernate factory object. 
<P><STRONG>Listing 6. struts-config.xml</STRONG> 
<P><CODE>
<P><CODE>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;<BR><BR>&lt;!DOCTYPE struts-config PUBLIC<BR>&nbsp;&nbsp; "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"<BR>&nbsp;&nbsp; "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;<BR><BR>&lt;struts-config&gt;<BR>&nbsp;&nbsp; &lt;form-beans&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form-bean name="searchForm"type="com.strutsrecipes.hibernate.forms.SearchForm"/&gt;<BR>&nbsp;&nbsp; &lt;/form-beans&gt;<BR><BR>&nbsp;&nbsp; &lt;global-forwards&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;forward name="search" path="/search.jsp"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;forward name="searchsubmit" path="/searchsubmit.do"/&gt;<BR>&nbsp;&nbsp; &lt;/global-forwards&gt;<BR><BR>&nbsp;&nbsp; &lt;action-mappings&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action path="/searchsubmit"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type="com.strutsrecipes.hibernate.actions.SearchAction"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name="searchForm"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scope="request"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input="/search.jsp"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;forward name="success" path="/element.jsp"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt;<BR>&nbsp;&nbsp; &lt;/action-mappings&gt;<BR><BR>&nbsp;&nbsp; &lt;plug-in className="com.strutsrecipes.hibernate.plugin.HibernatePlugin"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;set-property property="path" value="/hibernate.cfg.xml"/&gt;<BR>&nbsp;&nbsp; &lt;/plug-in&gt;<BR>&lt;/struts-config&gt; </CODE>
<P></CODE>
<P>Listing 7 presents the <CODE>SearchForm</CODE> used to search for an element. It's very simple because the user can only search by element symbol. 
<P><STRONG>Listing 7. SearchForm.java</STRONG> 
<P><CODE>
<P><CODE>package com.strutsrecipes.hibernate.forms;<BR><BR>import org.apache.struts.action.ActionForm;<BR>public class SearchForm extends ActionForm {<BR>&nbsp;&nbsp; String symbol;<BR><BR>&nbsp;&nbsp; public String getSymbol() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return symbol;<BR>&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; public void setSymbol(String symbol) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.symbol = symbol;<BR>&nbsp;&nbsp; }<BR>} </CODE>
<P></CODE>
<P>Let's have a look at the <CODE>SearchAction</CODE> in Listing 8. Although you may decide to employ Hibernate in other areas of your application architecture, we have chosen to use it in the <CODE>Action</CODE>. We'll defer the discussion of the other alternatives to the discussion section. 
<P><STRONG>Listing 8. SearchAction.java</STRONG> 
<P><CODE>
<P><CODE>package com.strutsrecipes.hibernate.actions;<BR><BR>import java.util.List;<BR><BR>import javax.servlet.http.HttpServletRequest;<BR>import javax.servlet.http.HttpServletResponse;<BR><BR>import org.apache.commons.logging.Log;<BR>import org.apache.commons.logging.LogFactory;<BR><BR>import net.sf.hibernate.Hibernate;<BR>import net.sf.hibernate.HibernateException;<BR>import net.sf.hibernate.Session;<BR>import net.sf.hibernate.SessionFactory;<BR><BR>import org.apache.struts.action.Action;<BR>import org.apache.struts.action.ActionError;<BR>import org.apache.struts.action.ActionErrors;<BR>import org.apache.struts.action.ActionForm;<BR>import org.apache.struts.action.ActionForward;<BR>import org.apache.struts.action.ActionMapping;<BR><BR>import com.strutsrecipes.hibernate.beans.Element;<BR>import com.strutsrecipes.hibernate.forms.SearchForm;<BR>import com.strutsrecipes.hibernate.plugin.HibernatePlugin;<BR><BR>public class SearchAction extends Action {<BR>&nbsp;&nbsp; private static Log log = LogFactory.getLog(SearchAction.class);<BR><BR>&nbsp;&nbsp; final public static String HQL_FIND_ELEMENT =<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"from com.strutsrecipes.hibernate.beans.Element as e where e.symbol = ?";<BR><BR>&nbsp;&nbsp; public ActionForward execute(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionMapping mapping,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionForm form,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest request,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse response)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws Exception {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SearchForm searchForm = (SearchForm) form;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List elements = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionFactory factory = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session session = null;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; factory =<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(SessionFactory) servlet.getServletContext()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getAttribute(HibernatePlugin.KEY_NAME);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session = factory.openSession();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elements =<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.find(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HQL_FIND_ELEMENT,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;searchForm.getSymbol(),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate.STRING);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!elements.isEmpty()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element = (Element) elements.get(0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (HibernateException e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Hibernate error", e);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.error("Hibernate exception encountered");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (element != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.setAttribute("element", element);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mapping.findForward("success");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionErrors errors = new ActionErrors();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errors.add(ActionErrors.GLOBAL_ERROR,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("error.notfound"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saveErrors(request, errors);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mapping.getInputForward();<BR>&nbsp;&nbsp; }<BR>} </CODE>
<P></CODE>
<P>Let's take a quick overview of what happens in the <CODE>SearchAction</CODE>. The <CODE>SearchAction</CODE> uses the <CODE>SearchForm.getSymbol()</CODE> method to obtain the element symbol entered by the user on the search page. Hibernate is used to search the database and convert the data stored in the database to an <CODE>Element</CODE> object. The <CODE>Element</CODE> object is placed in request context for the JavaServer Pages (JSP) page. Let's step through Listing 8 line by line to see how it's done in detail. 
<P>First, we declare a constant to search the database. We next cast the form to <CODE>SearchForm</CODE> and then we obtain the Hibernate factory. Recall the Hibernate plug-in has already created the factory and cached it in the servlet context. Next, we obtain a session. The session obtains a connection to the database. Hibernate uses the configuration information we created in Listing 4 to connect to the database. We then search the database. 
<P>There are other ways to employ Hibernate to search the database, but the <CODE>find</CODE> method is appropriate whenever a search doesn't use the primary key. Notice, we have the <CODE>HQL_FIND_ELEMENT</CODE> constant declared. The SQL defined in <CODE>HQL_FIND_ELEMENT</CODE> looks somewhat like standard SQL, but not quite. The SQL used by Hibernate is proprietary to Hibernate and reflects an object-oriented version of SQL, rather than the relational SQL to which you are accustomed. 
<P>Let's delve into the Hibernate SQL (HQL) code snippet. 
<P><CODE>
<P><CODE>from com.strutsrecipes.hibernate.beans.Element as e where e.symbol = ?</CODE> 
<P></CODE>
<P>This statement tells Hibernate to select all <CODE>Element</CODE> objects residing in the <CODE>com.strutsrecipes.hibernate.beans</CODE> package. The <CODE>where</CODE> clause filters the list to only those elements whose symbols match a runtime parameter. The <CODE>as e</CODE> indicates that <CODE>e</CODE> may be used as an alias elsewhere in the HQL, as we have done in the <CODE>where</CODE> clause. You can see that we are selecting objects, not rows, in the database. Hibernate uses the information in Listing 4 to map the class we are interested in to its associated table. In this example, the relationship between the table and the object are very close, but that does not necessarily need to be the case. 
<P>The second and third arguments to the <CODE>find</CODE> method are the value and data type of the HQL replacement parameter. The Hibernate reference material describes other ways to replace runtime parameters. 
<P>The <CODE>find</CODE> method always returns a <CODE>List</CODE>. In this case, we obtain a list of <CODE>Element</CODE> objects. We are confident that a maximum of one instance is returned because the "elements" table has a unique key constraint on the <CODE>symbol</CODE> column (see Listing 1). 
<P>Returning to Listing 8, we copy the element reference in the first position in the list to the element variable. To deal with any Hibernate exceptions, we have chosen to log the exception and present the user a "not found" message, but you may decide to present a different message or use declarative exception handling. Next, we close the session. Closing the session in the <CODE>finally</CODE> clause guarantees it is attempted even when exceptions are thrown. We store the <CODE>Element</CODE> object in the request context and finally we build the <CODE>ActionError</CODE> when the symbol can't be found. For the sake of completeness, we have presented the <CODE>search.jsp</CODE> (Listing 9) and the <CODE>element.jsp</CODE> (Listing 10). 
<P><STRONG>Listing 9. Search.jsp</STRONG> 
<P><CODE>
<P><CODE>&lt;%@ page language="java" %&gt;<BR>&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;<BR><BR>&lt;html:html&gt;<BR>&lt;body&gt;<BR>&nbsp;&nbsp; &lt;h1&gt;Search for an Element&lt;/h1&gt;<BR><BR>&nbsp;&nbsp; &lt;html:form action="/searchsubmit.do"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;symbol &lt;form:text property="symbol"/&gt;<BR>&nbsp;&nbsp; &lt;html:submit value="Search"/&gt;<BR>&nbsp;&nbsp; &lt;/html:form&gt;<BR><BR>&nbsp;&nbsp; &lt;html:errors/&gt;<BR><BR>&lt;/body&gt;<BR>&lt;/html:html&gt; </CODE>
<P></CODE>
<P><STRONG>Listing 10. Element.jsp</STRONG> 
<P><CODE>
<P><CODE>&lt;%@ page language="java" %&gt;<BR>&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;<BR>&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;<BR><BR>&lt;html:html&gt;<BR>&nbsp;&nbsp; &lt;h1&gt;Periodic Element&lt;/h1&gt;<BR>&nbsp;&nbsp; Name: &lt;bean:write name="element" property="name"/&gt;&lt;br&gt;<BR>&nbsp;&nbsp; Symbol: &lt;bean:write name="element" property="symbol"/&gt;&lt;br&gt;<BR>&nbsp;&nbsp; Number: &lt;bean:write name="element" property="number"/&gt;&lt;br&gt;<BR>&nbsp;&nbsp; Mass: &lt;bean:write name="element" property="mass"/&gt;&lt;br&gt;<BR><BR>&nbsp;&nbsp; &lt;html:link forward="search"&gt;Search&lt;/html:link&gt;&lt;p&gt;<BR>&lt;/html:html&gt; </CODE>
<P></CODE>
<P>Before putting Hibernate to work, consult the Hibernate documentation to ensure you have all the required Hibernate jar files in your classpath. 
<P><FONT size=+1><STRONG>Discussion</STRONG></FONT><BR>Persistence of data is a tedious and laborious job. To make matters worse, a considerable effort must be spent transforming an object-oriented representation of the data to a relational one, and vice versa. Fortunately, several good object-relational mappers exist to ease this burden. In this recipe, we explored Hibernate—one of the most popular open source object-relational mappers available to Java programmers. 
<P>Hibernate is a very rich product with many unexplored features left for you to discover. Our simple example is limited to <CODE>read</CODE> behavior, but the rest of the CRUD family is just as easy. Update functionality is as simple as accessing the desired element, calling the desired JavaBean setter, and calling the session commit method. Hibernate takes care of generating the SQL and updating the table. A <CODE>delete</CODE> is also rather simple—<CODE>session.delete(element)</CODE> is all it takes! Finally, <CODE>create</CODE> only requires instantiating the object, calling the setters, and calling <CODE>session.save(element)</CODE>. 
<P>Hibernate best practices recommend caching the Hibernate factory object. We chose to create and cache the factory using a Struts plug-in. Alternatively, you could have chosen to cache using any other means in your arsenal. 
<P>Although this recipe can serve you well, there are some drawbacks. First, we have exposed Hibernate to the Struts <CODE>Action</CODE>. Migrating to another persistence layer framework requires us to change every <CODE>Action</CODE> employing Hibernate. Second, our persistence is tightly coupled to the presentation layer. This coupling denies us the opportunity to reuse the persistence logic in some other presentation mechanism, such as a batch program. 
<P>Although there is room for improvement, this recipe is suitable when you do not expect to reuse your persistence logic. You may find yourself in this situation developing prototypes or small throwaway applications. <BR><BR></P>
<P><STRONG>About the author</STRONG><BR>George Franciscus is a J2EE consultant and Struts authority. He is a coauthor of Manning's <EM>Struts in Action</EM>. 
<P>Danilo Gurovich is a manager of Web engineering at an e-commerce company. He has designed e-commerce and ERP/EAI Struts applications, and has led teams who have built them. <BR></P><img src ="http://www.blogjava.net/RR00/aggbug/13308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-09-18 14:11 <a href="http://www.blogjava.net/RR00/articles/13308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts Resources</title><link>http://www.blogjava.net/RR00/articles/10014.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 12 Aug 2005 19:57:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/10014.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/10014.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/10014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/10014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/10014.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Contributor Taglibs</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://husted.com/struts/resources/MonkeyStruts.htm"><B>MonkeyStruts</B></A> by Arron Bates. An approach to nesting beans.</P>
<P><A href="http://www.multimania.com/bist77/struts.php"><FONT size=2><B>REGEXP.VALIDATOR.STRUTS</B></FONT></A> by Emmanuel Boudrant - A validation component that works with Struts 1.0, to manage form validation on server-side and client-side.</P>
<P><A href="http://husted.com/struts/resources/struts-was.zip"><B>Struts-WAS.jar</B></A> by Christopher Assenza - Modified Struts 1.0 JAR for Websphere 3.5 or 4. Zipped for download. (For additional tips regarding Websphere 3.5 see <A href="http://jakarta.apache.org/struts/installation-was352-x.html">http://jakarta.apache.org/struts/installation-was352-x.html</A>.)</P>
<P><A href="http://struts.application-servers.com/"><B>Struts Layout</B></A> by Improve - An extension library to improve interfaces creation with Struts.</P>
<P><A href="http://husted.com/struts/resources/indexed-tags.htm"><B>Indexed Tags</B></A> [Also available in the nightly build] by Dave Hays - Produce indexed names such as &lt;input type="text" name="parameter[0].value" value="Mac"&gt;. Link, Submit, and Select tags are included too.</P>
<P><A href="http://husted.com/struts/resources/logic-niallp.htm"><B>Struts IF/THEN/ELSE and SWITCH tags</B></A> by Niall Pemberton.</P>
<P><A href="http://www.mail-archive.com/struts-dev@jakarta.apache.org/msg01251.html"><B>TextArea Wrapping</B></A> by Matthias Bauer. Patch to HTML:TextArea tag to provide wrapping of long lines.</P>
<P><A href="http://husted.com/struts/resources/rowtag.zip"><B>RowTag</B></A> (ZIP file for download) - Source for a Struts-compatible tag to generate alternating row colors in a table by Niall Pemberton. [<I>NOTE: Requires a Struts build dated after 2001-04-28</I>]</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=extensions></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Contributor Extensions</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="file:///D:/DOWNLOAD/2004822203916/struts/resources/pow2acl.htm"><B>Pow2ACL</B></A> - Access Control List library. Track of application users roles and permissions. User can be authenticated: - directly using the package API; - using custom JSP tag libraries. </P>
<P><A href="http://bist77.multimania.com/struts.php#rose"><B>Struts .. in Rose</B></A> by Emmanuel.Boudrant - Use Struts with the Rational Rose UML model. </P>
<P><A href="http://husted.com/struts/resources/multi-struts.htm"><B>Multi-Controller</B></A> by Sukachevin, Stoehr - Use more than once ActionServlet in your Struts application </P>
<P><A href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg16093.html"><B>JavaScript with html:errors - new Struts validation</B></A> by Adam Grohs. </P>
<P><A href="http://www.scioworks.com/scioworks_camino.html"><B>Scioworks Camino</B></A> by Scioworks Pte Ltd. A visual tool for Struts. </P>
<P><A href="http://www.ejcenter.com/struts/"><B>Struts Console</B></A> by James Holmes. The Struts Console is a Java Swing application that provides an easy to use interface for editing Struts' "struts-config.xml" configuration file.</P>
<P><A href="http://jcorporate.com/"><B>Expresso</B></A> by JCorporate. An open source application development (AD) framework integrated with Struts.</P>
<P><A href="http://husted.com/struts/resources/DynamicProperties.htm"><B>Dynamic ActionForm Properties</B></A> by Jan Sorensen.</P>
<P><A href="http://husted.com/struts/resources/bean-util.htm"><B>Bean Utils with Indexed Strings</B></A> by Gregor Rayman.</P>
<P><A href="http://husted.com/struts/resources/struts-security.htm"><B>Role-Based Actions</B></A> by Nic Hobs. Set a security role for an Action from with struts-config.</P>
<P><A href="http://husted.com/struts/resources/codemaker.htm"><B>Struts CodeMaker</B></A> by Ravindran Ramaiah - Generate Struts application by reading configuration file or JSP files. Updated 2001-08-21.</P>
<P><A href="http://home.earthlink.net/~dwinterfeldt/generator/"><B>Struts Generator</B></A> by David Winterfeldt - Based on the generator.xml and a table/query an xml file is generated. Based on the generated xml file a primary key class, data bean class, jdbc class, and an ActionForm (Struts) can be generated.</P>
<P><A href="http://husted.com/struts/resources/ValueIterator.zip"><B>ValueIterator</B></A> by Ted Husted - Simple wrapper around a RowSet for use with Struts iterator tag. Also includes generic toMap(), set(map) methods for flexible data transfer.</P>
<P><A href="http://www.rpsenterprises.com/struts/index.html"><B>Struts Transformer</B></A> by Ron Smith - Transformations are responsible for taking an object in one form and transforming it into another. A forward transformation takes an object from its primary form to a secondary form (e.g. Date object to String). A reverse transformation takes an object from a secondary form to its primary form (e.g. String to Date).</P>
<P><A href="http://www.rpsenterprises.com/struts/index.html"><B>Struts Extender</B></A> by Ron Smith - Add extensions to the struts framework via entries in the Struts configuration file.</P>
<P><A href="http://husted.com/struts/resources/mapper.zip"><B>Mapper Framework</B></A> by Capco - The Mapper framework can be used for automating the process of validating/converting/transferring data fields. <FONT size=2>(See README to get started. Updated 18-JUL-2001.)</FONT></P>
<P><A href="http://www.sura.ru/~gonza/bean-factory/"><B>Bean factory</B></A> by Oleg V Alexeev - Adds the ability to easily link data bean creation to any Struts Action. All information about databeans and actions mappings stored in the standard Struts configuraton file. </P>
<P><A href="http://husted.com/struts/resources/workflow.htm"><B>Workflow Extension</B></A> by Matthias Bauer - An extension to the core Struts framework which provides control flow between actions.</P>
<P><A href="http://husted.com/struts/resources/struts-menu.zip"><B>Struts Menu</B></A> by Scott Sayles (ZIP file for download) - A Struts-compatible web menuing component (early release - work in progress) - unzip to a "struts-menu" folder, and see the README.</P>
<P><A href="http://home.earthlink.net/~dwinterfeldt/"><B>Struts Validator</B></A> [Also in the nightly build /contrib folder] by David Winterfeldt - Perform basic validations to check if a field is required, matches a regular expression, and some basic type checking. Different validation rules can be defined for different locales. The framework has basic support for user defined constants which can be used in some field attributes. The validation routines are modifiable in the validation.xml file so custom validation routines can be created and added to the framework.</P>
<P><A href="http://husted.com/struts/resources/tldtovlm.zip"><B>TLD to VLM</B></A> by Mario Busche - Simple Java program to convert standard TLD's to the VLM format used by Homesite, CF Studio, and JRun Studio.</P>
<P><A href="http://jakarta.apache.org/taglibs/doc/ultradev4-doc/intro.html"><B>UltraDev 4.0 Custom Tag Library Extension</B></A> - Hosted by Jakarta Taglibs.</P>
<P><A href="http://www.lifl.fr/~dumoulin/tiles/"><B>Tiles Library for building JSP views</B></A> [Also in the nightly build /contrib folder] by Cedric Dumoulin - A component is a JSP page that can be inserted in another JSP page, like templates, but can take "parameters" (URLs or 'direct' string intemplates).</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=examples></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Projects and Examples</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://husted.com/struts/resources/artimus.zip"><B>Artimus</B></A> by Ted Husted - Simple news poster application. Demonstrates using helper beans and a JDBC database with Struts. WAR zipped for download. Uses Scaffold package. See WEB-INF/README.txt for setup.</P>
<P><A href="http://husted.com/struts/resources/scaffold.zip"><B>Scaffold</B></A> by Ted Husted - Utility package of classes that can be used with various Web applications.</P>
<P><A href="http://husted.com/struts/resources/polls-20010812.zip"><B>Struts Polls</B></A> by Ted Husted - Simple poll application. Demonstrates using a database with Struts.</P>
<P><A href="http://www.raibledesigns.com/struts/"><B>Struts-example modified for iPlanet Application Server SP2</B></A> by Matt Raible.</P>
<P><A href="http://www.newparticles.com/struts/"><B>The Struts Framework</B></A> by Steve Wilkinson - Excerpt from latest Wrox Professional JSP book.</P>
<P><A href="http://husted.com/struts/resources/struts-simple.zip"><B>Struts-Simple</B></A> by Ted Husted - (WAR file zipped for download) A simple skeleton application outlining the files needs to input and re-display data. Now also demonstrates using "nested" beans.</P>
<P><A href="http://mycart.cjb.net/"><B>myCart</B></A> - Example Shopping Cart application using Struts - joint project with several contributors.</P>
<P><A href="http://www.oakgrovesoftware.com/~rbackhouse"><B>Sample hdml/wireless based struts application</B></A> by Richard Backhouse.</P>
<P><A href="http://husted.com/struts/resources/struts-logon.zip"><B>Struts Login</B></A> (WAR file zipped for download) by Ted Husted - A minimalist Struts application demonstrating form validation and tracking users with a session attribute (WAR file).</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=tutorials></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Tutorials</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://husted.com/struts/resources/fb-auth.htm"><B>How To: (Form-Based Authentication) use the form-error page to login</B></A> by Matt Raible.</P>
<P><A href="http://www.redbooks.ibm.com/redpieces/pdfs/sg246134.pdf"><B>WebSphere 4 Application Development Handbook</B></A> - IBM "Redbook" - See "Designing with Frameworks (Chapter 7).</P>
<P><A href="http://husted.com/about/scaffolding/catalog.htm"><B>Struts Catalog</B></A> by Ted Husted - Overview of Struts Design Patterns and Strategies.</P>
<P><A href="http://home.iprimus.com.au/moktc/howto/struts/howto_forte_struts.htm"><B>HOWTO Setup and Debug STRUTS Example in Forte</B></A> by Michael Mok.</P>
<P><A href="http://www.netstore.ch/mesi/strutsTutorial/"><B>JBuilder 5, Struts 1.0 &amp; WebLogic 6.0, a Tutorial</B></A> by Markus Colombo.</P>
<P><A href="http://www1.tramsasp.com/?section=dev"><B>Using JBuilder5 with Struts 1.0 Release</B></A> by Anthony Martin.</P>
<P><A href="http://www.borland.com/conf2001/updates/"><B>3148 Configuring AppServer to Work with Struts</B></A> by Ken Sipe (7/25/2001)</P>
<P><A href="http://www.borland.com/conf2001/updates/"><B>3004 Building Extensible Web Frameworks Using XML, XSL-T, and Java</B></A> by Richard Vowles 7/21/2001</P>
<P><A href="http://husted.com/about/scaffolding/strutByStrut.htm"><B>Strut by Strut</B></A> by Ted Husted - Building a web application from the ground up (maintenance release 2001/Aug/19).</P>
<P><A href="http://ioctl.org/doc/j2ee-tutorial/doc/JSPTags3.html"><B>J2EE Tutorial</B></A> - Early Release chapter featuring Struts 1.0 tags.</P>
<P><A href="http://developer.bluestone.com/scripts/SaISAPI.dll/Gallery.class/demos/trailMaps/index.jsp"><B>Welcome to the Struts Framework</B></A> by <A href="http://www.bluestone.com/">Bluestone Software</A>.</P>
<P><A href="http://www.jspinsider.com/tutorials/jsp/struts/strutsintro.view"><B>An Introduction to Struts</B></A> by Casey Kochmer.</P>
<P><A href="http://husted.com/struts/resources/uml-jps.pdf"><B>Struts UML Diagrams</B></A> (PDF) by Jean-Pierre Schnyder.</P>
<P><A href="http://husted.com/struts/resources/example-spec.html"><B>Blueprinting a Struts Application</B></A> by Ted Husted - Sample specification and API for the Struts Example application.</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=seminars></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Seminars</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://www.basebean.com/"><B>Fast Track to MVC Frameworks</B></A> - 2001-Dec-2.</P>
<P><A href="http://bravepoint.com/scripts/wsisa.dll/WService=training/training_course.html?courseid=354"><B>BravePoint - Advanced JSP Architecture for J2EE</B></A> - 2001-11-19, 2001-12-10.</P>
<P><A href="http://www.avantsoft.com/jsp.html"><B>AvantSoft Inc. - JSP, Servlets and Struts</B></A></P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=articles></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Articles</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://www.informit.com/content/index.asp?product_id={0917F29F-56D8-4B25-9C67-211EC945BBAB}"><B>The Struts Framework's Action Mappings Configuration File</B></A> by Wellington L.S. da Silva</P>
<P><A href="http://husted.com/struts/resources/web_dev_products.htm"><B>Web Development Products Spreadsheet</B> </A>by Dan Cancro.</P>
<P><A href="http://www.javadude.com/articles/layering.html"><B>Layering Applications</B></A> by Scott Stanchfield.</P>
<P><A href="http://www.sys-con.com/java/article.cfm?id=1175"><B>MVC and Struts</B></A> by Steven Sweeting, Clive Jones, and Aaron Rustad.</P>
<P><A href="http://www.onjava.com/pub/a/onjava/2001/09/11/jsp_servlets.html"><B>Introduction to Jakarta Struts Framework</B></A> by Sue Spielman.</P>
<P><A href="http://www.informit.com/content/index.asp?product_id={0917F29F-56D8-4B25-9C67-211EC945BBAB}"><B>The Struts Framework's Action Mappings Configuration File</B></A> by Wellington L.S. da Silva</P>
<P><A href="http://husted.com/struts/resources/performant.htm"><B>Is Struts Performant?</B></A> by Ted Husted -- An analysis of framework components, and how they contribute to overall efficiency.</P>
<P><A href="http://husted.com/struts/resources/strutsforeveryone.zip"><B>Struts for Everyone</B></A> by Jonathan Asbell -- Word document zipped for download. Early release: still in working draft form.</P>
<P><A href="http://husted.com/struts/resources/1291-authentication.zip"><B>Approaches to User Authentication and Access Control in Web Applications</B></A> by Craig McClanahan. Slides from the JavaOne BOF (June 2001 #1291). Star Office Format. Zipped for download.</P>
<P><B>Support your application development with Struts</B> [404] by McClanahan, McCay, and Bergenholtz.</P>
<P><A href="http://www.computer-programmer.org/articles/struts/"><B>Introduction to MVC and the Jakarta Struts Framework</B></A> by <A href="mailto:craiger@tataryn.net">Craig Tataryn</A>.</P>
<P><A href="http://husted.com/struts/resources/kickstart.html"><B>Kickstart</B></A><B> </B>- The obligatory Struts Q&amp;A.</P>
<P><A href="http://www-106.ibm.com/developerworks/library/j-struts/?n-j-2151"><B>Struts, an open-source MVC implementation</B></A> by <A href="mailto:malcolm@nuearth.com">Malcom Davis</A>.</P>
<P><A href="http://www.javaworld.com/javaworld/jw-12-2000/jw-1201-struts.html"><B>Strut Your Stuff With JSP Tags</B></A>, by <A href="mailto:Thor.Kristmundsson@javaworld.com">Thor Kristmundsson</A>.</P>
<P><A href="http://informit.com/books/authors/author_template/index.asp?authorid={A08A00B0-71BB-42DB-9B29-08879A9A7ABE}&amp;t={94AE5B48-1D7D-462A-A4A6-83CE19EC0705}&amp;n={4641FAF9-E21F-4902-8F6E-0C8FAF114C62}"><B>Using the Struts Framework to Develop a Message Board</B></A> by Maneesh Sahu (article requires registration with informit.com).</P>
<P><A href="http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-jspweb_p.html"><B>JSP templates</B></A> by <A href="mailto:david.geary@javaworld.com">David Geary</A>.</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=books></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Books</STRONG></FONT></TD></TR>
<TR>
<TD>
<UL>
<LI><A href="http://www.amazon.com/exec/obidos/ISBN=1861005512/hitchhikeguidetoA/"><B>Professional JSP Site Design</B></A> - Wrox book - Features Struts throughout. 
<LI><A href="http://www.amazon.com/exec/obidos/ISBN=0735710953/hitchhikeguidetoA/"><B>JSP and Tag Libraries for Web Development </B></A>- by Wellington L. S. Da Silva. Several chapters regarding Struts. 
<LI><A href="http://www.redbooks.ibm.com/redpieces/pdfs/sg246134.pdf"><B>Websphere Version 4 Application Development Handbook</B></A> <FONT size=1>(PDF)</FONT> - Chapter 7 covers designing with both the Struts and Websphere frameworks, 
<LI><A href="http://shannon.informatik.fh-wiesbaden.de/jsp/index.html"><B>Java Server Pages and J2EE Web-based Applications for Enterprises</B></A> - In German, with a Chapter regarding MVC and Struts. 
<LI><A href="http://www.amazon.com/exec/obidos/ISBN=0130648841/hitchhikeguidetoA/"><B>Core J2EE Patterns</B></A> - Many of these patterns are deployed in Struts. 
<LI><A href="http://www.amazon.com/exec/obidos/ISBN=1861004958/hitchhikeguidetoA/"><B>Professional JSP 2nd Edition</B></A> - Wrox book - long chapter on Struts. 
<LI><A href="http://www.amazon.com/exec/obidos/ISBN=0130307041/hitchhikeguidetoA/"><B>Advanced JavaServer Pages</B></A> by David Geary - features template tag library from Struts 1.0 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=apis></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Selected APIs, RFCs, and JSRs</STRONG></FONT></TD></TR>
<TR>
<TD>
<UL>
<LI><A href="http://java.sun.com/products/servlet/download.html">Servlet API</A> 
<LI><A href="http://java.sun.com/products/jsp/technical.html">JavaServer Pages</A> 
<UL>
<LI><A href="http://java.sun.com/products/jsp/technical.html">JSP Tag Libraries</A> 
<UL>
<LI><A href="http://jakarta.apache.org/taglibs/doc/jsptl-doc/intro.html">JavaServer Pages Standard Tag Library (JSPTL) Early Release</A> </LI></UL></LI></UL></LI></UL>
<UL>
<LI><A href="http://java.sun.com/products/javabeans/docs/">JavaBeans</A> 
<LI><A href="http://java.sun.com/j2se/1.3/docs/guide/jdbc/index.html">JDBC API Documentation</A> 
<LI><A href="http://java.sun.com/j2ee/blueprints/">Java2 Enterprise Edition (J2EE)</A> 
<LI><A href="http://java.sun.com/products/jaas/index-10.html">Java Authentication and Authorization Service</A> (JAAS) </LI></UL>
<UL>
<LI><A href="http://www.w3.org/MarkUp/">HyperText Markup Language</A> (w3c) 
<UL>
<LI><A href="http://www.w3.org/TR/html4/">HTML 4.01 Specification</A> </LI></UL></LI></UL>
<UL>
<LI><A href="http://www.ietf.org/rfc/rfc2396.txt">Uniform Resource Identifiers (URI): Generic Syntax</A> 
<UL>
<LI><A href="http://www.w3.org/Addressing/#9808uri">Naming and Addressing: URIs, URLs, ...</A> </LI></UL>
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2616.txt">Hypertext Transfer Protocol -- HTTP/1.1</A> 
<UL>
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2617.txt">HTTP Authentication: Basic and Digest Access Authentication</A> 
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2660.txt">The Secure HyperText Transfer Protocol</A> 
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2936.txt">HTTP MIME Type Handler Detection</A> 
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2854.txt">The 'text/html' Media Type</A> 
<LI><A href="ftp://ftp.isi.edu/in-notes/rfc2518.txt">HTTP Extensions for Distributed Authoring -- WEBDAV</A> 
<UL>
<LI><A href="http://www.ics.uci.edu/pub/ietf/webdav/intro/webdav_intro.pdf">WebDAV: IETF Standard for Collaborative Authoring on the Web</A> </LI></UL></LI></UL>
<LI><A href="http://www.rfc-editor.org/"><B>RFC Editor (index)</B></A> </LI></UL>
<UL>
<LI><A href="http://www.jcp.org/jsr/detail/52.jsp">Standard Tag Library for JavaServer Pages</A> 
<LI><A href="http://jcp.org/jsr/detail/127.jsp">Java Faces</A> 
<LI><A href="http://jcp.org/jsr/overview/index.jsp"><B>JSR Index</B></A> </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=other></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Other Resource Pages</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://www.jguru.com/faq/home.jsp?topic=Struts"><B>JGuru FAQ</B></A></P>
<P><A href="http://husted.com/struts/"><B>More About Struts</B></A> by <A href="mailto:support@husted.com">Husted dot Com</A>.</P>
<P><A href="http://habweb.de/struts/"><B>German Translation of Users Guide</B></A> by Hartmut Bernecker.</P>
<P><A href="http://java.sun.com/docs/books/tutorial/"><B>Javasoft Tutorials</B></A></P>
<P><A href="http://archives.java.sun.com/"><B>Javasoft Mailing Lists</B></A></P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=archives></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Mailing List Archives</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><A href="http://mail-archive.com/"><B>mail-archive.com</B></A>.</P>
<P><B><A href="http://husted.com/struts/FAQ/">Struts FAQ with Mailing List Threads</A> - </B>Clippings from the User Lists</P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=powered></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Powered by Struts</STRONG></FONT></TD></TR>
<TR>
<TD>
<UL>
<LI><A href="http://www.application-servers.com/"><B>Application-Servers.com</B></A> - French site. 
<LI><A href="http://www.clickstarttutoring.com/index.jsp"><B>Clickstart Tutoring</B></A> - One on one in home tutoring. 
<LI><A href="http://dbforms.org/"><B>dbForms</B></A> - RAD framework for database applications. 
<LI><A href="http://www.e-involve.com/"><B>E-Involve</B></A> 
<LI><A href="http://adminweb.enitel.no/login.jsp"><B>Enitel</B></A> - French site. 
<LI><A href="http://www.hallmarkstories.com/"><B>Hallmark Stories</B></A> - "Tell the story behind your photos". 
<LI><A href="http://www.iknowbase.com/"><B>iKnowBase</B></A> - The Knowledge Engine. 
<LI><A href="http://ironmax.com/"><B>IronMax</B></A> - B2B site; see Equipment Information Products. 
<LI><A href="http://www.ipipi.com/index.jsp"><B>IPIPI</B></A> - e-Mail to SMS delivery service. 
<LI><A href="http://www.jcorporate.com/"><B>Jcorporate.com</B></A> - open source and shared source commercial applications. 
<LI><A href="http://get2hawaii.com/"><B>Get To Hawaii</B></A> - B2B Travel Service Provider 
<LI><A href="http://www.newdawnart.com/"><B>New Dawn Art</B></A> - Social and spiritual art on the Internet. 
<LI><A href="http://www.webappcabaret.com/normad"><B>Normad</B></A> - Web Timesheet Management System. 
<LI><A href="https://www.organox.com.br/"><B>Organonx</B></A> 
<LI><A href="http://www.pizzahut.com.au/"><B>Pizza Hut Online / Sydney Metro</B></A> - For pickup or delivery in the Syndey Metro area. 
<LI><B>Povoglie</B> [403] - Goverment regional press services news center in Russia, middle Volga. 
<LI><A href="http://www.ipayment.co.za/"><B>South African Revenue Services</B></A> - Directive and certificate service. 
<LI><A href="http://www.redgalleon.com/"><B>Red Galleon</B></A> - Offer aggregator. 
<LI><A href="http://www.webappcabaret.com/teatimej/"><B>TeaTimeJ</B></A> - Website and Java hosting. 
<LI><A href="http://wxxi.org/"><B>WXXI Spring MarketPlace 2001</B></A> - Online auction for Public Television station. </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=hosts></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Java / Struts ISPs</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>Provided as a reference only. No endorsements given or implied. To be listed, post a documentation enhancement request in Bugzilla.</P>
<UL>
<LI><A href="http://www.aoindustries.com/servlet/com.aoindustries.website.HomePage"><B>AO Industries</B></A> 
<LI><A href="http://www.hostjsp.com/"><B>host<FONT size=-1>JSP</FONT>.com</B></A> 
<LI><A href="http://www.imagineis.com/"><B>Imagine Internet Services</B></A> 
<LI><A href="http://www.infinitehost.com/"><B>Infinite Host</B></A> 
<LI><A href="http://www.irdesign.com/services/hosting/website_hosting.html"><B>irdesign.com</B></A> 
<LI><A href="http://www.mmaweb.net/"><B>mma</B></A> 
<LI><A href="http://www.servlets.net/index.html"><B>servlets.com</B></A> 
<LI><A href="http://www.webappcabaret.com/"><B>Web App Cabaret</B></A> </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=consultants></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>Consultants</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>Provided as a reference only. No endorsements given or implied. To be listed, post a documentation enhancement request in Bugzilla.</P>
<UL>
<LI><B>AccessData</B> - <A href="http://www.accessdc.com/">www.accessdc.com</A> - <A href="mailto:cassenza@Accessdc.com">Chris Assenza</A>. 
<LI><B>Bravepoint</B> - <A href="http://www.bravepoint.com/">www.bravepoint.com</A> - <A href="mailto:struts@bravepoint.com">Struts Info</A>. 
<LI><B>Creatrix</B> - <A href="http://www.creatrixs.com/">www.creatrixs.com</A> - <A href="mailto:sami.elhini@creatrixs.com">sami.elhini@creatrixs.com</A>. 
<LI><B>eBlox</B> - <A href="http://www.eblox.com/">www.eblox.com</A> - <A href="mailto:andrewb@eblox.com">andrewb@eblox.com</A>. 
<LI><B>Husted dot Com</B> - <A href="http://husted.com/">www.husted.com</A> - <A href="mailto:ted@husted.com">Ted Husted</A>. 
<LI><FONT size=1><B>JATEC AG</B></FONT> - <A href="http://www.jatec.ch/">www.jatec.ch</A> - <A href="mailto:sascha.urfer@jatec.net">Sascha Urfer</A>. 
<LI><B>jCorporate</B> - <A href="http://www.jcorporate.com/">jcorporate.com</A> - <A href="mailto:scann@jcorporate.com">Sandra Cann</A>. 
<LI><B>Kambrium.net Technologies</B> - <A href="http://www.kambrium.net/"></A><A href="http://www.kambrium.net/">kambrium.net</A> - <A href="mailto:struts@kambrium.net">Dirk Gabler</A>. 
<LI><B>Living Logic</B> - <A href="http://www.livinglogic.de/">www.livinglogic.de</A> - <A href="mailto:matthias.bauer@livinglogic.de">Matthias Bauer</A>. 
<LI><B>Multitask Consulting</B> - <A href="http://www.multitask.com.au/">www.multitask.com.au</A> - <A href="file:///D:/DOWNLOAD/2004822203916/struts/dion@multitask.com.au">dIon Gillard</A><A href="file:///D:/DOWNLOAD/2004822203916/struts/dion@multitask.com.au">.</A> 
<LI><B>New Particles</B> - <A href="http://www.newparticles.com/struts">www.newparticles.com/struts</A> - <A href="mailto:steve@newparticles.com">Steve Wilkinson</A>. 
<LI><B>Raible Designs</B> - <A href="http://www.raibledesigns.com/">www.raibledesigns.com</A> - <A href="mailto:matt_raible@yahoo.com">Matt Raible</A>. 
<LI><B>Shared Skills Ltd (UK)</B> - <A href="http://www.sharedskills.com/">www.sharedskills.com</A> - <A href="mailto:mike.way@sharedskills.com">Mike Way</A>. 
<LI><B>SoftwareMentor</B> - <A href="http://softwarementor.com/">softwareMentor.com</A> - <A href="mailto:tim@softwareMentor.com">Tim Biernat</A>. 
<LI><B>Solution Array</B> - <A href="http://www.solutionarray.com/">www.solutionarray.com</A> - <A href="mailto:chkmiec@hotmail.com">Chris Kmiec</A>. 
<LI><B>Stonebridge Technology</B> - <A href="http://www.sbti.com/">www.sbti.com</A> - <A href="mailto:john.thomas@sbti.com">John J. Thomas</A>. 
<LI><B>Tallan</B> - <A href="http://www.tallan.com/">www.tallan.com</A> - <A href="mailto:michael.grassotti@tallan.com">Michael Grassotti</A>. 
<LI><B>Thalles Information Services</B> - <A href="http://www.thales-is.ch/">www.thales-is.ch</A> - <A href="mailto:markus.colombo@thales-is.ch">Markus Collumbo</A>. 
<LI><B>U</B><B>pco</B> -<A href="http://www.upco.co.uk/">upco.co.uk</A> - <A href="mailto:Jon.Ridgway@upco.co.uk">Jon Ridgeway</A>. 
<LI><B>viadee <FONT size=1>UNTERNEHMENSBERATUNG GmbH</FONT></B> - <A href="http://www.viadee.de/">www.viadee.de</A> - <A href="mailto:friedrich.budde@viadee.de">Frido Budde</A>. </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/10014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-13 03:57 <a href="http://www.blogjava.net/RR00/articles/10014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1. 简介</title><link>http://www.blogjava.net/RR00/articles/10013.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 12 Aug 2005 19:51:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/10013.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/10013.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/10013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/10013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/10013.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1. 简介</STRONG></FONT></TD></TR></TBODY></TABLE><A name=prereqs></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.0 先决条件</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>这份用户指南是为那些活跃的Web开发者编写的，假设读者已经了解java Web application是如何工作的。在开始之前，您应该已经掌握下列基本核心技术。 </P>
<UL>
<LI><B>HTTP Request/Response 结构.</B><BR>正式的文档在这里<A href="http://www.ietf.org/rfc/rfc2616.txt?number=2616">RFC 2616 - Hypertext Transfer Protocol (HTTP/1.1)</A>. 
<LI><B>Java Servlets</B>.<BR>开始学习的一个好地方是 <A href="http://java.sun.com/products/jsp/product.html">Sun Servlet product page</A> 和 <A href="http://java.sun.com/docs/books/tutorial/">Sun Java Tutorials</A>. 
<LI><B>JavaServer Pages (JSP)</B>.<BR>类似的，一个开始学习的好地方是 <A href="http://java.sun.com/products/jsp/product.html">Sun JSP product page</A> 和<A href="http://java.sun.com/docs/books/tutorial/">Sun Java Tutorials</A>. 
<LI><B>JavaBeans</B>.<BR>很多Struts的类被编写成为Javabeans.如果您没有接触过Javabeans,参阅 <A href="http://java.sun.com/products/javabeans/">Sun JavaBean product page</A> 和 <A href="http://java.sun.com/docs/books/tutorial/">Sun Java Tutorials</A> </LI></UL>
<P>如果您在其他平台上开发过web applications,您也许可以继续。在需要的时候参考以上的资料。他们几乎是所有Java web开发项目需要用到的核心技术。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=preface></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.1 前言 ：回到从前！（也是Struts的简史）</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>当java servlets被发明出来的时候，很多程序员迅速意识到这是一个好东西。它比标准CGI快速强大，可以移植，并且几乎可以无限扩展。 </P>
<P>但是无穷无尽的编写 println()语句来吧HTML送到浏览器是浪费时间并且容易造成问题。答案就是JavaServer Pages,它把编写servlet的任务倒了个个儿。现在开发者可以很容易的把HTML和Java代码混合起来，并且仍然拥有servlet的所有好处。只有天空才会限制（我们）！ </P>
<P>Java web程序很快变成了以JSP为中心的。关于(JSP)本身并不是一件坏事，但是它并没有解决流程控制和web application的其他一些问题 </P>
<P>显然，我们需要另一个模型...</P>
<P>很多聪明的程序员认识到JSP和servlets可以被<B>一起</B>使用来构造web程序。Servlets可以用来辅助流程控制，JSP主要关注于实现那些凌乱的HTML.在这样的过程中，一起使用JSP和servlet开始被称为Model 2.(同时只使用JSP被称为Model 1)。 </P>
<P>当然，天底下没有新东西...很快很多人指出JSP的Model 2 遵循SmallTalk的经典的Model-View-controller设计模式。现在术语Model 2和MVC可以互相替代。 </P>
<P>Struts工程于2000年5月由Craig R. McClanahan开始动工，来为Java社区实现一个标准的MVC框架。2001年6月，Struts 1.0发布了。从此，Model 2开发开始变得不同。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=mvc></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.2 Model-View-Controller ('MVC') 设计模式</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>在MVC设计模式中，程序流程由一个的Controller(控制器)居中斡旋。Controller委派请求--在我们的情形中,HTTP请求--到合适的handle（处理程序）去。Handle和Model（模型）相联系，每一个handle的作用就是成为在请求和Model之间的适配器(adaptor有一个意思是电源插头--译者注)。Model 代表或者封装了一个程序的商业逻辑或者状态。通常控制由Controller重新转移到对应的View去。这个转移由一系列的映射决定，一般从数据库或者配置文件中取得。这样就为View和Model提供了一个松散的联系，编写和维护程序变得显而易见的的容易。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=overview></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.3 Struts 框架纵览</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>忠实的和Model-View-Controller设计模式对应，Struts程序有三个主要的部件：一个Servlet Controller,它由Struts本身提供,JSP 页面("view"),还有程序的商业逻辑("model").我们来看看他们是怎么组合到一起的。 </P>
<P>Struts的Controller servlet把HTTP 请求打包并传送到框架中的其他对象，包括JavaServer Pages和由Struts开发者编写的<CODE>org.apache.struts.action.Action</CODE>的子类。当(系统)初始化的时候，Controller 解释一个配置资源文件。这个文件定义了(和其他配置一起)这个程序的<CODE>org.apache.struts.action.ActionMapping</CODE>。Controller用这些映射来把HTTP 请求转换为程序的actions(动作)。 </P>
<P>一个ActionMapping通常会指出:</P>
<UL>
<LI><B>一个request请求的路径</B> (简称 "URI"), 
<LI>用于处理请求的<B>object type（对象）</B> (Action 的子类), 
<LI>和其他一些必要的属性。 </LI></UL>
<P>Action 对象可以处理请求并响应客户端(通常是一个web browser),或者指出流程应该被指向另一个地方。例如，如果登录成功，一个login Action可能希望把流程转移到主菜单。 </P>
<P>Action对象可以操作程序的Controller servlet,所以可以操作这个Controller的方法。当转发控制的时候，一个Action对象可以不直接的转发一个或多个共享对象，包括JavaBeans,这个过程是通过把它们放到Java servlet共享的某一个标准collection对象里去。 </P>
<P>Action对象可以创建一个购物车Bean，在购物车里面加上一个条目，把这个bean放到session 结构里去，然后把控制转发到另一个映射。那个映射会使用一个JavaServer Page来显示用户的购物车里的内容。因为每个用户都有他自己的session,他们也会有自己的购物车。在一个Struts程序里，大部分商业逻辑都可以由JavaBeans表示。一个Action可以调用一个JavaBean的属性，不需要知道她实际上是如何工作的。这封装了 商业逻辑，所以Action可以专注于错误处理和如何转发控制。 </P>
<P>JavaBeans也可以用来管理输入的Forms.设计一个web程序的主要问题是得到并检查用户在请求中的输入。通过Struts,你可以 定义你自己的Form Bean 类集合，他们都是<CODE>org.apache.struts.action.ActionForm</CODE>的子类，并很容易的把用户form（这里是指HTTP form--译者注）输入的内容放到这些Form bean里去。这个bean被存放到一个标准的共享上下文集合里去，所以另一个对象可以使用它，特别是指一个Action对象。 （我的理解，使用ActionForm是因为这样可以标准化的检查Form里的值，也可以标准化的调用Action--译者注。） </P>
<P>Form bean可以被一个JSP使用来从用户收集数据...通过一个Action 对象来检查用户输入的数据...然后再通过JSP来重新显示form的字段。如果检查错误，Struts由一个公用的机制来提交和显示错误信息。 </P>
<P>Struts 的Form bean在配置文件中声明，在一个Java文件中被定义，并且通过一个通用的属性名字来连接到一个ActionMapping去。当一个请求 调用一个需要FormBean 的Action时候，Controller servlet要么从输入中获取form bean,要么自己构造一个form bean,把它传递到Action对象去。Action 对象可以在显示之前检查form bean的内容，也可以为要在form里显示的内容排队。准备好之后，Action对象返回控制权并转移到它的输入叶面去。controller就可以响应HTTP请求，并重定向到JavaServer Page去。 </P>
<P>Struts 框架包括自定义的Tag来自动从一个formBean填充子段。JavaServer Page唯一需要知道的是确切的字段名和下一步提交form到何处。一些部件例如被Action排队的消息可以在一个自定义tag就被输 出。也可以定制其他为程序定制的tag来从jsp中隐藏实现细节。 </P>
<P>在Struts框架中的自定义tag被设计为使用Java平台内置的国际化特性。所有的字段名和消息都可以从消息资源中获取，并且Java可以自动为一个客户端的国家和语言提供想对应的资源。为了提供另一种语言的支持，只需简单的的增加另一个资源文件。 </P>
<P>除了国际化之外，这个进步的好处还在于在不同的form中保持一样的标签名字，也可以全局化的复查所有的标签和消息。 </P>
<P>对于最简单的程序来说，有时候一个Action对象可以处理一个请求对应的商业逻辑。<B>但是，在大多数情况下，一个Action对 象应该调用另一个对象，一般是一个JavaBean来处理实际的业务逻辑。</B>这让Action专注于错误处理和流程控制，而非商业逻 辑。为了在其他平台上重用，商业逻辑JavaBean不应该引用任何web程序的对象。Action对象应该从HTTP请求翻译必要的细节并 象普通的java变量一样传递到商业逻辑对象去。 </P>
<P>举个例子，在一个数据库程序中： </P>
<UL>
<LI>一个商业逻辑bean会连接到数据库并进行查询, 
<LI>商业逻辑bean把结果传递到Action, 
<LI>Action把结果保存在一个form bean中，放置到request中去, 
<LI>JavaServer Page把结果显示到一个HTML Form中去。 </LI></UL>
<P>不管是Action还是JSP都不需要知道结果是从哪儿来的。他们只需要知道如何打包和显示结果。 </P>
<P>用户指南的其它部分非常详细的解释了Struts的不同部件。Struts发布版本也包含了一些开发者手册包含几个不同的主题，也包括例子程序，标准的Javadoc API,当然还有全部的源代码！ </P>
<P>Struts 在Apache软件基金会协议下发布。代码拥有版权，但是可以在任何程序中自由的使用。参阅<A href="http://www.apache.org/LICENSE-1.1">ASF license</A> 得到详细信息. </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=modelConcepts></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.4 Model（模型）: 系统状态和商业逻辑JavaBeans</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>基于MVC的系统中的<I>Model(模型)</I>部分可以被分为两个概念，系统的内部状态和可以用来改变状态的动作。从语法上来说 ，我们可以把状态信息看成是<I>名词</I>，而动作是<I>动词</I>（用来改变状态）。 </P>
<P>一般来说，米的程序需要用一套包含一个或多个JavaBeans来表达内部状态，(这些)JavaBean包含了这个状态的详细属性。根据 你的程序的复杂程度，他们可能是自我包含的（自己知道怎么样保留持续化信息），或者仅是一个知道必要时如何从外部数据源（如数据库）获取信息的对象。Entity Enterprise JavaBeans (Entity EJBs)一般也用于表示内部状态。 </P>
<P>大型程序经常使用一些bean的方法来表示一组可能的商业逻辑，这些方法维护状态信息。例如，你可能有一个购物车Bean,保存 在每个用户的session中，包含用户当前决定购买的条目。这个bean可能有一个<CODE>checkOut()</CODE>方法来取得用户信用卡 的授权，发送订单到仓库去来发送。另一些系统可能把可能的动作单独包装，可能是一个Session Enterprise JavaBeans(Session EJBs). </P>
<P>在一些较小的程序中，相反，可能的动作会内置于<CODE>Action</CODE>类中，是Controller角色的一部分。当逻辑非常简单的 时候，或者当重用商业逻辑不是关注点的时候这是合适的。Struts框架支持任何一种模式，但是<B>强烈</B>建议把商业逻辑 （如何做）从<CODE>Action</CODE>类扮演的角色（做什么）中分开。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=presentationConcepts></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.5 View（视图）: JSP页面和表示部件</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>基于Struts程序的<I>View</I>部分基本上是由JavaServer pages(JSP)技术构成的。JSP页面可以包含静态的HTML（或者XML）文本，被称为“模版文本”，再加上在特殊的标签运行时（当页面被调用的时候）插入动态内容的能力。JSP环境包含一套标准的动作标签，比如<CODE>&lt;jsp:useBean&gt;</CODE>他们的 用处在<A href="http://java.sun.com/products/jsp/download.html">JavaServer Pages Specification</A>描述了。另外，还有一种标准的方法来定义你自己的标签，他们被组织在“自定义标签库”里。 </P>
<P>Struts包含了一个内容广泛的自定义标签库，用以帮助编写完全国际化的用户界面。它也和处于<I>Model</I>部分的<CODE>ActionForm</CODE>高度互动。关于使用这些标签的方法在后面会详细讨论。 </P>
<P>除了JSP 页面和原有的以及自定义的标签之外，有时候让商业逻辑对象拥有把他们自己根据当前的状态渲染成HTML（或者XML）的能力也 是经常需要的。这些被渲染出来的输出可以很容易的在一个结果JSP文件里面用<CODE>&lt;jsp:include&gt;</CODE>标准动作标 签引用。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=controllerConcepts></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>1.6 Controller（控制器）: ActionServlet 和 ActionMapping</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>程序的<I>Controller（控制器）</I>部分关注于从客户端接收请求（通常是一个使用浏览器的用户），决定那个商业逻辑方法应该被执行，然后分配任务给到一个合适的view组件来制造下一步的用户界面。在Struts里面，Controller的主要部分是一个servlet,它是<CODE>ActionServlet</CODE>.这个servlet用一组<CODE>ActionMappings</CODE>来配置，一个ActionMapping定义了一个<CODE>path（路径）</CODE>，它和用户请求的URI对应，一般会指定一个完整的Action类的类名。所有的Action类都是<CODE>org.apache.struts.action.Action</CODE>的子类。Action封装了商业逻辑，组装结果，并且最终分配控制权到合适的View部件来创建结果。 </P>
<P>Struts也支持在<CODE>ActionMapping</CODE>中使用除了标准的框架所需之外附加的属性。这样允许你保存你的程序所特定的附加信息。除此之外，Struts还允许你定义控制转移的逻辑“名字”，这样一个Action方法可以要求“主菜单”（举例）而不需要知道对应的JSP页面的实际名字。这个功能很大的帮助你把控制逻辑(做什么）和表示逻辑(如何显示)分开。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/10013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-13 03:51 <a href="http://www.blogjava.net/RR00/articles/10013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3. 构造 View （视图）部件 </title><link>http://www.blogjava.net/RR00/articles/10012.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 12 Aug 2005 19:46:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/10012.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/10012.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/10012.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/10012.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/10012.html</trackback:ping><description><![CDATA[<A name=overview></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.1 纵览</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>这一章关注构造程序的View(视图)部件的任务，主要是由JavaServer Pages(JSP)技术完成的。特别的，Struts提供对编写国际化程序的支持，同时也支持和(用户)输入的Form交互。其他几个和View(视图)有关的主题也会被简要的涉及。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=i18n></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.2 Internationalized Messages</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>几年前，程序开发者们只期望支持他们自己国家的国民，只使用一种（有时候是两种）语言，也只有一种表达日期，数字，钱币的格式。然而，基于Web技术的,在internet和其他一些可以被广泛访问的网络上的程序开发有了爆炸性的增长，让国界问题浮现在我们的眼中。这个问题被理解为对于支持<I>国际化</I>(经常被称为i18n,因为在"国际化"一词internationalization中i和n之间有18个字母)和<I>本地化</I>程序的需要。 </P>
<P>Struts 在Java平台上编写，可以辅助支持编写国际化和本地化的程序。需要熟悉的概念有： </P>
<UL>
<LI><B>Locale (国籍,地区)</B> - 支持国际化的最基本的Java类是<CODE>java.util.Locale</CODE>。每一个<CODE>Locale</CODE>表示一个特定的国家和语言(包括一种可选的不同语言),和一套对于数字，日期之类的字符串的格式化方案。 
<LI><B>ResourceBundle (资源包)</B> - <CODE>java.util.ResourceBundle</CODE>类提供了支持不同语言的信息的基本支持。参阅<CODE>ResourceBundle</CODE>的Javadoc和在你的JDK版本中的国际化支持的信息来得到进一步的帮助。 
<LI><B>PropertyResourceBundle (属性资源包)</B> - 一个<CODE>ResourceBundle</CODE>的标准实现，它允许你用和properties文件一样的"name=value"的格式来定义资源。这对于在web程序中准备信息资源宝石很方便的，因为大部分的信息都是文本。 
<LI><B>MessageFormat (信息格式)</B> - <CODE>java.text.MessageFormat</CODE> 类允许你在运行时用参数的方式替代一个信息字符串（在这种情况下，是从reousece bundle中取出的）。有时候你要编写一个句子，但是在不同的语言中词语出现的顺序不一样，这就很有用了。字符串中的占位符<CODE>{0}</CODE>会被第一个运行时参数取代，<CODE>{1}</CODE>会被第二个取代，其它的也是这样。 
<LI><B>MessageResources (信息资源）</B> - Struts类<CODE><A href="file:///D:/DOWNLOAD/2004822203916/struts/api/org/apache/struts/util/MessageResources.html">org.apache.struts.util.MessageResources</A></CODE>让你把一套resource bundle当成数据库，允许你得到某种特定的Locale（一般是当前用户的Locale）中的特定信息字符串，而非服务器自己正在使用的Locale。 </LI></UL>
<P>请注意在一个Struts之类的框架中i18n的支持只限于<B>显示</B>国际化的字符串和图像给用户。支持地区相关的<B>输入法</B>(在日语，中文，或者韩文之类的语言中使用)被留给客户端设备，一般是一个web浏览器。 </P>
<P>对于一个国际化程序来说，请遵循JDK中附带的国际化文档中描述的步骤来为你的平台创建每一种语言的properties文件。下面的例子更深入的说明这一点： </P>
<P>假设你的源代码位于<CODE>com.mycompany.mypackage</CODE>包,所以它保存在<CODE>com/mycompany/mypackage</CODE>目录中（相对于你的源代码目录）。要创建一个名为<CODE>com.mycompany.mypackage.MyResources</CODE>的资源包，你应该在<CODE>com/mycompany/mypackage</CODE>下创建下列文件: </P>
<UL>
<LI><B>MyResources.properties</B> - 包含了使用你的服务器所在的语言的文本。如果你的默认语言是英语，你可能会有如下的条目： <CODE>prompt.hello=Hello</CODE> 
<LI><B>MyResources_xx.properties</B> - 包含了ISO代码为"xx"的语言的文本（参阅ResourceBundle的Javadoc得到最新的代码列表）。对于一个上面所示文本的法语版本，你可能会有如下的条目： <CODE>prompt.hello=Bonjour</CODE> 你可以编写所以你愿意支持的语言的资源包。 </LI></UL>
<P>当你配置你web程序中controller servlet的发布描述时，你需要定义的一个国际化参数是程序的基本资源包的名字。在我们上面举的例子中，它就是<CODE>com.mycompany.mypackage.MyResources</CODE>。 </P><PRE>&lt;servlet&gt;
  &lt;servlet-name&gt;action&lt;/servlet-name&gt;
  &lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;
  &lt;init-param&gt;
    &lt;param-name&gt;application&lt;/param-name&gt;
    &lt;param-value&gt;com.mycompany.mypackage.MyResources&lt;/param-value&gt;
  &lt;/init-param&gt;
  &lt;.../&gt;
&lt;/servlet&gt;
</PRE>
<P>一件重要的事情是要让你的资源包在你程序可以访问的class path中。另一个方法是把<CODE>MyResources.properties</CODE>放在你的程序的<CODE>classes</CODE>目录下，你就可以简单的用“myResource”作为程序的值。但是要注意如果你的编译脚本为了保证一个“干净”的编译目标，会删除整个classes目录，这时要保证这个资源文件不被删除。 </P>
<P>如果是这种情形，这儿有一段Ant任务可以包含在你的编译脚本中，它把<CODE>src/conf</CODE>目录中的内容拷贝到<CODE>classes</CODE>目录去。 </P><PRE>        &lt;!-- Copy any configuration files --&gt;
        &lt;copy todir="classes"&gt;
            &lt;fileset dir="src/conf"/&gt;
        &lt;/copy&gt;
       </PRE>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=form_beans></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.3 Forms 和 FormBean 的交互</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>以前，大多数web开发者使用标准的HTML能力来编写Forms,比如使用<CODE>&lt;input&gt;</CODE>标签。用户希望和程序互动，产生某种特定的行为，其中之一和错误处理有关——如果用户犯了个错误，程序应该允许他们改正需要改正的地方——而非重新填写页面上所有的字段。 </P>
<P>使用标准的HTML和JSP页面来满足这种需求是非常繁琐和粗笨的，举个例子，一个<CODE>username</CODE>字段的输入框可能是这样的(在JSP里)： </P><PRE>&lt;input type="text" name="username"
      value="&lt;%= loginBean.getUsername() %&gt;"/&gt;
</PRE>
<P>如果HTML程序员并没有编程基础知识的话，这很难输入正确，而且也会对页面编辑者带来麻烦。基于JSP1.1中的自定义标签库，Struts为编写form提供了很大的方便，可以取代原始的方法。上面的例子用Struts来编写的话会是这样: </P><PRE>&lt;html:text property="username"/&gt;
</PRE>
<P>并不需要显式的引用一个JavaBean以取得初始值。框架自动完成这些事情。 </P>
<P>HTML form有时候被用来上传一些文件。大部分浏览器通过&lt;input type="file"&gt; 元素来支持这一点，它会显示一个浏览文件的按钮，但是（在Server端--译者注）下面就轮到开发者来处理这些(上传)来的文件了。Struts可以用和普通的form一致的方式来处理这些"multipart" form.在下一节里，我们会谈到用Struts来创建一个简单的login页面，还包括一个简单的multipart form。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=forms></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.3.1 在Struts里编写Form </STRONG></FONT></TD></TR>
<TR>
<TD>
<P>一个完整的login页面有助于展示Struts如何用比直接的HTML和标准JSP方式更轻松的方式来处理form。考虑如下的页面（基于Struts附带的示例程序），名字是<CODE>logon.jsp</CODE>: </P>
<HR>
<PRE>&lt;%@ page language="java" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-html.tld"
        prefix="html" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-bean.tld"
        prefix="bean" %&gt;
&lt;html:html&gt;
&lt;head&gt;
&lt;title&gt;
  &lt;bean:message key="logon.title"/&gt;
&lt;/title&gt;
&lt;body bgcolor="white"&gt;
&lt;html:errors/&gt;
&lt;html:form action="/logon" focus="username"&gt;
&lt;table border="0" width="100%"&gt;
  &lt;tr&gt;
    &lt;th align="right"&gt;
      &lt;html:message key="prompt.username"/&gt;
    &lt;/th&gt;
    &lt;td align="left"&gt;
      &lt;html:text property="username"
                     size="16"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th align="right"&gt;
      &lt;html:message key="prompt.password"/&gt;
    &lt;/th&gt;
    &lt;td align="left"&gt;
      &lt;html:password property="password"
                         size="16"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td align="right"&gt;
      &lt;html:submit&gt;
        &lt;bean:message key="button.submit"/&gt;
      &lt;/html:submit&gt;
    &lt;/td&gt;
    &lt;td align="right"&gt;
      &lt;html:reset&gt;
        &lt;bean:message key="button.reset"/&gt;
      &lt;/html:reset&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;/html:form&gt;
&lt;/body&gt;
&lt;/html:html&gt;
</PRE>
<HR>

<P>根据上面的例子，下面描述了Struts里form处理的关键特性: </P>
<UL>
<LI><CODE>taglib</CODE>指令告诉JSP页面编译器如何去寻找关于Struts标签库的<I>标签库描述</I>。在这里，我们用<CODE>bean</CODE>作为表示struts-bean标签库的前缀代号，而"html"是struts-html的前缀代号。你可以用任何你希望使用的前缀。 
<LI>这个页面使用了几个message 来从包含这个程序所有可用资源的<CODE>MessageResources</CODE>对象中查找国际化信息串。下列文本关键字必须在资源文件中定义，这个页面才能正常工作: 
<UL>
<LI><B>logon.title</B> - logon 页面的标题 
<LI><B>prompt.username</B> - "Username:" 询问用户名的标签 
<LI><B>prompt.password</B> - "Password:" 询问密码的标签 
<LI><B>button.submit</B> - "Submit" "提交表单"的按钮的标签 
<LI><B>button.reset</B> - "Reset" "重置"按钮的标签 </LI></UL>当用户登录的时候，程序会在用户的session中保存一个<CODE>Locale</CODE>对象。这个<CODE>Locale</CODE>对象会被用来选择合适的语言信息。这样让用户自己选择语言会变得很容易——简单的改变这个保存的<CODE>Locale</CODE>对象，所有的文本都会自动切换。 
<LI>错误标签显示任何保存在商业逻辑部件中的可能的错误信息，如果没有错误，那么就不显示。关于这个标签，下面会详细讨论。 
<LI>根据指定的属性，form标签展开为一个HTML <CODE>&lt;form&gt;</CODE>元素。它也让所有在这个form内部的字段值被存放到一个session范围的FormBean中去，它在session中的关键字是<CODE>logonForm</CODE>。Struts开发者会给出关于这个form bean的Java实现，它是一个Struts类<CODE>ActionForm</CODE>的字类。这个bean用来给出所有的输入字段的初始值，只要字段名和bean的属性名一致。如果合适的bean没有找到，会自动用指定的Java类名字来创建一个新的。 
<LI>这个formbean也需要在Struts配置文件中指明。这里名字和类型可以被省略。参阅"<A href="file:///D:/DOWNLOAD/2004822203916/struts/building_controller.html#config">Action Mappings （动作映射）配置文件</A>"得到详细信息。 
<LI>Text标签展开成为HTML里的<CODE>&lt;input&gt;</CODE>元素，它的类型是"text"。在这里，在浏览器中显示时占据多少个字符空间也被指明了。当这个页面被执行的时候，对应的bean的<CODE>username</CODE>属性的值会被作为初始值（就是<CODE>getUsername()</CODE>的返回值）。 
<LI>password 标签用起来很简单。不同之处是当用户输入自己的密码时浏览器会显示星号而非用户输入值。. 
<LI>submit和reset标签生成form中对应的按钮。其上的标签文字是用message 标签生成的，所以它们显示的是国际化的字符串。 </LI></UL>
<P>处理multipart form也是很简单的。显而易见，当你编写一个multipart form的时候你创建的form中具有至少一个"file"类型的input输入框。编写一个multipart的form的第一步是使用struts-html标签库来创建显示页面： </P>
<HR>
<PRE>&lt;%@page language="java"&gt;
&lt;%@taglib uri="/WEB-INF/struts-html.tld"
       prefix="html"&gt;
&lt;html:form action="uploadAction.do"&gt;
  Please Input Text:
  &lt;html:text property="myText"&gt;&lt;br/&gt;
  Please Input The File You Wish to Upload:&lt;br/&gt;
  &lt;html:file property="myFile"&gt;&lt;br /&gt;
  &lt;html:submit /&gt;
&lt;/html:form&gt;
</PRE>
<HR>

<P>下一步是创建你的ActionForm bean： </P>
<HR>
<PRE>import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
public class UploadForm extends ActionForm {
  protected String myText;
  protected FormFile myFile;
  public void setMyText(String text) {
    myText = text;
  }
  public String getMyText() {
    return myText;
  }
  public void setMyFile(FormFile file) {
    myFile = file;
  }
  public FormFile getMyFile() {
    return myFile;
  }
}
</PRE>
<HR>

<P>在<A href="file:///D:/DOWNLOAD/2004822203916/api/index.html">Javadocs</A>里查阅FormFile可以看到在文件上传时它提供的处理文件的方法。也要看Javadoc里面的ActionServlet 和ActionMapping的不同的参数，你可以指定它们来指明文件如何上传。基本上你在你的Action类的perform()方法中需要调用<CODE>((UploadForm) form).getMyFile()</CODE>得到你的文件并且做出你的处理。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=form_input></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.3.2 支持的Input 字段的类型</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>下面列出了Struts定义的所有的input字段的类型，带有指向手册的连接。 </P>
<UL>
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#checkbox">checkboxes </A>选择框 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#hidden">hidden fields </A>隐藏字段 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#password">password</A> 密码输入框 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#radio">radio</A> 单选框 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#reset">reset</A> 重置按钮 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#select">select</A> 列出内值的选择条目（下拉选择框） 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#option">option</A>备选条目 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#options">options</A>备选条目 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#submit">submit</A> 提交按钮 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#text">text</A> 单行文本输入框 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#textarea">textareas</A> 多行文本输入框 </LI></UL>
<P>在任何情况下，字段标签都必须内置在<CODE>form</CODE>标签中，这样这些字段才知道用哪个bean来得到初始值。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=presentation_tags></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.3.3 其它有用的表示层标签</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>有好几个有用的tag用来创建表示层，请查阅它们的标签库的文档和Tag Develipers Guide得到更多的信息： </P>
<UL>
<LI>[逻辑] <A href="file:///D:/DOWNLOAD/2004822203916/struts-logic.html#iterate">iterate 枚举</A> 为一个列表中的所有元素重复输出标签。（这个列表可能是 Enumeration,Hashtable, Vector, 或者对象数组）。 
<LI>[逻辑] <A href="file:///D:/DOWNLOAD/2004822203916/struts-logic.html#present">present 存在</A> 根据一个指定的属性，这个tag在当前的request中检查，如果这个属性存在的话就显示它所包含的页面内容。每次使用这个标签的时候只能指定一个属性，名字是必需的。属性可以包括cookie, header,name,parameter,property,role,scopr还有user。 
<LI>[逻辑] <A href="file:///D:/DOWNLOAD/2004822203916/struts-logic.html#notPresent">notPresent 不存在</A> 和present作用相反的标签，当指定的属性不存在的时候显示。 
<LI>[html] <A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#link">link 连接</A> 创建一个 &lt;a&gt; HTML元素，作为一个锚点或者指向指定URL的超链接，它会自动进行URL编码，以在不支持cookie的时候维护session状态。 
<LI>[html] <A href="file:///D:/DOWNLOAD/2004822203916/struts-html.html#img">img 图像</A> 创建一个 &lt;img&gt; HTML元素，它可以动态改变"src"和"lowurl"中指定的URL，和&lt;html:link&gt;的方式相同。 
<LI>[bean] <A href="file:///D:/DOWNLOAD/2004822203916/struts-bean.html#parameter">parameter 参数</A> 获取特定的request 参数的值，把结果作为一个page范围的属性，类型是字符串或者字符串数组。 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=form_validation></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.3.4 自动form检查</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>除了上文提到的form和bean之间的交互之外，Struts还提供了附加的机制来检查它接收到的输入字段。要使用这个特性，在你的ActionForm中重载下面的这个类: </P><PRE>public ActionErrors
  validate(ActionMapping mapping,
    HttpServletRequest request);
</PRE>
<P>validate() 方法在bean的属性被自动填充之后，在对应的Action类的<CODE>porform()</CODE>方法调用之前由controller servlet自动调用。<CODE>validate()</CODE>方法有下面几个选择： </P>
<UL>
<LI>进行了恰当的检查，没有发现任何问题——返回<CODE>null</CODE>或者长度为零的ActionError实例，Controller servlet会继续调用对应的<CODE>Action</CODE>类的<CODE>的perform()</CODE>方法。 
<LI>进行了恰当的检查，发现了问题。——返回一个包含<CODE>ActionError</CODE>的ActionErrors实例，它包含了应该显示错误信息的关键字（位于程序的<CODE>MessageResources</CODE> 信息资源库中的关键字）。controller servlet会把这个数组保存为request的属性，以便<CODE>&lt;html:errors&gt;</CODE>标签使用，并且流程会重新转回到输入form(通过<CODE>ActionMapping</CODE>的<CODE>input</CODE>属性得到）。 </LI></UL>
<P>前面曾经提到过，这个特性完全是可选的。默认的validate()方法返回<CODE>null</CODE>,controller servelt会认为对应的Action类会做必要的检查。 </P>
<P>另一个常用的方式是在ActionForm的validate()方法中进行简单的主要的检查，在Action里面做“商业逻辑”检查。 </P>
<P>在夜间编译包和下列地址还有一个可选的ActionForm检查的包可以使用：<A href="http://home.earthlink.net/~dwinterfeldt/">David Winterfeldt的网站</A>。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=other_presentations></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.4 其他表示层技术</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>虽然你的程序的观感可以完全用标准的JSP和Struts的自定义标签库创建，你也许会考虑动用其他技术来增加部件重用，减少维护工作，并且/或者减少错误。下面几节讨论了几种可选项。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=custom_tags></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.4.1 针对程序的自定义标签</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>除了Struts定义的自定义标签，你针对你正在编写的程序创建标签也很容易，这会帮助你编写用户界面。通过针对下面的程序编写tag,Struts附带的示例程序描绘了基本原理： </P>
<UL>
<LI><B>checkLogon</B> - 检察是否存在一个特定的session对象，并且如果没有的话就转向到登录页面。这可以防止用户在使用你的程序到一半的时候，把页面用书签记录下来，试图以后跳过登录这一步。或者防止session失效。 
<LI><B>linkSubscription</B> - 生成一个指向明细页面的超连接，它传递需要的主键的值作为request属性。这在列出用户拥有的订阅纪录时有用，它提供了编辑或者删除订阅信息的链接。 
<LI><B>linkUser</B> - 生成一个指向用户详细信息页面的超链接，把需要的主键信息作为request属性传递。 </LI></UL>
<P>这些tag的源代码都在<CODE>src/example</CODE>目录下，位于<CODE>org.apache.struts.example</CODE>包中，和其它在程序中需要的java类在一起。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=includes></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.4.2 用Include(引用)来组合页面</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>用一个JSP页面（包括子定义标签和Bean来取得必要的动态数据）在生成整个表现是一个很普通的方式，在Struts的示例程序中也出现过。然而，很多程序需要在同一个页面中显示多个不同的单一逻辑部分的组合。 </P>
<P>举例，一个门户站点可能在门户的主页上有以下几个功能部分： </P>
<UL>
<LI>显示门户的搜索引擎 
<LI>一个或多个"新闻"显示部分，根据用户登记的个性文件中的兴趣组合。 
<LI>显示关于这个门户的讨论主题 
<LI>一个“有邮件在等待”提示，如果你的门户提供免费邮件账户。 </LI></UL>
<P>如果你能把工作分成不同的部分，为每个部分分配不同的开发者，开发工作会容易些。那么你需要用JavaServer Pages技术中的<I>include(包含)</I>能力，或者Struts提供的include 标签来把不同的页面结果组合到一起去。取决于你需要在什么时候组合你的输出，有三种不同的<I>include</I>可供选择: </P>
<UL>
<LI>一个 <CODE>&lt;%@ include file="xxxxx" %&gt;</CODE>指令可以包含一个包括Java代码或者JSP标记的页面。其中的代码甚至可以访问父页面之前定义的变量。在JavaServer Page编译之前，这段代码已经被包含了，所以它可以包含的不只是HTML代码。 
<LI>include <I>action(动作,这里指JSP中的标准指令)</I>(<CODE>&lt;jsp:include page="xxxxx" flush="true" /&gt;</CODE>)在请求时被处理，服务器会透明的处理它。除此以外，这意味着你通过在一个类似<A href="file:///D:/DOWNLOAD/2004822203916/struts-logic.html#equals">equals</A>这样使用参数的标签中编写这条请求，可以有条件的进行包含。 
<LI><A href="file:///D:/DOWNLOAD/2004822203916/struts-bean.html#include">bean:include</A>读取一个"forward"参数通过一个逻辑名字映射到一个被包含的jsp页面，或者读取"id"参数，打印一个页面上下文的字符串变量到jsp页面上。 </LI></UL>
<P>另一个方法是使用Struts Template Tag library(模版标签库）。察看Developer's Guide得到详细信息。 </P>
<P>Tiles是一个原来的Template Tag library的替代品，提供几处增强和新功能。Tiles位于夜间编译包，或者在<A href="http://www.lifl.fr/~dumoulin/tiles/">Cedric Dumoulin的网站</A>。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=image_rendering></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.4.3 图像生成部件</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>有一些程序需要动态生成图像，比如价格图或者股票报告等等。一般有两种不同的方法满足这个需求： </P>
<UL>
<LI>显示一个指向servlet请求的超链接。这个servlet会使用一个图像库来渲染出图像，把输出改为合适的内容类型(比如<CODE>image/gif</CODE>),并送出图像的字节流到浏览器。浏览器会像一个静态图像一样显示它。 
<LI>生成必要的HTML代码来下载一个Java applet来创建需要的图像。通过在生成的代码中传送初始化参数，你可以决定图像。或者applet也可以自行和server连结以取得这些参数。 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=text_rendering></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>3.4.4 生成文字</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>有些程序需要动态生成文本或者打包的文本，例如XML.如果整个页面都是被生成的，可以用PrintWriter输出，从Action里可以很容易的办到: </P><PRE>           response.setContentType("text/plain"); // or text/xml
           PrintWriter writer = response.getWriter();
           // use writer to render text
           return(null);
</PRE>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/10012.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-13 03:46 <a href="http://www.blogjava.net/RR00/articles/10012.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>4. 构造 Controller （控制器）部件 </title><link>http://www.blogjava.net/RR00/articles/10011.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 12 Aug 2005 19:17:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/10011.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/10011.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/10011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/10011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/10011.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4. 构造 Controller （控制器）部件</STRONG></FONT></TD></TR></TBODY></TABLE><A name=overview></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.1 纵览</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>现在我们已经理解如何构造你的程序的Model(模型)和View(视图)部件，现在是时候来关注<CODE>Controllder</CODE>部件了。Struts包含一个主要功能是映射一个请求URI到一个<CODE>Action</CODE>类的servlet。因此，对于Controller你的主要责任是关于: </P>
<UL>
<LI>为每一个可能接收的逻辑请求编写一个<CODE>Action</CODE>类（扩展自<CODE>org.apache.action.Action</CODE>）。 
<LI>为每一个可能提交的逻辑请求在XML中配置一个ActionMapping。这个XML配置文件通常命名为<CODE>struts-config.xml</CODE>。 
<LI>更新你的web程序的部署描述文件（在XML里）来包含需要的Struts部件。 
<LI>在你的程序里增加恰当的Struts部件。 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=action_classes></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.2 Action 类</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><CODE>Action</CODE>类提供了两个可以被继承的方法，适应你的servlet环境: </P><PRE>public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             ServletRequest request,
                             ServletResponse response)
  throws IOException, ServletException;

public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             HttpServletRequest request,
                             HttpServletResponse response)
  throws IOException, ServletException;
</PRE>
<P>大部分工程可能只需要用到"HttpServletRequest"版本。 </P>
<P><CODE>Action</CODE>类的目标是通过它的<CODE>perform()</CODE>方法处理一个请求，返回一个<CODE>ActinForward</CODE>对象表明控制权应该被转移到哪里（例如一个JSP）作为合适的相应。在<I>MVC/Model 2</I>设计模式中，一个典型的<CODE>Action</CODE>类会在<CODE>perform()</CODE>中执行如下逻辑： </P>
<UL>
<LI>检查当前用户session的状态（比如，检查用户是否已经成功登录）。如果<CODE>Action</CODE>类发现尚未登录，请求可以被转移到一个JSP页面提示让用户输入用户名和密码。当用户试图访问一个程序的“中间部分”（可能是从一个书签）的时候，或者是session已经超时，servlet容器创建了一个新的session的时候者都可能发生。 
<LI>如果检查还未完成的话，继续检查form bean的属性。如果发现了问题，把相应的错误的信息关键字放在request的属性里，然后把控制权重新转到输入页面来让用户改正。 
<LI>进行请求需要的操作(比如在数据库中保存一行数据）。这可能由<CODE>Action</CODE>内部的逻辑代码自己来完成，但是一般应该调用一个商业逻辑bean的合适的方法。 
<LI>更新服务器端的对象，来创建下一步用户面对的界面（典型的是request范围或者session范围的bean,取决于你需要这些条目保存多长时间）。 
<LI>返回一个合适的<CODE>ActionForward</CODE>对象来挑选JSP页面根据刚刚更新的bean来生成回应。典型的，你需要通过你接收到的<CODE>ActionMapping</CODE>的<CODE>findForward()</CODE>方法或者从controller servlet自身（如果你使用一个全局的逻辑名字）来得到这样的一个引用。 </LI></UL>
<P>在编写<CODE>Action</CODE>类代码时请记住以下几个设计要点： </P>
<UL>
<LI>Controller servlet只创建你的<CODE>Action</CODE>类的一个实例，用来对对付所有的请求。所以，你需要处理好你的代码，在一个多线程环境下你的<CODE>Action</CODE>应该运作良好，就象你编写一个servlet的<CODE>service()</CODE>方法一样。 
<LI>最有助于编写线程安全的程序的原则是在你的<CODE>Action</CODE>类中只使用本地变量(local variable)，而非实例变量(instance variable)。本地变量在堆栈中创建并依附于每一个独立的请求线程（由你的JVM处理），所以你不用担心共享它们。 
<LI>你系统中表示Model(模型)的bean由可能因为访问数据库或者其他资源而抛出异常。你应该在你的<CODE>perform()</CODE>逻辑中捕获所有的异常，把它们记录到程序的log文件中去（同时给出对应的stack trace)。可以这样做：<BR><CODE>servlet.log("Error message text", exception);</CODE> 
<LI>作为一项基本的规则，分配稀少的资源并且为每一个用户在它们的session里分配一个会导致规模问题。你应该在把你的控制转移到View（视图）部件之前就释放它们（比如数据库连接）——就算你调用的bean的方法抛出了异常也要这样。 </LI></UL>
<P>除此之外，你还需要警惕你的<CODE>Action</CODE>类们变得太大。出现这种情况最容易的可能就是把功能逻辑放在<CODE>Action</CODE>本身，而不是在独立的商业逻辑bean。除了让<CODE>Action</CODE>类变得难以阅读和维护，这种方法还会让重用商业逻辑变得困难，因为它们被嵌入在部件内部（那个<CODE>Action</CODE>类），从而被限制在一个web程序环境中运行。 </P>
<P>只要需要的所有属性都是在方法签名中传递的（指的是通过函数调用传递？——译者注），一个<CODE>Action</CODE>可以被分散在几个本地方法中。JVM把这些属性在堆栈中处理，所以它们就是是线程安全的。 </P>
<P>Struts附带的例子程序只是设计用于展示某些原理，因为它自己的商业逻辑是被嵌入在<CODE>Action</CODE>类中的。这应该被理解为设计中的某种bug，而非Struts体系本身的特性，或者应该被模仿的方法。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=actionmapping></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.3 ActionMapping 的实现</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>为了能成功的操作，关于如何把每一个请求URI映射到恰当的<CODE>Action</CODE>类，Struts controller servlet需要知道几件事情。这些需要的知识被封装在一个叫做<CODE>ActionMapping</CODE>的Java接口中，下列是最重要的几个属性: </P>
<UL>
<LI><B>type</B> - 在这个映射中<CODE>Action</CODE>实现的完整java类名。 
<LI><B>name</B> - 这个action会用到的form bean在配置文件中使用的名字 
<LI><B>path</B> - 请求的URL用以选择（触发）这个映射。下面会有关于匹配如何工作的例子。 
<LI><B>unknown</B> - 当无法找到合适的其他action来处理请求时，某个action可以被配置为默认处理这个请求，这时候把这一项置为<CODE>true</CODE>。一个程序中只能有一个action作为默认处理action。 
<LI><B>validate</B> - 如果这个映射中涉及的action需要在调用前先调用<CODE>validate()</CODE>方法，把这一项置为<CODE>true</CODE>。 
<LI><B>forward</B> - 当这个映射被调用的时候，转向一个请求URI。这是<B>type</B>属性的一个替代品。 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=config></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.4 Action Mappings 配置文件</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>controller servlet是如何知道你希望的映射的？写一个小java类来创建新的<CODE>ActionMapping</CODE>的实例，并且调用每一个setter方法来赋值是可行的，但是非常繁琐。为了简化这个步骤，Struts包含一个Digester模块，它能够读取一段基于XML的关于需要的映射的描述，并创建合适的对象。参阅<A href="file:///D:/DOWNLOAD/2004822203916/api/index.html">API 文档</A>得到关于Digester的更多信息。 </P>
<P>开发者的责任是编写一个命名为<CODE>struts-config.xml</CODE>的XML文件，并把它放在你的程序的WEB-INF目录下。文档的格式由"struts-config_1_0.dtd"中的描述指定。最外层的XML元素必须是<CODE>&lt;struts-config&gt;</CODE>。 </P>
<P>在&lt;struts-config&gt;元素之内，有两个重要的元素被用于描述你的action: <B>&lt;form-beans&gt;</B><BR>这一段包含你的form bean的定义。你为每一个form bean使用一个&lt;form-bean&gt; 元素，包含下列属性： 
<UL>
<LI><B>name</B>: 这个bean的一个唯一的标识名，它将会被用来在action映射中引用来指定这个bean.通常，这也是把这个对象存放在request或者session中的属性的关键字。 
<LI><B>type</B>: 你的form bean的完整的Java类名。 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE><B>&lt;action-mappings&gt;</B><BR>这一段包含你的action的定义。你为你的每一个需要定义的action使用一个&lt;action&gt; 元素。每一个action元素需要定义下列的属性： 
<UL>
<LI><B>path</B>: 这个action的程序上下文相关的路径 
<LI><B>type</B>: 这个Action类的完整类名 
<LI><B>name</B>: Action中所用到的&lt;form bean&gt;元素的名字 </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE>
<P></P>
<P>示例程序中的<CODE>struts-config.xml</CODE>文件包含了下列的映射元素，它们是用来实现“登录”功能的，我们用它来说明需求。注意其它的Action的条目都被剔除了： </P><PRE>&lt;struts-config&gt;
  &lt;form-beans&gt;
    &lt;form-bean
      name="logonForm"
      type="org.apache.struts.example.LogonForm" /&gt;
  &lt;/form-beans&gt;      
  &lt;global-forwards
      type="org.apache.struts.action.ActionForward" /&gt;
    &lt;forward name="logon" path="/logon.jsp"
         redirect="false" /&gt; 
  &lt;/global-forwards&gt;      
  &lt;action-mappings&gt;     
    &lt;action
        path="/logon" 
        type="org.apache.struts.example.LogonAction"
        name="logonForm"
       scope="request"
       input="/logon.jsp"
     unknown="false"
    validate="true" /&gt;          
  &lt;/action-mappings&gt;
&lt;/struts-config&gt;
</PRE>
<P>首先定义的是form bean .一个基础的"<CODE>org.apache.struts.example.LogonForm</CODE>"类被映射为逻辑名"<CODE>logonForm</CODE>"。这个名字也被用在session或者request作为这个form bean的属性名。 </P>
<P>"<CODE>global-forwards</CODE>"部分用来创建全局可用的逻辑名映射。这儿的任何一个转移都可以通过调用你的action mapping的实例实现，比如<CODE>actionMappingInstace.findForward("logicalName")</CODE>。 </P>
<P>你可以看到，这个映射匹配<CODE>/logon</CODE>路径（实际上，因为实例程序用了后缀名映射，你指定的URI请求会是由<CODE>/logon.do</CODE>结尾的）。当收到一个匹配这个路径的请求时，会创建一个<CODE>LogonAction</CODE>的实例（仅当第一次），并且使用它。controller serverl会寻找一个session范围的名为<CODE>logonForm</CODE>的bean,如果需要的话，创建并保存这样的一个bean。 </P>
<P>局部的"<CODE>forward</CODE>" 元素是可选的但是非常实用。在实例程序中，很多action包含一个局部的"success"和/或"failure"转移作为Action mapping的一部分。 </P><PRE>&lt;!-- Edit mail subscription --&gt;
&lt;action    path="/editSubscription"
  type="org.apache.struts.example.EditSubscriptionAction"
  name="subscriptionForm"
  scope="request"
  validate="false"&gt;
  &lt;forward name="failure" path="/mainMenu.jsp"/&gt;
  &lt;forward name="success" path="/subscription.jsp"/&gt;
  &lt;/action&gt;
</PRE>
<P>只用了两个额外的属性，示例程序中的<CODE>Action</CODE>类变得几乎和页面设计者用的实际JSP页面的名字无关了。页面可以在重新设计的时候被改名（举个例子），只会给<CODE>Action</CODE>类带来微不足道的冲击。如果“下一个”JSP页面的名字是被硬编码在<CODE>Action</CODE>里面的话，所有的类就必须做出改动。当然，你可以决定在你的程序中使用怎样的局部转移属性。 </P>
<P>另一个很有用的部分是<CODE>&lt;data-sources&gt;</CODE>，它定义了你的程序可以使用的数据源。下面是你如何在你的程序的struts-config.xml中指定一个基本的数据源： </P><PRE>&lt;struts-config&gt;
  &lt;data-sources&gt;
    &lt;data-source
      autoCommit="false"
     description="Example Data Source Description"
     driverClass="org.postgresql.Driver"
        maxCount="4"
        minCount="2"
        password="mypassword"
             url="jdbc:postgresql://localhost/mydatabase"
            user="myusername"/&gt;
  &lt;/data-sources&gt;
&lt;/struts-config&gt;
</PRE>
<P>关于如何获取这个数据源，参阅<A href="file:///D:/DOWNLOAD/2004822203916/struts/building_model.html#databases">访问关系数据库</A>这一节。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=dd_config></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.5 Web 程序发布描述</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>设置你的程序的最后一步是配置程序的发布描述（保存在<CODE>WEB-INF/web.xml</CODE>文件中）来包含所有需要的Struts部件。用示例程序中的发布描述作为一个指南，我们发现下列条目需要创建或者修改。 </P><A name=dd_config_servlet></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.5.1 配置Action servlet实例</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>增加一个条目来定义action servlet自己，包含合适的初始化参数。这样的一个条目可能是这样的： </P><PRE>&lt;servlet&gt;
  &lt;servlet-name&gt;action&lt;/servlet-name&gt;
  &lt;servlet-class&gt;
    org.apache.struts.action.ActionServlet
  &lt;/servlet-class&gt;
  &lt;init-param&gt;
    &lt;param-name&gt;application&lt;/param-name&gt;
    &lt;param-value&gt;
      org.apache.struts.example.ApplicationResources
    &lt;/param-value&gt;
  &lt;/init-param&gt;
  &lt;init-param&gt;
    &lt;param-name&gt;config&lt;/param-name&gt;
    &lt;param-value&gt;
      /WEB-INF/struts-config.xml
    &lt;/param-value&gt;
  &lt;/init-param&gt;
  &lt;init-param&gt;
    &lt;param-name&gt;debug&lt;/param-name&gt;
    &lt;param-value&gt;2&lt;/param-value&gt;
  &lt;/init-param&gt;
  &lt;init-param&gt;
    &lt;param-name&gt;mapping&lt;/param-name&gt;
    &lt;param-value&gt;
      org.apache.struts.example.ApplicationMapping
    &lt;/param-value&gt;
  &lt;/init-param&gt;
  &lt;load-on-startup&gt;2&lt;/load-on-startup&gt;
&lt;/servlet&gt;
</PRE>
<P>controller servlet支持的初始化参数如下所示。（你也可以在<A href="file:///D:/DOWNLOAD/2004822203916/api/index.html">Javadocs</A>中查找ActionServlet类得到详细信息。）方括号表示如果你没有给出初始值时使用的默认值。 
<UL>
<LI><STRONG>application</STRONG> - 程序的资源包的基础类的Java类名。 [NONE] 
<LI><STRONG>bufferSize</STRONG> - 处理文件上传的输入缓冲区大小。[4096] 
<LI><STRONG>config</STRONG> - 指向包含我们的配置信息的XML资源的相对于上下文的路径。[/WEB-INF/struts-config.xml] 
<LI><STRONG>content</STRONG> - 默认输出响应的的文档类性和字符集编码。它可以被一个转移到的servlet或者JSP重载。[text/html] 
<LI><STRONG>debug</STRONG> - 这个servlet的debug信息详细程度，它控制多少信息应该被记录。[0] 
<LI><STRONG>detail</STRONG> - 我们在<CODE>initMapping()</CODE>中使用的Digester的debug信息详细程度，它输出到System.out而非servlet的log。[0] 
<LI><STRONG>factory</STRONG> - 用于创建程序的<CODE>MessageResources</CODE>对象的<CODE>MessageResourcesFactory</CODE>的类名。 [org.apache.struts.util.PropertyMessageResourcesFactory] 
<LI><STRONG>formBean</STRONG> - ActionFormBean继承的根的Java类名。[org.apache.struts.action.ActionFormBean]. 
<LI><STRONG>forward</STRONG> - ActionForwarder继承的根的Java类名。 [org.apache.struts.action.ActionForward]. 两个你可能选择的类是： Two convenient classes you may wish to use are: 
<UL>
<LI><EM>org.apache.struts.action.ForwardingActionForward</EM> - <CODE>org.apache.struts.action.ActionForward</CODE>的子类，它的 <CODE>redirect</CODE>属性被默认置为<CODE>false</CODE>(和Actionforward 默认值一样）。 
<LI><EM>org.apache.struts.action.RedirectingActionForward</EM> - <CODE>org.apache.struts.action.ActionForward</CODE>的子类，它的<CODE>redirect</CODE>属性被默认置为<CODE>true</CODE>。 </LI></UL>
<LI><STRONG>locale</STRONG> - 如果被置为 <CODE>true</CODE>, 并且有一个用户session,如果没有Locale对象的话，放置一个合适的<CODE>java.util.Locale</CODE> object (用<CODE>Action.LOCALE_KEY</CODE>作为标识关键字)到用户session中去。[true] 
<LI><STRONG>mapping</STRONG> - ActionMapping继承的根的Java类名。[org.apache.struts.action.ActionMapping]. 两个你可能选择的类是： 
<UL>
<LI><EM>org.apache.struts.action.RequestActionMapping</EM> - <CODE>org.apache.struts.action.ActionMapping</CODE> 的子类，<CODE>scope</CODE>属性默认是"request"。 
<LI><EM>org.apache.struts.action.SessionActionMapping</EM> - of <CODE>org.apache.struts.action.ActionMapping</CODE> 的子类，<CODE>scope</CODE>属性默认是"session"(和ActionMapping默认值一样）。 </LI></UL>
<LI><STRONG>maxFileSize</STRONG> - 一次上传文件可能的最大大小（单位是字节）。可以在数字后面加上"K","M',或者"G", 代表千字节，兆字节和千兆字节。[250M] 
<LI><STRONG>multipartClass</STRONG> - 用于文件上传的MultipartRequestHandler 的实现的完整Java类名。[org.apache.struts.upload.DiskMultipartRequestHandler] 
<LI><STRONG>nocache</STRONG> - 如果设置为<CODE>true</CODE>, 在每一个响应中加上HTTP头信息来访置我们的任何响应或者转移被浏览器缓存。[false] 
<LI><STRONG>null</STRONG> - 如果设置为<CODE>true</CODE>, 如果（资源）信息的关键字无法找到，返回一个<CODE>null</CODE>。否则，返回一个带有此关键字的错误信息。[true] 
<LI><STRONG>tempDir</STRONG> - 文件上传时的临时目录。 [这个web程序的servlet上下文属性指定的工作目录] 
<LI><STRONG>validate</STRONG> - 我们是否适用性的配置文件格式？[true] 
<LI><STRONG>validating</STRONG> - 我们是否使用一个带有校验的XML 解释器来处理配置文件（强烈建议）？ [true] </LI></UL>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=dd_config_mapping></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.5.2 配置Action Servlet 映射</STRONG></FONT></TD></TR>
<TR>
<TD>
<P><STRONG>注意：</STRONG> 这一段中的材料不是针对Struts的。配置servlet映射是在Java Servlet规格书中定义的。这一段描述了最普通的针对配置一个Struts程序的方法。 </P>
<P>又两种一般的方法来配置一个URL成为被controller servlet处理的URL - 前缀匹配和后缀匹配。每种方法相应的配置条目会在下面描述。 </P>
<P>前缀匹配意味着你希望所有的以某一个特定值开头的URL（在上下文路径部分之后）都被送往这个servlet。这样的条目可能是这样： </P><PRE>  &lt;servlet-mapping&gt;
     &lt;servlet-name&gt;action&lt;/servlet-name&gt;
     &lt;url-pattern&gt;/execute/*&lt;/url-pattern&gt;
   &lt;/servlet-mapping&gt;
</PRE>
<P>就是说前面我们提到过的匹配<CODE>/logon</CODE>的URI请求会被这样描述： <PRE>http://www.mycompany.com/myapplication/execute/logon
</PRE>
<P>这里<CODE>/myapplication</CODE>是你的程序部署的上下文路径。 </P>
<P>后缀匹配映射，相反，在URL以某一个特定的字符串结尾时把URI请求匹配到action servlet.举个例子，JSP处理servlet对应到<CODE>*.jsp</CODE>，这样，每当一个jsp页面被访问，它都会被调用进行处理。为了使用<CODE>*.do</CODE>后缀名（意思是“做什么”），映射条目可能是这样的： </P><PRE>  &lt;servlet-mapping&gt;
     &lt;servlet-name&gt;action&lt;/servlet-name&gt;
     &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;
   &lt;/servlet-mapping&gt;
</PRE>
<P>前面我们提到过的匹配<CODE>/logon</CODE>的URI请求会被这样描述： </P><PRE>http://www.mycompany.com/myapplication/logon.do
</PRE>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=dd_config_taglib></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.5.3 配置 Struts 标签库</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>下一步，你必须增加一个条目来定义Struts标签库。当前Struts打包了4个标签库。 </P>
<P>struts-bean 标签库包含访问bean和它们的属性的有用的标签，也包含利用这些访问定义新的bean以便在页面剩下的部分用脚本中的变量和页面范围的属性来访问。还有用request coolie,header和parameter的值来创建bean的便利机制。 </P>
<P>struts-html 标签库包含用户创建struts输入表单，还有其他通常很在创建基于HTML的用户界面上很有用的标签。 </P>
<P>struts-logic 标签库包括用于有条件的生成输出代码，循环整个对象容器来输出重复的文本，还有程序流管理。 </P>
<P>struts-template 标签库包含定义了一个模版机制的标签。 </P>
<P>下面是在你的程序中如何定义所有这些标签。在实际工作中你可以只指定你的程序要用到的。 </P><PRE>&lt;taglib&gt;
  &lt;taglib-uri&gt;
    /WEB-INF/struts-bean.tld
  &lt;/taglib-uri&gt;
  &lt;taglib-location&gt;
    /WEB-INF/struts-bean.tld
  &lt;/taglib-location&gt;
&lt;/taglib&gt;
&lt;taglib&gt;
  &lt;taglib-uri&gt;
    /WEB-INF/struts-html.tld
  &lt;/taglib-uri&gt;
  &lt;taglib-location&gt;
    /WEB-INF/struts-html.tld
  &lt;/taglib-location&gt;
&lt;/taglib&gt;
&lt;taglib&gt;
  &lt;taglib-uri&gt;
    /WEB-INF/struts-logic.tld
  &lt;/taglib-uri&gt;
  &lt;taglib-location&gt;
    /WEB-INF/struts-logic.tld
  &lt;/taglib-location&gt;
&lt;/taglib&gt;
&lt;taglib&gt;
  &lt;taglib-uri&gt;
    /WEB-INF/struts-template.tld
  &lt;/taglib-uri&gt;
  &lt;taglib-location&gt;
    /WEB-INF/struts-template.tld
  &lt;/taglib-location&gt;
&lt;/taglib&gt;
</PRE>
<P>这告诉JSP系统到哪里去寻找标签库的定义（在你的程序的WEB-INF目录，而不是Internet上的某处）。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=config_add></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>4.5.4 把Struts部件增加到你的程序中</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>为了使用Struts,你必须拷贝你需要的.tld文件到你的<CODE>WEB-INF</CODE>目录，并且拷贝<CODE>struts.jar</CODE>（和其它所有的<CODE>commons-*.jar</CODE>文件）到你的<CODE>WEB-INF/lib</CODE>目录。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/10011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-13 03:17 <a href="http://www.blogjava.net/RR00/articles/10011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 2. 构造Model（模型）部件 </title><link>http://www.blogjava.net/RR00/articles/10010.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Fri, 12 Aug 2005 18:18:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/10010.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/10010.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/10010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/10010.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/10010.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2. 构造Model（模型）部件</STRONG></FONT></TD></TR></TBODY></TABLE><A name=overview></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.1 纵览</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>很多用于构造web程序的需求文档都是关注于<I>View(视图)</I>的。但是，你需要确认每一个确定的请求需要的处理也是在<I>Model(模型)</I>层清楚的定义的。一般说来，<I>Model(模型）</I>的开发者会关注如何建立满足所有功能需求的JavaBean类。一个特定的程序所需要的明确定义的bean会有很大不同，取决于他们的需求。然而他们大致上可以被归为下面会讨论的几类。然而，先做一个关于“Scope范围”这个概念的简要的回顾会是很有用的。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=javabeans></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.2 JavaBeans 和 scope(范围)</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>在一个基于web的程序中，JavaBean可以被存放在（也是获取于)几个不同的“属性”集合。每一个集合有不同的关于集合的生存期和储存在其中的bean的可视范围的规则。定义生存期和可视范围的规则共同被称为这些bean的“scope(范围)”。JavaServer pages(JSP)的规格书定义了以下的术语(在servlet API中同样的也有这些定义）: </P>
<UL>
<LI><B>page</B> - Bean在一个单一的JSP页面中可见，生存期是这个请求。（<CODE>service()</CODE>函数的本地变量） 
<LI><B>request</B> - Beans 在一个单一的JSP页面中可见，包括被包含在这个页面中或者被此页面转移到的任何页面或者servlet. (Request 属性) 
<LI><B>session</B> - Beans 在一个特定的用户session中的所有JSP页面和Servlet中可见，跨越一个或多个请求。(Session 属性) 
<LI><B>application</B> - Beans 在web 程序的所有的JSP页面和servlet中可见。 (Servlet context属性) </LI></UL>
<P>记住同一个web程序中的JSP页面和servlet共享同样的bean集合是很重要的。例如，如下的代码在一个servlet中把一个bean加入了request的属性: </P>
<P><CODE>MyCart mycart = new MyCart(...);<BR>request.setAttribute("cart", mycart); </CODE></P>
<P>马上在这个servlet转移到的JSP页面中可见,通过使用一个标准的动作tag,就像这样： </P>
<P><CODE>&lt;jsp:useBean id="cart" scope="request"<BR>class="com.mycompany.MyApp.MyCart"/&gt; </CODE></P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=actionform></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.3 ActionForm Beans</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>注意:ActionForm Beans实际上更靠近<I>View(视图)</I>而非<I>Model(模型)</I>。 </P>
<P>Struts框架一般会假设你已经为你程序中每一个需要输入的Form定义好了一个<CODE>ActionForm</CODE>Bean(这是一个从<CODE>ActionForm</CODE>继承的一个类).<CODE>ActionForm</CODE> beans有时候就叫做"form beans"。如果你已经在你的<CODE>ActionMapping</CODE>配置文件里(参阅"<A href="file:///D:/DOWNLOAD/2004822203916/struts/building_controller.html#config">构造Controller（控制器）部件</A>")生命了这些bean, Struts Controller servlet在调用合适的<CODE>Action</CODE>方法之前会自动为你提供如下服务: </P>
<UL>
<LI>在用户的session里面察看在恰当的键值下是否有一个合适的类的实例。 
<LI>如果没有这样的session范围的bean存在，会自动创建一个新的实例并加入到user的session中。 
<LI>对每一个request 参数，如果能对应于(form) bean的一个同名属性，会调用相应的setter方法。这个操作很象标准的JSP动作<CODE>&lt;jsp:setProperty&gt;</CODE>,当你用'*'符号来选择所有的属性的时候。 
<LI>更新过的<CODE>ActionForm</CODE>bean 会被传递到Action 类的<CODE>perform()</CODE>方法，（当这个方法被调用时）这些值马上就可以使用了。 </LI></UL>
<P>当你编写你的 <CODE>ActionForm</CODE> bean的时候，记住这些基本的原则： </P>
<UL>
<LI><CODE>ActionForm</CODE>类本身不需要实现具体的方法。它是用来为了明确特殊的bean在整个体系中的角色的。一般来说，一个<CODE>ActionForm</CODE>bean 只需要属性的getter和属性的setter方法，没有商业逻辑。 
<LI>ActionForm 对象也提供了一个标准的检查机制。如果你重载了一个"stud"函数，并且在标准的程序资源里给出了错误信息，Struts会自动检查输入的值（使用你的方法）。参阅"<A href="file:///D:/DOWNLOAD/2004822203916/struts/building_view.html#form_validation">Action Form 检查</A>" 得到详细说明。当然，你可以忽略在ActionForm中的检查而在你的Action对象中自己进行。 
<LI>为每一个form中出现的字段定义一个属性(附带相应的<CODE>getXxx()</CODE>和<CODE>setXxx()</CODE>方法)。字段的命名和属性的命名必须遵循通常的JavaBeans规范。举例来说，一个输入的字段名叫<CODE>username</CODE>会导致<CODE>setUsername()</CODE>方法被调用。 
<LI>设想你的ActionForm bean是HTTP和Action之间的防火墙。用validate方法来保证所有需要的书形式存在的，并且包含合理的值。一个没有通过检查的ActionForm不会被送到Action去处理。 
<LI>你也可以在你的form里面放置一个bean的实例，来使用内置的属性引用。比如，你可能在你的ActionForm上有一个“customer”bean,可以在你的JSP 中使用属性"customer.name"。这会对应到你的customer bean的<CODE>customer.getName()</CODE>和<CODE>customer.setName()</CODE>方法。 参阅 tag Library Develiper Guides 得到更多关于内置属性语法的说明。 
<LI><I>警告:</I> 如果你在你的form上放置一个以存在的bean的实例，考虑它暴露出来的属性。任何public的，接受一个单一的字符串的属性可能被一个查询字符串重置。这些bean放在一个瘦的“包装者”类里面，只暴露需要的属性可能时有所帮助的。这个包装者也可以提供一次过滤来保证运行时的属性不被置为无意义的值。 </LI></UL>
<P>你可能注意到了一个在这里讨论的"form"，并非必须是用户界面端一个单独的JSP页面。在很多程序里都会出现跨越多个页面的"form"(从使用者的角度来说）。想一下，举例来说，在安装新程序时经常会出现的向导风格的用户界面。Struts鼓励你定义一个单独的<CODE>ActionForm</CODE>包含所有可能用到的属性，不管到底是在那个页面显示的。同样的，同一个form的不同页面应该被提交到同样的Action类。如果你遵循这些建议，页面设计者可以重新在页面之间安排这些字段，通常不需要修改处理逻辑。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=system_state></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.4 系统状态Beans</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>系统的实际状态一般会表现为一套包括一个或多个JavaBean类，它们的属性定义了当前的状态。一个购物车，举例来说，会包括为每一个购物者维护一个bean,并且会（和其他属性一起）包括一些购物者当前选择的物品条目。另外，系统也会包括不同的bean来保存用户的个人资料（包括他们的信用卡号码和送货地址），还有按照他们的购物等级所能得到的可购买物品清单。 </P>
<P>对于一个小型的系统，或者对不需要长期保存状态信息的系统来说，一套系统状态bean可能已经保存了系统所需要的全部特定细节。否则，大多数情况下，系统状态bean会把它持有的信息包村到一个外部的数据库去（比如一个<CODE>CustomerBean</CODE>对象对应于CUSTOMERS表中的一个特定的行），并可以在服务器的内存中按照需要创建或者删除。Entity Enterprise JavaBeans 在大规模系统也是为了这个目的使用的。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=business_logic></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.5 商业逻辑 Beans</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>你应该把你的程序的功能逻辑封装在你为此设计的JavaBean的方法调用中。这些方法可能是同一个系统状态bean,或者他们分布在不同的类中，潜在的体现了逻辑。在后一种状况中，你往往需要把系统状态bean作为参数调用以便这些方法处理。 </P>
<P>为了最大化代码重用，商业逻辑bean因为被设计和实现为假设它们<B>不</B>知道会在web环境下被执行。如果你发现你在你的bean中import<CODE>javax.servlet.*</CODE>，你(就知道你在)在试图把这个商业逻辑bean放置在web环境中。请考虑重新编排，让你的<CODE>Action</CODE>类（属于controller角色的一部分，下文将会谈到）从HTTP请求翻译所有需要的信息，通过调用你的商业逻辑bean的setter方法预置，然后调用一个<CODE>execute()</CODE>方法来执行。这样的商业逻辑类可以在不是最初的Web的环境下重用。 </P>
<P>取决于你的程序的复杂程度和范围(宽广程度)，商业逻辑bean可能是普通的JavaBeans(它们和作为参数传递的系统状态bean打交道),或者是通过JDBC调用存取数据库的一般的JavaBeans。对于大规模程序来说，它们往往是被有状态的或者无状态的Enterprise JavaBeans(EJBs)所取代。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><A name=databases></A>
<TABLE cellSpacing=5 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#023264><FONT face=arial,helvetica,sanserif color=#ffffff size=+1><STRONG>2.6 访问关系数据库</STRONG></FONT></TD></TR>
<TR>
<TD>
<P>Struts可以在它的标准配置文件中为程序定义datasource.也提供一个<B>简单</B>的JDBC连接池。参阅<A href="file:///D:/DOWNLOAD/2004822203916/struts/building_controller.html#config">Action Mappings 配置文件</A>和Utilities Developer Guide(工具开发指南)得到更详细的信息。 </P>
<P>当datasource被定义号之后，下面是一个在Action的perform方法中取得连接的例子。 </P><PRE>public ActionForward
       perform(ActionMapping mapping,
               ActionForm form,
               HttpServletRequest request,
               HttpServletResponse response)
{
 try {
   javax.sql.DataSource dataSource =
     servlet.findDataSource(null);
   java.sql.Connection myConnection =
     dataSource.getConnection();

   //do what you wish with myConnection
 } catch (SQLException sqle) {
   getServlet().log("Connection.process", sqle);
 } finally {

   //enclose this in a finally block to make
   //sure the connection is closed
   try {
     myConnection.close();
   } catch (SQLException e) {
     getServlet().log("Connection.close", e);
   }
 }
}
</PRE>
<P>注意Struts 普通连接池是一个<B>可选</B>组件。很多Struts程序使用其它连接池来获取更高的性能，特别是大流量的生产系统。 </P>
<BLOCKQUOTE></BLOCKQUOTE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/RR00/aggbug/10010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-13 02:18 <a href="http://www.blogjava.net/RR00/articles/10010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts study blog</title><link>http://www.blogjava.net/RR00/articles/9158.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Wed, 03 Aug 2005 20:07:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/9158.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/9158.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/9158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/9158.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/9158.html</trackback:ping><description><![CDATA[<P><FONT color=#ff0000>1。<ACTION path="/inputProduct" <BR>&nbsp;&nbsp;&nbsp;type="com.yourcompany.struts.DemoAction" name="DemoForm"<BR>&nbsp;&nbsp;&nbsp;scope="request" input="/index.jsp" /&gt;</FONT></P>
<P><FONT color=#808080>一个<FONT color=#ff0000>DemoForm</FONT>(<FONT color=#ff0000>继承 ActionForm</FONT>)对应一个<FONT color=#ff0000>DemoAction</FONT>（ extends Action）必须实现 execute <BR>&nbsp; (ActionMapping mapping,ActionForm form, <BR>&nbsp; HttpServletRequest request, <BR>&nbsp; HttpServletResponse response) </FONT></P>
<P><FONT color=#808080>里面的ActionForm form对应</FONT><FONT color=#ff0000>DemoForm；</FONT></P>
<P><FONT color=#ff0000>2。DemoForm里面的validate(ActionMapping mapping,HttpServletRequest request)验证；</FONT></P>
<P><FONT color=#0000ff>不通过转向 input="/index.jsp" /；</FONT></P>
<P><FONT color=#ff0000><FONT color=#0000ff>否则由&nbsp;type="com.yourcompany.struts.DemoAction"</FONT> </FONT><FONT color=#000000>验证！</FONT></P>
<P>3<FONT color=#006400>。<?xml:namespace prefix = html /><html:form action="/user.do"><BR>&nbsp;&nbsp;&nbsp; user:<BR>&nbsp;&nbsp;&nbsp; <html:text property="user"></html:text></FONT></P>
<P><FONT color=#006400><html:submit></html:submit><html:reset></html:reset></html:form></FONT></P>
<P><FONT color=#ff0000><ACTION path="/user" <BR type="com.yourcompany.struts.UserAction">&nbsp;&nbsp;&nbsp;name="UserForm" scope="request" input="/failedIn.do" /&gt;</FONT></P>
<P><FONT color=#006400>html:form对应action="/user.do"&gt;对应</FONT><FONT color=#ff0000>UserForm"</FONT></P>
<P><FONT color=#006400>property对应</FONT><FONT color=#ff0000>UserForm"里的属性！</FONT></P>
<P><FONT color=#ff0000>还可添加reset(ActionMapping mapiping,HttpServletRequest request)</FONT></P>
<P>&nbsp;</P>
<P><FONT color=#808080>4</FONT></P>
<P><FONT color=#808080><?xml:namespace prefix = logic /><logic:present name="userbean" scope="request"><BR>&nbsp;&nbsp;&nbsp; logic:present:<?xml:namespace prefix = bean /><bean:write  name="userbean" property="user"></bean:write ><BR>&nbsp;&nbsp;&nbsp; 
<HR>
&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; </logic:present></FONT>
<P></P>
<P><FONT color=#808080><logic:present name="userbean" scope="request"></FONT><FONT color=#ff1493>判断userbean是否存在！存在则显示后面的内容！</FONT></P>
<P>5&nbsp;web.xml<BR>tomcat&nbsp;启动时加载,servlet类，类中对象保存在httpcontext中，即application范围内，所有组件可共享。 <SPAN id=dissub1></P>
<DIV id=blog_sub_st name="blog_sub_st"><FONT color=#ff1493><LOAD-ON-STARTUP>1</LOAD-ON-STARTUP>这句话不能缺少！！！！！！！！！！！</FONT><BR><BR>6.<FORM-BEAN name="UploadForm" type="com.yourcompany.struts.UploadForm<FONT style=" #800080? BACKGROUND-COLOR:> </FONT>"/&gt;<BR><FORM-BEAN name="UploadForm" type="com.yourcompany.struts.UploadForm" /><BR>前一句多了个空格，导致严重错误！！！！！！！！！！！<BR><BR>7.DynaActionForm f = (DynaActionForm) form;<BR>&nbsp;&nbsp;String[] s = (String[]) <FONT style="BACKGROUND-COLOR: #7fffd4">f.getMap().</FONT>get("results");<BR>注意getMap部分</DIV></SPAN></logic:present><img src ="http://www.blogjava.net/RR00/aggbug/9158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-04 04:07 <a href="http://www.blogjava.net/RR00/articles/9158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse3.0.1+Myeclipse3.8.2+tomcat5开发第一个struts应用（配置篇)</title><link>http://www.blogjava.net/RR00/articles/9157.html</link><dc:creator>R.Zeus</dc:creator><author>R.Zeus</author><pubDate>Wed, 03 Aug 2005 20:06:00 GMT</pubDate><guid>http://www.blogjava.net/RR00/articles/9157.html</guid><wfw:comment>http://www.blogjava.net/RR00/comments/9157.html</wfw:comment><comments>http://www.blogjava.net/RR00/articles/9157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RR00/comments/commentRss/9157.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RR00/services/trackbacks/9157.html</trackback:ping><description><![CDATA[<P>最近刚刚进入STRUTS大门，学习了《STRUTS IN ACTION》，写了几个小程序，感觉必须选一个IDE来<BR>省点力气。去GOOGLE了一下，发现很多人使用Eclipse+Easystruts插件+Tomcat插件来开发，立刻去<BR>下了所有的程序，找了一些文章来指导配置，但用尽力气，使用了所有可能的方法都没有成功，可以<BR>识别LOMBOZ和TOMCAT但无法识别Easystruts插件，但是在Eclipse的HELP--About Eclipse Platform<BR>--Plug-in Details里面却有Easystruts插件，无奈！最后在网上继续找了下，发现有些人说Eclipse3.0.1<BR>支持LOMBOZ但不能支持Easystruts（不知道真实性怎么样~），还是算了，换个方法吧。<BR>&nbsp;&nbsp;&nbsp; 于是我选择Eclipse3.0.1+Myeclipse3.8.2+tomcat5来开发struts，这个配置就简单多了，哈哈。 </P>
<P><BR>一.下载<BR>我的环境是<BR>JDK1.4.2<BR>TOMCAT5.0.28<BR>Eclipse3.0.1<BR>Myeclipse3.8.2</P>
<P><BR>二.安装<BR>Eclipse3.0.1+Myeclipse3.8.2的安装就不多说了，很简单。<BR>主要的Myeclipse3.8.2的破解<BR>我在网上找到了Myeclipse3.8.2的破解程序<BR>这是我的私人空间，我已经把破解程序上传了，方便大家。<BR>地址是：<BR>下完后解压到<BR>MyEclipse\eclipse\plugins\com.genuitec.eclipse.core_3.8.2<BR>覆盖原来的文件，<BR>然后启动MyEclipse<BR>填入MyEclipse3.6.4的注册信息（程序里面有，网上也很多！），就可以了。</P>
<P>三.基础配置</P>
<P>破解文件覆盖后，启动MyEclipse<BR>进入Window---&gt;Perferences---&gt;MyEclipse----&gt;Subscription输入注册信息。<BR>然后在Window---&gt;Perferences---&gt;Java---&gt;Installed JREs添加你的jdk路径<BR>在你需要默认的jdk路径前打勾。<BR>最后设置tomcat服务器<BR>Window---&gt;Perferences---&gt;MyEclipse----&gt;Application Servers---&gt;tomcat5<BR>使得tomcat server&nbsp;&nbsp; Enable<BR>然后选择tomcat Home，还要add JDK，选你刚才在java里面设置的jdk，然后要记得apply！</P>
<P>这样你的环境就配置好了！</P>
<P><BR>请看下篇实战篇，初学者愚见，请大侠们指点.写这些的目的是想和其他初学者一起进步</P><img src ="http://www.blogjava.net/RR00/aggbug/9157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RR00/" target="_blank">R.Zeus</a> 2005-08-04 04:06 <a href="http://www.blogjava.net/RR00/articles/9157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>