﻿<?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-杂家-随笔分类-10.Struts2</title><link>http://www.blogjava.net/super2/category/32730.html</link><description>学习复习</description><language>zh-cn</language><lastBuildDate>Fri, 13 Mar 2009 11:44:18 GMT</lastBuildDate><pubDate>Fri, 13 Mar 2009 11:44:18 GMT</pubDate><ttl>60</ttl><item><title>FreeMarker常用内容</title><link>http://www.blogjava.net/super2/archive/2009/03/13/259572.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Fri, 13 Mar 2009 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2009/03/13/259572.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/259572.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2009/03/13/259572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/259572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/259572.html</trackback:ping><description><![CDATA[如果某个变量test为null，在ftl页面中会报错，需要写${test?default("N/A")}，加入默认就没错了，还有就是if_exists,exists,!(叹号)等等。<br />
在&lt;#if test??&gt;&lt;/#if&gt;可以防止报错，不能写test==null这是不对的，还可以test?exists这样写。<br />
学学模板：common.ftl<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">#macro&nbsp;</span><span style="color: #ff0000;">html&nbsp;title</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">${title?html}</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">#nested</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">#macro</span><span style="color: #0000ff;">&gt;</span></div>
使用页面:test.ftl<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">#import&nbsp;</span><span style="color: #ff0000;">"common.ftl"&nbsp;as&nbsp;tl</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">@tl</span><span style="color: #ff0000;">.html&nbsp;title</span><span style="color: #0000ff;">="标题"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
这里写body的内容<br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">@tl.html</span><span style="color: #0000ff;">&gt;</span></div>
<br /><img src ="http://www.blogjava.net/super2/aggbug/259572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2009-03-13 16:56 <a href="http://www.blogjava.net/super2/archive/2009/03/13/259572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>附录二 使用Maven2 原型（Archetype） 建立Struts程序框架</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237996.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237996.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237996.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237996.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237996.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;"><br />
<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">使用如下命令可以建立一个<span lang="EN-US">Struts2 Starter</span>应用程序<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn archetype:create<span>&nbsp; </span><o:p></o:p></span></p>
<p style="text-indent: 20.6pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">-DgroupId=tutorial <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>-DartifactId=tutorial <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>-DarchetypeGroupId=org.apache.struts \<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>-DarchetypeArtifactId=struts2-archetype-starter \<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>-DarchetypeVersion=<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.5</st1:chsdate>-SNAPSHOT<o:p></o:p></span></p>
<p style="text-indent: 20.6pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">-DremoteRepositories=http://people.apache.org/repo/m2-snapshot-repository<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">参数含义：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<table style="border: medium none ; border-collapse: collapse;" class="MsoTableGrid" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="border-style: solid solid double; border-color: windowtext; border-width: 1pt 1pt 1.5pt; padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 50%; width: 95.4pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">参数<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="border-style: solid solid double none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-width: 1pt 1pt 1.5pt medium; padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 50%; width: 340.6pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">含义<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">groupId<o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">当前应用程序隶属的<span lang="EN-US">Group</span>的<span lang="EN-US">ID</span>，通常是公司所有应用程序的根目录，例如：<span lang="EN-US">com.jpleasure<o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">artifactId<span>&nbsp; </span><o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">当前应用程序的<span lang="EN-US">ID<o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">package<o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">代码生成时使用的根包的名字，如果没有给出，默认使用<span lang="EN-US">archetypeGroupId<o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">archetypeGroupId<o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">原型（<span lang="EN-US">archetype</span>）的<span lang="EN-US">Group ID</span>，因为我们这里使用的是<span lang="EN-US">Struts2</span>的原型，所以这里总是<span lang="EN-US">org.apache.struts<o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">archetypeArtifactId<span>&nbsp; </span><o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">原型（<span lang="EN-US">archetype</span>）<span lang="EN-US">ID<o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">archetypeVersion<span>&nbsp; </span><o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">原型（<span lang="EN-US">archetype</span>）版本<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 95.4pt;" valign="top" width="127">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">remoteRepositories<span>&nbsp; </span><o:p></o:p></span></p>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 340.6pt;" valign="top" width="454">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">包含原型（<span lang="EN-US">archetype</span>）的远程资源库的列表，如果部署在标准的<span lang="EN-US">maven</span>资源库或者本地，这不需要标记本项<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">一些相关的<span lang="EN-US">Maven</span>命令（注意要再项目目录中运行）<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">构建<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn install<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">创建<span lang="EN-US">IntelliJ IDEA</span>项目文件<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn idea:idea<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">创建<span lang="EN-US">Eclipse</span>项目文件<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>mvn eclipse:eclipse<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">运行测试<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn test<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">清除<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn clean<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">打包<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn package<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">获得需要的<span lang="EN-US">JAR</span>文件<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-indent: 10.3pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn initialize<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">使用<span lang="EN-US">Jetty</span>运行<span lang="EN-US"><o:p></o:p></span></span></p>
<span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">mvn jetty:run</span><img src ="http://www.blogjava.net/super2/aggbug/237996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:32 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>附录一 Maven2 安装</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237995.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:31:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237995.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237995.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237995.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Maven</span><span style="font-size: 10.5pt; font-family: 宋体;">是一个构建工具，详细信息请参考<span lang="EN-US">maven</span>官方网站（<span lang="EN-US"><a href="http://maven.apache.org/">http://maven.apache.org</a></span>）<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;" class="MsoNormal"><!--[if !supportLists]--><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp; </span></span></span><!--[endif]--><span style="font-size: 10.5pt; font-family: 宋体;">从<span lang="EN-US"><a href="http://maven.apache.org/">http://maven.apache.org</a> </span>下载最新的<span lang="EN-US">maven</span>压缩文件，在<span lang="EN-US">windows</span>操作系统下通常下载<span lang="EN-US">zip</span>文件，使用解压缩工具将文件解压缩到某个目录（以下称为<span lang="EN-US">Maven</span>安装目录）。<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin-left: 18pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">例如：<span lang="EN-US">E:\struts2\maven-<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.7</st1:chsdate></span>，这个目录的文件结构为：<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin-left: 18.05pt; text-indent: 20.6pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">E:\struts2\maven-<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.7</st1:chsdate><o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">bin\<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">boot\<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">conf\<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">lib\<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">LICENSE.TXT<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">NOTICE.TXT<o:p></o:p></span></p>
<p style="margin-left: 18.05pt; text-indent: 41.2pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">README.TXT<o:p></o:p></span></p>
<p style="margin-left: 18pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;" class="MsoNormal"><!--[if !supportLists]--><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp; </span></span></span><!--[endif]--><span style="font-size: 10.5pt; font-family: 宋体;">设置环境变量<span lang="EN-US">MVN_HOME</span>使其指向<span lang="EN-US">Maven</span>安装目录<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;" class="MsoNormal"><!--[if !supportLists]--><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>3.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp; </span></span></span><!--[endif]--><span style="font-size: 10.5pt; font-family: 宋体;">将<span lang="EN-US">%MVN_HOME%\bin</span>添加到系统环境变量<span lang="EN-US">Path</span>中<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;" class="MsoNormal"><!--[if !supportLists]--><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>4.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp; </span></span></span><!--[endif]--><span style="font-size: 10.5pt; font-family: 宋体;">开始<span lang="EN-US"> &gt; </span>运行中输入<span lang="EN-US">cmd </span>点击<span lang="EN-US">ok<o:p></o:p></span></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;" class="MsoNormal"><!--[if !supportLists]--><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>5.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp; </span></span></span><!--[endif]--><span style="font-size: 10.5pt; font-family: 宋体;">在弹出的命令行窗口中输入<span lang="EN-US">mvn &#8211;v </span>看到如下信息说明<span lang="EN-US">mvn</span>安装成功<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">E:\&gt;mvn -v<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Maven version: 2.0.7<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Java version: 1.6.0_01<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">OS name: "windows xp" version: "5.1" arch: "x86"<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Maven</span><span style="font-size: 10.5pt; font-family: 宋体;">将不同项目依赖的<span lang="EN-US">jar</span>文件做了统一管理，这些<span lang="EN-US">jar</span>文件都放在一个叫资源库的目录，这个目录通常情况下是用户<span lang="EN-US">HOME</span>目录下的<span lang="EN-US">/.m2/repository</span>目录，可以通过修改<span lang="EN-US">conf</span>目录下的<span lang="EN-US">settings.xml</span>文件中的<span lang="EN-US">&lt;localRepository&gt;</span>段来自定义资源库的位置，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;settings&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;localRepository&gt;C:/struts2/maven-<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.7</st1:chsdate>/repository&lt;/localRepository&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&#8230;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/settings&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">上述内容把<span lang="EN-US">maven</span>的资源库定位到了目录<span lang="EN-US">C:/struts2/maven-<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.7</st1:chsdate>/repository<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">另外，使用代理服务器上网的<span lang="EN-US">PC</span>机还可以修改<span lang="EN-US">settings.xml</span>文件中的<span lang="EN-US">&lt;proxies&gt;</span>段来利用代理服务器，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;proxies&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;proxy&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;id&gt;optional&lt;/id&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;active&gt;true&lt;/active&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;protocol&gt;http&lt;/protocol&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;username&gt;proxyuser&lt;/username&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;password&gt;proxypass&lt;/password&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;host&gt;proxy.jpleasure.com&lt;/host&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;port&gt;808&lt;/port&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;nonProxyHosts&gt;local.net,some.host.com&lt;/nonProxyHosts&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;/proxy&gt;<o:p></o:p></span></p>
<span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/proxies&gt;</span><img src ="http://www.blogjava.net/super2/aggbug/237995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:31 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十六章 锁机制(离线并发，乐观锁，悲观锁)</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237994.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237994.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237994.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237994.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237994.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-family: 宋体;">离线并发的来源</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">在</span><span lang="EN-US">Web</span><span style="font-family: 宋体;">项目中，离线并发显得尤其严重。例如，用户</span><span lang="EN-US">A</span><span style="font-family: 宋体;">和用户</span><span lang="EN-US">B</span><span style="font-family: 宋体;">同时修改数据库中的某张表的</span><span lang="EN-US">R</span><span style="font-family: 宋体;">行，加入</span><span lang="EN-US">R</span><span style="font-family: 宋体;">行有两个字段分别是</span><span lang="EN-US">C1</span><span style="font-family: 宋体;">，</span><span lang="EN-US">C2</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">假如按照如下过程修改：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>1 </span><span style="font-family: 宋体;">用户</span><span lang="EN-US">A</span><span style="font-family: 宋体;">将数据</span><span lang="EN-US">R</span><span style="font-family: 宋体;">（</span><span lang="EN-US">C1,C2</span><span style="font-family: 宋体;">）读取到</span><span lang="EN-US">A</span><span style="font-family: 宋体;">的浏览器中。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>2 </span><span style="font-family: 宋体;">用户</span><span lang="EN-US">B</span><span style="font-family: 宋体;">将数据</span><span lang="EN-US">R</span><span style="font-family: 宋体;">（</span><span lang="EN-US">C1,C2</span><span style="font-family: 宋体;">）读取到</span><span lang="EN-US">B</span><span style="font-family: 宋体;">的浏览器中。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>3 </span><span style="font-family: 宋体;">用户</span><span lang="EN-US">A</span><span style="font-family: 宋体;">在浏览器上将数据修改为</span><span lang="EN-US">R</span><span style="font-family: 宋体;">（</span><span lang="EN-US">C1&#8217;</span><span style="font-family: 宋体;">，</span><span lang="EN-US">C2</span><span style="font-family: 宋体;">），同时更新到数据库。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>4 </span><span style="font-family: 宋体;">用户</span><span lang="EN-US">B</span><span style="font-family: 宋体;">在浏览器上将数据修改为</span><span lang="EN-US">R</span><span style="font-family: 宋体;">（</span><span lang="EN-US">C1</span><span style="font-family: 宋体;">，</span><span lang="EN-US">C2&#8217;</span><span style="font-family: 宋体;">），同时更新到数据库。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">上述过程存在两个问题，第一，第</span><span lang="EN-US">4</span><span style="font-family: 宋体;">步</span><span lang="EN-US">B</span><span style="font-family: 宋体;">在修改数据的时候数据库中的数据和</span><span lang="EN-US">B</span><span style="font-family: 宋体;">的浏览器中数据已经不一致了；第二，如果程序按照哪个字段变化在数据库中更新哪个字段的方式处理的话，那么经过上述四步修改，数据库中</span><span lang="EN-US">R</span><span style="font-family: 宋体;">行的内容是（</span><span lang="EN-US">C1&#8217;,C2&#8217;</span><span style="font-family: 宋体;">），这和</span><span lang="EN-US">A</span><span style="font-family: 宋体;">或者</span><span lang="EN-US">B</span><span style="font-family: 宋体;">的想法都不同（</span><span lang="EN-US">A</span><span style="font-family: 宋体;">认为是（</span><span lang="EN-US">C1&#8217;</span><span style="font-family: 宋体;">，</span><span lang="EN-US">C2</span><span style="font-family: 宋体;">），</span><span lang="EN-US">B</span><span style="font-family: 宋体;">认为是（</span><span lang="EN-US">C1</span><span style="font-family: 宋体;">，</span><span lang="EN-US">C2&#8217;</span><span style="font-family: 宋体;">））。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">上述过程中</span><span lang="EN-US">A</span><span style="font-family: 宋体;">对数据库的修改过程或者</span><span lang="EN-US">B</span><span style="font-family: 宋体;">对数据库的修改过程，都是无法根据数据库的最新内容做修改，所以成为离线。</span><span lang="EN-US">A</span><span style="font-family: 宋体;">和</span><span lang="EN-US">B</span><span style="font-family: 宋体;">同时对记录</span><span lang="EN-US">R</span><span style="font-family: 宋体;">进行就该叫离线。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">以上的环境叫离线并发。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">那么如何解决离线并发过程中遇到的问题呢？我们引入锁机制。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">锁机制</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">锁机制，就是在需要修改的数据上加互斥锁，通过互斥锁避免数据被同时修改。锁机制更具其应用环境又分为<strong>乐观锁</strong>和<strong>悲观锁</strong></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">乐观锁</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">乐观锁，指认为冲突很少发生，所以只是在数据修改的时候比较修改的基础数据和数据库中的数据是否相同，相同则修改，否则提示用户重新装入数据库中已经变化的数据。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">实现方法</span><span lang="EN-US">1</span><span style="font-family: 宋体;">：在进行</span><span lang="EN-US">update</span><span style="font-family: 宋体;">的时候使用</span><span lang="EN-US">where</span><span style="font-family: 宋体;">条件，在</span><span lang="EN-US">Where</span><span style="font-family: 宋体;">标间中比较所有上一步中查询得到的数据。如果数据库中的数据没有变化，则</span><span lang="EN-US">update</span><span style="font-family: 宋体;">可以更新到内容，否则</span><span lang="EN-US">update</span><span style="font-family: 宋体;">语句不能更新到内容，可以根据</span><span lang="EN-US">update</span><span style="font-family: 宋体;">的返回值确定更新是否成功。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">实现方法</span><span lang="EN-US">2</span><span style="font-family: 宋体;">：在每一个表中追加一个特殊字段，类型为</span><span lang="EN-US">timestamp</span><span style="font-family: 宋体;">，每次更新的时候比较这个字段的值是否一致，如果一致，则更新，同时将这个字段更新为当前时间，否则，说明数据已经变更。这也可以使用</span><span lang="EN-US">update</span><span style="font-family: 宋体;">加上</span><span lang="EN-US">where</span><span style="font-family: 宋体;">实现。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">悲观锁</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">悲观锁指，需要修改的数据，在读取的时候就对数据加锁，其他用户在准备修改，读取数据的阶段判断数据是否上锁，以此来决定是否进行修改前的读操作。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">实现方法：</span></p>
<p style="margin-left: 21pt;" class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">通常在数据库中建立一张</span><span lang="EN-US">lock</span><span style="font-family: 宋体;">表，该表的字段包括，表明，唯一索引，时间，用户信息等。</span></p>
<p style="margin-left: 21pt;" class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">在用户读取数据准备修改的时候，首先判断</span><span lang="EN-US">lock</span><span style="font-family: 宋体;">表中是否存在自己将要读取的数据。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">如果不存在，则在</span><span lang="EN-US">lock</span><span style="font-family: 宋体;">表中添加一条记录，记录对那张表的哪行数据进行修改；如果存在，在判断时间字段是否超时。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">如果超时，则更新</span><span lang="EN-US">lock</span><span style="font-family: 宋体;">表中本条记录的时间字段。<strong>（防止死锁的必要手段）</strong></span></p>
<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal"><span style="font-family: 宋体;">如果存在，也不超时，说明本条记录正在被其他用户修改，则返回并发信息。</span></p><img src ="http://www.blogjava.net/super2/aggbug/237994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:27 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十五章 长时间的处理（Long Lived Action）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237992.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237992.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237992.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237992.html</trackback:ping><description><![CDATA[<div><strong><span style="font-size: 10.5pt;">双击制御</span></strong></div>
<div><span style="font-size: 10.5pt;">有些时候一些操作会非常的耗费时间（Long Lived Operation），例如这个数据库的导出，表表生成等。有些时候程序的使用者看到很长时间服务器没有反应，倾向于多次点击提交按钮。这样恰恰相反，由于重新使服务器运行相同的长时间操作，反而让反应时间更慢。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">我们如何来制御这样的操作呢？</span></div>
<div><span style="font-size: 10.5pt;">我们能不能在每个页面生成的时候，自动生成一个特殊的隐藏字段，这个隐藏字段具有唯一性。每次向服务器提交请求的时候，服务器就记录下这个隐藏字段，当在看到有相同的特殊字段的内容提交时，服务器认为这是重复提交，将画面定位到一个特殊的画面来提示客户重复提交了数据。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">在Struts2中，内容了对双击的制御操作，特殊的隐藏字段叫做token。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">如何在生成页面的时候生成token字段？</span></div>
<div><span style="font-size: 10.5pt;">使用token标签。</span></div>
<div><span style="font-size: 10.5pt;">代码如下：</span></div>
<div><span style="font-size: 10.5pt;">&lt;s:url id="formUrl" action="longLivedTokenAction"/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&lt;s:form action="%{formUrl}" method="post"&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>&lt;s:token /&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:textfield name="name" label="Name"/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:textfield name="password" label="Password"/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:submit/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&lt;/s:form&gt;</span></div>
<div><span style="font-size: 10.5pt;">其中<strong>&lt;s:token /&gt;</strong>标签用来生成一个唯一的隐藏字段，在运行的时候生成的内容如下：</span></div>
<div><span style="font-size: 10.5pt;">&lt;input type="hidden" name="struts.token" value="C21ZWHEH0Q4B6FY15ZO5BFM1I9W8SIQH" /&gt;</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">如何在服务器上记录已经提交的token？</span></div>
<div><span style="font-size: 10.5pt;">可以使用token intercepter。</span></div>
<div><span style="font-size: 10.5pt;">代码如下：</span></div>
<div><span style="font-size: 10.5pt;">&lt;action name="longLivedTokenAction" class="com.jpleasure.LongLivedTokenAction"&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>&lt;interceptor-ref name="token"/&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;interceptor-ref name="basicStack"/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;/jsp/longLived.jsp&lt;/result&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>&lt;result name="invalid.token"&gt;/jsp/invalidToken.jsp&lt;/result&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&lt;/action&gt;</span></div>
<div><span style="font-size: 10.5pt;">上述<strong>&lt;interceptor-ref name="token"/&gt;</strong>表
示所有的请求必须经过token Interceptor，token
Interceptor作用就是纪录所有已经提交的token。那么发现提交的token被重复提交的时候怎么办呢？也许大家已经猜到了，他会重定向到
invalid.token所指向的页面，也就是/jsp/invalidToken.jsp。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">基于Interceptor的执行顺序按照struts.xml中定义的顺序，为了更早的结束重复提交的处理，应该将Token Interceptor放在所有Interceptor的最面。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">有了上述的Token Interceptor，可以防止客户重复提交，大大地降低了服务器的负荷。但是对用户来说，可能会很不方便，一不小心点击了提交按钮，进入到了invalid.token页面，就再也回不去了，上述的操作就再也看不见了。</span></div>
<div>&nbsp;</div>
<div><strong><span style="font-size: 10.5pt;">等待画面</span></strong></div>
<div><span style="font-size: 10.5pt;">我们能不能提供一个等待画面呢？</span></div>
<div><span style="font-size: 10.5pt;">每次我们提交之后画面立即迁移到一个类似状态条的画面，这个画面不断的向服务器请求，以确定Action是否执行完毕，一旦Action执行完毕，立即定位到正确的画面。这样不是更好。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">Struts2</span><span style="font-size: 10.5pt;">也提供了对等待画面的支持。</span></div>
<div><span style="font-size: 10.5pt;">首先当我们提交完成的时候，画面会前一到一个叫做等待画面的页面。等待画面定时的向服务器提交请求，以确定服务器操作是否完成。另外正在执行的Action需要有一个拦截对象，拦截等待页面的每一次请求，告诉等待页面是否处理完成。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">首先我们需要定义，等待页面和Action是否完成的拦截对象</span></div>
<div><span style="font-size: 10.5pt;">&lt;action name="longLivedAction" class="com.jpleasure.LongLivedAction"&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;interceptor-ref name="completeStack"/&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>&lt;interceptor-ref name="execAndWait"/&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>&nbsp;&lt;result name="wait"&gt;/jsp/wait.jsp&lt;/result&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result name="success"&gt;/jsp/after.jsp&lt;/result&gt;</span></div>
<div><span style="font-size: 10.5pt;">&lt;/action&gt;</span></div>
<div><strong><span style="font-size: 10.5pt;">&lt;result name="wait"&gt;/jsp/wait.jsp&lt;/result&gt;</span></strong><span style="font-size: 10.5pt;">定义了等待画面是/jsp/wait.jsp，当我们向服务器提交请求之后，画面会迁移到这个画面。</span></div>
<div><strong><span style="font-size: 10.5pt;">&lt;interceptor-ref name="execAndWait"/&gt;</span></strong><span style="font-size: 10.5pt;">定义了一个拦截对象，告诉等待画面是否完成了长时间操作。</span></div>
<div><span style="font-size: 10.5pt;">那么等待画面如何定期的查询呢？</span></div>
<div><span style="font-size: 10.5pt;">之需要一个指向该Action调用的一个不断地刷新即可。代码如下：</span></div>
<div><span style="font-size: 10.5pt;">&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;</span></div>
<div><span style="font-size: 10.5pt;">&lt;%@taglib prefix="s" uri="/struts-tags" %&gt;</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">&lt;html&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&lt;head&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp; &lt;title&gt;Please wait&lt;/title&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&nbsp;&nbsp; <strong>&lt;meta http-equiv="refresh" content="5;url=&lt;s:url includeParams='all'/&gt; "/&gt;</strong></span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&lt;/head&gt;</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;&lt;body&gt;</span></div>
<div><span style="font-size: 10.5pt;">&lt;/body&gt;</span></div>
<div><span style="font-size: 10.5pt;">&lt;/html&gt;</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">&nbsp;Please wait while we process your request.</span></div>
<div><span style="font-size: 10.5pt;">&nbsp;<strong>&lt;a href="&lt;s:url includeParams="all" /&gt;"&gt; Click Here&lt;/a&gt;</strong> if this page does not reload automatically.</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">上述黑体部分表示，一旦画面建立，就建立了一个刷新，每5秒钟刷新一次，刷新的廉洁为</span></div>
<div><span style="font-size: 10.5pt;">url=&lt;s:url includeParams=&#8221;all&#8221;/&gt;</span><span style="font-size: 10.5pt;">，meta是标准浏览器支持的内容之一。</span></div>
<div><span style="font-size: 10.5pt;">在运行的时候可以看到生成需下的内容：</span></div>
<div><span style="font-size: 10.5pt;">&lt;meta http-equiv="refresh" </span></div>
<div style="text-indent: 20.6pt;"><span style="font-size: 10.5pt;">content="5;url=/wait/jsp/longLivedAction.action?name=zhangsf&amp;amp;value=119 "/&gt;</span></div>
<div><span style="font-size: 10.5pt;">如果浏览器不支持自动刷新也不要紧，可以让客户自己点击Click Here来确定操作是否完成。</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 10.5pt;">其实这里最重要的是<strong>execAndWait </strong>Interceptor，每次向它拦截的Action发送请求的时候，execAndWait会确定Action操作是否完成，如果完成，将画面定位到对应的页面（通常是SUCCESS指向的页面），否则纸箱wait指向的页面。</span></div><img src ="http://www.blogjava.net/super2/aggbug/237992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:26 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十四章 文件上传与下载</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237991.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237991.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237991.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237991.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237991.html</trackback:ping><description><![CDATA[<div>文件上传和下载</div>
<div>&nbsp;</div>
<div><strong>一些需要注意的地方：</strong></div>
<div>&nbsp;</div>
<div>在处理到文件上传和下载的时候首先说明一些需要注意的地方。</div>
<div>&nbsp;</div>
<div>1) &nbsp;使用HTML默认的功能不能上传目录，这里的默认功能指的是不做额外的开发（例如ActiveX）的情况下。</div>
<div>&nbsp;<span>&nbsp;&nbsp;</span>所以客户如果跟你说：&#8220;我有一个目录需要上传，能不能让我选择目录，然后一下子上传整个目录？&#8221;，出于工作量的考虑你最好回绝他，然后使用动态增加的方式来动态的支持多个上传文件，或者更简单的让客户指定所有的上传文件。</div>
<div>&nbsp;</div>
<div>2) &nbsp;不能设置文件上传字段的默认值。</div>
<div>&nbsp;<span>&nbsp;&nbsp;</span>出于安全的考虑，HTML不支持默认的文件上传字段的默认值。例如，在你不知道的情况下，你访问了某个网站的某个页面，结果你的password文件被上传上去了，哈哈，你有危险了。</div>
<div>&nbsp;<span>&nbsp;&nbsp;</span>所以如果客户跟你说：&#8220;我能不能打开画面的时候就设置好上传的文件？&#8221;，处于工作量和技术难度的考虑，你最好说：&#8220;哦，为了您的安全，还是不要这样子做了&#8221;，呵呵，</div>
<div>&nbsp;</div>
<div>3）文件类型</div>
<div><span>&nbsp;&nbsp;&nbsp; </span>每一种文件都有类型，一般情况下扩展明决定了文件的类型。。所有文件类型的列表可以从这个目录中找到，相信可以为你提供参考：</div>
<div>TOMCAT_HOME\conf\web.xml<span>&nbsp;&nbsp; </span></div>
<div>&#8230;</div>
<div>&lt;mime-mapping&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;extension&gt;bin&lt;/extension&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mime-type&gt;application/octet-stream&lt;/mime-type&gt;</span></div>
<div>&lt;/mime-mapping&gt;</div>
<div>&lt;mime-mapping&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;extension&gt;gif&lt;/extension&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mime-type&gt;image/gif&lt;/mime-type&gt;</span></div>
<div>&lt;/mime-mapping&gt;</div>
<div>&#8230;</div>
<div>4) 下载文件时本页面内部打开，还是弹出另存对话框？</div>
<div>文件下载的时候可以在本页面打开，和可以弹出另存对话框。选择条件是设置文件下载的：contentDisposition，inline表示当前页面打开，attachment表示弹出另存对话框。</div>
<div>例如：</div>
<div>contentDisposition=inline;filename="image.jpg"<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>当前画面打开</div>
<div>contentDisposition=attachment;filename="image.jpg"<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>打开另存对话框</div>
<div>&nbsp;</div>
<div>5）文件上传需要使用method="post" 和 enctype="multipart/form-data"类型的form</div>
<div>&nbsp;</div>
<div><strong>使用Struts2</strong><strong>上传文件：</strong></div>
<div>Struts文件上传需要使用File Upload Filter。Filter Upload Filter使用一些默认的规则：</div>
<div>Form中的&lt;s:file
name="image"&gt;&lt;/s:file&gt;标签对应着Action类中的三个属性分别是：上传文件（java.io.File类
型），文件名（java.lang.String类型），文件类型（java.lang.String类型，例如：image/jpeg）。命名规约为：</div>
<div>文件：名字与&lt;s:file&gt;标签中的name属性一致，这里为：image</div>
<div>文件名：文件 + FileName，这里为：imageFileName</div>
<div>文件类型：文件 + ContentType，这里为：imageContentType</div>
<div>&nbsp;</div>
<div>所以针对上述&lt;s:file name="image"&gt;&lt;/s:file&gt;表示啊的上传文件的JSP和Action类被别为：</div>
<div>&nbsp;</div>
<div>imageUpload.jsp：</div>
<div>&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;</div>
<div>&lt;%@taglib prefix="s" uri="/struts-tags" %&gt;</div>
<div>&nbsp;</div>
<div>&lt;html&gt;</div>
<div>&lt;head&gt;&lt;title&gt;Image Upload&lt;/title&gt;&lt;/head&gt;</div>
<div>&lt;body&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;h1&gt; Image Upload Page &lt;/h1&gt;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;s:form action="imageUpload" method="post" enctype="multipart/form-data"&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:file name="image"&gt;&lt;/s:file&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:submit&gt;&lt;/s:submit&gt;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;/s:form&gt;</span></div>
<div>&lt;/body&gt;</div>
<div>&lt;/html&gt;</div>
<div>&nbsp;</div>
<div>ImageUploadAction.java：</div>
<div>package com.jpleasure;</div>
<div>&nbsp;</div>
<div>import com.opensymphony.xwork2.ActionSupport;</div>
<div>&nbsp;</div>
<div>import java.io.File;</div>
<div>import java.io.InputStream;</div>
<div>import java.io.FileInputStream;</div>
<div>import java.io.FileNotFoundException;</div>
<div>&nbsp;</div>
<div>public class ImageUploadAction extends ActionSupport {</div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; private File image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; private String imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; private String imageContentType;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public File getImage() {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImage(File image) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.image = image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String getImageFileName() {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImageFileName(String imageFileName) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageFileName = imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String getImageContentType() {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return imageContentType;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImageContentType(String imageContentType) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageContentType = imageContentType;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String execute() {</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (image != null) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file name is:" + this.imageFileName);</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file content type is:" + this.imageContentType);</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file length is:" + this.image.length());</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>}</div>
<div>&nbsp;</div>
<div>Struts.xml配置文件：</div>
<div>&lt;action name="imageUpload" class="com.jpleasure.ImageUploadAction"&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;/success.jsp&lt;/result&gt;</span></div>
<div>&lt;/action&gt;</div>
<div>&nbsp;</div>
<div>这样当我们选中上传文件，提交的时候：文件内容会以File类型的方式放在image声明的变量中。文件的名字将会被放在imageFileName命名的变量中，文件的类型被放在imageContentType命名的变量中。</div>
<div>&nbsp;</div>
<div><strong>文件下载：</strong></div>
<div>文件下载需要使用一个特殊的Result，stream类型的Result。Stream类型的Result主要用来处理文件下载操作。</div>
<div>处理原理为：所有的下载文件都是将一个二进制的流写入到HttpResponse中去。在Action类中定义一个InputSream类型的二进制流，在Result返回给用户的时候返回给用户。</div>
<div>&nbsp;</div>
<div>扩展上述的代码，将上传来的文件直接下载给用户：</div>
<div>ImageUploadAction中需要追加一个InputSream类型的对象，并且指向上传的文件，代码如下，红色部分表示变化：</div>
<div>package com.jpleasure;</div>
<div>&nbsp;</div>
<div>import com.opensymphony.xwork2.ActionSupport;</div>
<div>&nbsp;</div>
<div>import java.io.File;</div>
<div>import java.io.InputStream;</div>
<div>import java.io.FileInputStream;</div>
<div>import java.io.FileNotFoundException;</div>
<div>&nbsp;</div>
<div>public class ImageUploadAction extends ActionSupport {</div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; private File image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; private String imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; private String imageContentType;</span></div>
<div>&nbsp;</div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp; private InputStream imageInputStream = null;</span></strong></div>
<div><strong>&nbsp;</strong></div>
<div><strong>&nbsp;</strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp; public InputStream getImageInputStream() {</span></strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return imageInputStream;</span></strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp; }</span></strong></div>
<div><strong>&nbsp;</strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp; public void setImageInputStream(InputStream imageInputStream) {</span></strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageInputStream = imageInputStream;</span></strong></div>
<div><strong><span style="color: red;">&nbsp;&nbsp;&nbsp; }</span></strong></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public File getImage() {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImage(File image) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.image = image;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String getImageFileName() {</span></div>
<div>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImageFileName(String imageFileName) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageFileName = imageFileName;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String getImageContentType() {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return imageContentType;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public void setImageContentType(String imageContentType) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageContentType = imageContentType;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp; public String execute() {</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (image != null) {</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file name is:" + this.imageFileName);</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file content type is:" + this.imageContentType);</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file length is:" + this.image.length());</span></div>
<div>&nbsp;</div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.imageInputStream = new FileInputStream (image);</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (FileNotFoundException e) {</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<div style="text-indent: 57.75pt;"><span style="color: red;">&nbsp;}</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; }</span></div>
<div>}</div>
<div>配置文件为，红色为变化部分：</div>
<div>&lt;action name="imageUpload" class="com.jpleasure.ImageUploadAction"&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">&nbsp;&lt;result name="success" type="stream"&gt;</span></span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="contentType"&gt;image/pjpeg&lt;/param&gt;</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="inputName"&gt;imageInputStream&lt;/param&gt;</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="contentDisposition"&gt;attachment;filename="image.jpg"&lt;/param&gt;</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="bufferSize"&gt;1024&lt;/param&gt;</span></div>
<div><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/result&gt;</span></div>
<div>&lt;/action&gt;</div>
<div>ContentType表示下载文件的类型。</div>
<div>InputName表示Action类中用来下载文件的字段的名字。</div>
<div>ContentDisposition用来控制文件下载的一些信息，包括是否打开另存对话框，下载文件名等。</div>
<div>BufferSize表示文件下载时使用的缓冲区的大小。</div>
<div>&nbsp;</div>
<div><strong>实际项目开发的考虑：</strong></div>
<div>控制上传文件的类型和最大允许上传文件的size</div>
<div>使用File Upload Intercepter的参数可盈控制上传文件的类型和最大允许上传文件的size。例如：</div>
<div>&lt;struts&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;package name="myPackage" extends="struts-default"&gt;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;interceptor-ref name="fileUpload"&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="maximumSize"&gt;2MB&lt;/param&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="allowedTypes"&gt;text/html,image/jpeg&lt;/param&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/interceptor-ref&gt;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;interceptor-ref name="basicStack"/&gt;</span></div>
<div>&nbsp;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action name="imageUpload" class="com.jpleasure.ImageUploadAction"&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result name="success" type="stream"&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="contentType"&gt;image/pjpeg&lt;/param&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="inputName"&gt;imageInputStream&lt;/param&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="contentDisposition"&gt;</span></div>
<div style="text-indent: 105pt;">attachment;filename="image.jpg"</div>
<div style="text-indent: 84pt;">&lt;/param&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="bufferSize"&gt;1024&lt;/param&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/result&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/action&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;/package&gt;</span></div>
<div>&lt;/struts&gt;</div>
<div>&nbsp;</div>
<div>上述表示允许上传jpeg和html类型的文件，且最大文件上传size为2MB</div>
<div>&nbsp;</div>
<div>显示错误信息：</div>
<div>可以使用如下key表示的message来显示文件上传出错的提示信息：</div>
<p>
</p>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="border: 1pt solid windowtext; padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 213.05pt;" valign="top" width="284">
            <div><strong>消息Key</strong></div>
            </td>
            <td style="border-style: solid solid solid none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 213.05pt;" valign="top" width="284">
            <div><strong>说明</strong></div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>struts.messages.error.uploading</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>文件无法正常上传时的公共错误</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>struts.messages.error.file.too.large</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>文件大小超过最大允许size时的错误提示</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>struts.messages.error.content.type.not.allowed</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 213.05pt;" valign="top" width="284">
            <div>文件类型不在上传文件允许类型中的错误提示</div>
            </td>
        </tr>
    </tbody>
</table><img src ="http://www.blogjava.net/super2/aggbug/237991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:25 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十三章 Exception Architecture</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237990.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:23:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237990.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237990.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237990.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237990.html</trackback:ping><description><![CDATA[<p>我们看一下应用程序开发中两类比较常见的异常情况，第一类是诸如数据库无法链接，配置文件不存在，SQL语句编译错误等的系统级别的异常，一旦这种
异常发生基本上系统无法正常运行。另一类是诸如数据库中的内容不存在，格式不正确，业务逻辑不满足要求等的异常，这种异常往往只影响某一条的数据，不会对
系统的正常运行有影响。</p>
<h2>Java中的两类异常</h2>
<p>Java中的异常分为两种类型运行时的异常（RuntimeException）和检查异常（Checked Exception）。</p>
<p>&nbsp;</p>
<p>运行时的异常（RuntimeException）可以在程序运行的时候动态的抛出，但是不需要在方法接口中声明要跑出的运行时异常，也不需要在方
法调用的时候做try-catch处理。系统的运行时异常是指java.lang.RuntimeExceptioin或者他的子类型。
RuntimeException在逻辑上的含义是：</p>
<p>&nbsp;</p>
<p>检查异常（Checked Exception）必须要在方法的接口中声明，并且在使用方法的时候，其抛出的Checked Exception必须使用try-catch处理，检查异常指的是java.lang.Exception或者他的子类型。</p>
<p>&nbsp;</p>
<p>注意：有一点需要指出，java.lang.RuntimeException是java.lang.Exception的子类型。所以上述中说的
检查异常（Checked
Exception）指的是java.lang.Exception和其他的非java.lang.RuntimeException子类的子类型。</p>
<p>&nbsp;</p>
<p>如下代码展示了RuntimeException的使用：</p>
<p>&nbsp;</p>
<p>package com.jpleasure.exception;</p>
<p>/**<br />
&nbsp;* System Exception<br />
&nbsp;* @author <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#122;&#104;&#97;&#111;&#64;&#100;&#108;&#46;&#99;&#110;">mazhao@dl.cn</a><br />
&nbsp;*<br />
&nbsp;*/<br />
public class SystemException extends RuntimeException {</p>
<p>&nbsp;public SystemException() {<br />
&nbsp;}</p>
<p>&nbsp;public SystemException(String message) {<br />
&nbsp;&nbsp;super(message);<br />
&nbsp;}</p>
<p>&nbsp;public SystemException(Throwable cause) {<br />
&nbsp;&nbsp;super(cause);<br />
&nbsp;}</p>
<p>&nbsp;public SystemException(String message, Throwable cause) {<br />
&nbsp;&nbsp;super(message, cause);<br />
&nbsp;}<br />
}<br />
</p>
<p>以下代码可以编译通过，运行的时候抛出异常：</p>
<p>package com.jpleasure.exception;</p>
<p>public class Main {<br />
&nbsp;public static void main(String ... args ) {<br />
&nbsp;&nbsp;testRuntimeException();<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public static void testRuntimeException() {<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;methodThrowsRuntimeException();<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;private static void methodThrowsRuntimeException() {<br />
&nbsp;&nbsp;if(true) {<br />
&nbsp;&nbsp;&nbsp;throw new SystemException("Hello World!");<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</p>
<p>运行的时候输出内容为：</p>
<p>&nbsp;Exception in thread "main" com.jpleasure.exception.SystemException: Hello World!<br />
&nbsp;at com.jpleasure.exception.Main.methodThrowsRuntimeException(Main.java:17)<br />
&nbsp;at com.jpleasure.exception.Main.testRuntimeException(Main.java:11)<br />
&nbsp;at com.jpleasure.exception.Main.main(Main.java:5)<br />
</p>
<p>以下代码展示了Exception的使用：</p>
<p>&nbsp;package com.jpleasure.exception;</p>
<p>/**<br />
&nbsp;* Application Exception <br />
&nbsp;* @author <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#122;&#104;&#97;&#111;&#64;&#100;&#108;&#46;&#99;&#110;">mazhao@dl.cn</a><br />
&nbsp;*<br />
&nbsp;*/<br />
public class ApplicationException extends Exception {</p>
<p>&nbsp;public ApplicationException() {<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</p>
<p>&nbsp;public ApplicationException(String message) {<br />
&nbsp;&nbsp;super(message);<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</p>
<p>&nbsp;public ApplicationException(Throwable cause) {<br />
&nbsp;&nbsp;super(cause);<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</p>
<p>&nbsp;public ApplicationException(String message, Throwable cause) {<br />
&nbsp;&nbsp;super(message, cause);<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</p>
<p>}<br />
</p>
<p>异常使用代码：</p>
<p>package com.jpleasure.exception;</p>
<p>public class Main2 {</p>
<p>&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;</p>
<p>&nbsp;}<br />
&nbsp;<br />
&nbsp;public static void testCheckedException() {<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;methodThrowsCheckedException();<br />
&nbsp;&nbsp;}<strong> catch (ApplicationException e) {<br />
&nbsp;&nbsp;&nbsp;// 异常处理代码<br />
&nbsp;&nbsp;}<br />
</strong>&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;private static void methodThrowsCheckedException() <strong>throws ApplicationException</strong> {<br />
&nbsp;&nbsp;if(true) {<br />
&nbsp;&nbsp;&nbsp;throw new ApplicationException("Hello World!");<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>}<br />
</p>
<p>由于ApplicationException是Checked Exception，所以在方法的接口中必须加以声明，并且在使用的时候必须包括在try-catch代码块中。</p>
<h2>应用程序开发中的异常</h2>
<p>如上述代码中说明的那样处于使用方便我们总是将系统异常设置为RuntimeException的子类，在统一的地方处理。</p>
<p>&nbsp;</p>
<p>为什么要将系统异常设置为Runtime的呢？</p>
<p>&nbsp;</p>
<p>try-catch块主要是为了在异常发生的时候有可以挽救的方式，所以会在try部分异常发生的时候进入catch部分，但是系统异常（例如数据
库无法链接，配置文件不存在等）一旦发生基本上没有挽救的办法，所以将系统异常声明为RuntimeException的子类。</p>
<p>另外，系统异常是一种很少会发生的异常，所以在开发中基本不需要考虑，所以将系统异常生命为RuntimeException的子类，这样在开发的时候基本不需要考虑系统异常发生的情况，只需要统一的做错误处理即可。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>应用程序异常通常设置为Checked Exception。需要在使用的地方逐个处理。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>异常消息定义</h2>
<p>异常消息通常不会在构造异常的时候传入，通常情况下在构造异常的时候传入的是异常消息的编号。</p>
<p>&nbsp;</p>
<p>编号一般包含的内容有：系统ID，子系统ID，消息类型，流水号等。系统ID，子系统ID，流水号等都比较好理解，那么消息类型是什么呢？我们的消
息常见的有以下一些类型：提示性的，警告性的，错误性的。所以我们可以分别以C（Confirm），W（Warnning），E（Error）来区分消息
的类型</p>
<p>&nbsp;</p>
<p>消息一般存储在属性文件（Properties）中使用ResourceBundle类或者Properties类来获取。当使用到多国语言的错误消息的时候需要使用ResourceBundle类。</p>
<p>有些时候也可以存储在代码中，这个时候需要使用到ListResourceBundle类。</p>
<h2>异常发生时的操作</h2>
<p>第一就是要记录错误日志，需要将类，方法，操作数据，异常类型，异常内容的信息记录下来，便于系统维护人员分析问题数据。</p>
<p>第二及时要抛出错误信息，反馈给系统用户，让客户知道系统无法处理他的当前操作。如果有必要还需要提示客户可能的错误情况，希望用户改善。</p>
<p>&nbsp;</p>
<h2 goog_ds_charindex="3807">如何获得异常的详细信息</h2>
<p goog_ds_charindex="3820">从异常中可以获得详细的抛出信息，例如都那些代码涉及到这个异常，分别在那些类的那些方法中，代码行数是多少，代码文件名字是什么等。</p>
<p goog_ds_charindex="3885">例如类LoginLogic调用了LoginDao，而Main调用了LoginLogic，代码为：</p>
<p goog_ds_charindex="3935">&nbsp;</p>
<p goog_ds_charindex="3936">package com.jpleasure.exception;</p>
<p goog_ds_charindex="3970">/**<br goog_ds_charindex="3974" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="4003" />
&nbsp;* User: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#46;&#122;&#104;&#97;&#111;&#64;&#100;&#108;&#46;&#99;&#110;" goog_ds_charindex="4013">ma.zhao@dl.cn</a><br goog_ds_charindex="4028" />
&nbsp;* Date: 2007-9-3<br goog_ds_charindex="4046" />
&nbsp;* Time: 22:55:47<br goog_ds_charindex="4064" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="4129" />
&nbsp;*/<br goog_ds_charindex="4133" />
public class LoginDao {<br goog_ds_charindex="4157" />
&nbsp;&nbsp;&nbsp; public void testLogin() throws SystemException {<br goog_ds_charindex="4210" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(true) {<br goog_ds_charindex="4229" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new SystemException("System Exception Occurs!");<br goog_ds_charindex="4296" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4306" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4312" />
}<br goog_ds_charindex="4314" />
</p>
<p goog_ds_charindex="4316">package com.jpleasure.exception;</p>
<p goog_ds_charindex="4350">import java.util.Random;</p>
<p goog_ds_charindex="4376">/**<br goog_ds_charindex="4380" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="4409" />
&nbsp;* User: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#46;&#122;&#104;&#97;&#111;&#64;&#100;&#108;&#46;&#99;&#110;" goog_ds_charindex="4419">ma.zhao@dl.cn</a><br goog_ds_charindex="4434" />
&nbsp;* Date: 2007-9-3<br goog_ds_charindex="4452" />
&nbsp;* Time: 22:56:30<br goog_ds_charindex="4470" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="4535" />
&nbsp;*/<br goog_ds_charindex="4539" />
public class LoginLogic {<br goog_ds_charindex="4565" />
&nbsp;&nbsp;&nbsp; private LoginDao dao = new LoginDao();</p>
<p goog_ds_charindex="4609">&nbsp;&nbsp;&nbsp; public void testLogin() throws ApplicationException {</p>
<p goog_ds_charindex="4668">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Random randam = new Random(System.currentTimeMillis());<br goog_ds_charindex="4732" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int randamInt = randam.nextInt();</p>
<p goog_ds_charindex="4775">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (randamInt % 2 == 0) {<br goog_ds_charindex="4809" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dao.testLogin();<br goog_ds_charindex="4838" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br goog_ds_charindex="4855" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ApplicationException("Application Exception Occurs!");<br goog_ds_charindex="4932" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4942" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4948" />
}</p>
<p goog_ds_charindex="4775"><br goog_ds_charindex="4950" />
&nbsp;</p>
<p goog_ds_charindex="4952">异常处理代码：</p>
<p goog_ds_charindex="4952">&nbsp;</p>
<p goog_ds_charindex="4952">package com.jpleasure.exception;</p>
<p goog_ds_charindex="4952">/**<br />
&nbsp;* Created by IntelliJ IDEA.<br />
&nbsp;* User: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#46;&#122;&#104;&#97;&#111;&#64;&#100;&#108;&#46;&#99;&#110;">ma.zhao@dl.cn</a><br />
&nbsp;* Date: 2007-9-3<br />
&nbsp;* Time: 22:57:38<br />
&nbsp;* To change this template use File | Settings | File Templates.<br />
&nbsp;*/<br />
public class Main {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {</p>
<p goog_ds_charindex="4952">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LoginLogic logic = new LoginLogic();</p>
<p goog_ds_charindex="4952">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; logic.testLogin();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (ApplicationException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (SystemException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="4952">&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="4952">&nbsp;&nbsp;&nbsp; private static void printException(Exception e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String msg = e.getMessage();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("exception message:" + msg);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StackTraceElement[] stes = e.getStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; stes.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printStackTraceElement(stes[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="4952">&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; private static void printStackTraceElement(StackTraceElement ste) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String fileName = ste.getFileName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String className = ste.getClassName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String methodName = ste.getMethodName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int line = ste.getLineNumber();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("file:" + fileName + "\t class:" + className + "\t method:" + methodName + "\t line:" + line);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("");<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
</p>
<p goog_ds_charindex="4961">&nbsp;</p><img src ="http://www.blogjava.net/super2/aggbug/237990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:23 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十一章 模板方法（Template Method） </title><link>http://www.blogjava.net/super2/archive/2008/11/01/237988.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:22:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237988.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237988.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237988.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237988.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237988.html</trackback:ping><description><![CDATA[<p goog_ds_charindex="31" align="justify">什么是模板方法呢？我们先回想以下SQL保存的例子，这个例子要
求我们能够同时处理三种类型的SQL语句保存文件：XML格式的文件，Properties格式文件和普通的文本格式的文件。不论那种格式的文件都要求能
够提供根据SQL语句名字获得SQL语句的方法。我们可以这样子设计：</p>
<p goog_ds_charindex="168" align="justify">public class AbstractSqlManager {</p>
<p goog_ds_charindex="203" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private Map sqlMap ;</p>
<p goog_ds_charindex="230" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public AbstractSqlManager(String filePath) {</p>
<p goog_ds_charindex="281" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlMap = initSqlMap(filePath)</p>
<p goog_ds_charindex="321" align="justify">&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="329" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_ds_charindex="336" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String getSql(String key) {</p>
<p goog_ds_charindex="377" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (String)sqlMap.get(key);</p>
<p goog_ds_charindex="419" align="justify">&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p goog_ds_charindex="428" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_ds_charindex="435" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong goog_ds_charindex="441">public abstract Map initSqlMap(String filePath);</strong></p>
<p goog_ds_charindex="492" align="justify">}&nbsp;</p>
<p goog_ds_charindex="496" align="justify">&nbsp;</p>
<p goog_ds_charindex="497" align="justify">public class XmlSqlManager extends AbstractSqlMamager {</p>
<p goog_ds_charindex="554" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;<strong>&nbsp;public Map initSqlMap(String filePath) {</strong></p>
<p goog_ds_charindex="601" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解析XML文件将SQL语句，以SQL语句的名字为Key，放在sqlMap中。</strong></p>
<p goog_ds_charindex="653" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</strong></p>
<p goog_ds_charindex="661" align="justify">}</p>
<p goog_ds_charindex="664" align="justify">&nbsp;</p>
<p goog_ds_charindex="665" align="justify">public class PropertiesSqlManager extends AbstractSqlMamager {</p>
<p goog_ds_charindex="729" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>public Map initSqlMap(String filePath) {</strong></p>
<p goog_ds_charindex="776" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解析Properties文件将SQL语句，以SQL语句的名字为Key，放在sqlMap中。</strong></p>
<p goog_ds_charindex="835" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</strong></p>
<p goog_ds_charindex="843" align="justify">}</p>
<p goog_ds_charindex="846" align="justify">public class TextSqlManager extends AbstractSqlMamager {</p>
<p goog_ds_charindex="904" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;<strong>&nbsp;public Map initSqlMap(String filePath) {</strong></p>
<p goog_ds_charindex="951" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解析Text文件将SQL语句，以SQL语句的名字为Key，放在sqlMap中。</strong></p>
<p goog_ds_charindex="1004" align="justify"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</strong></p>
<p goog_ds_charindex="1012" align="justify">}</p>
<p goog_ds_charindex="1015" align="justify">&nbsp;</p>
<p goog_ds_charindex="1016" align="justify">参看上述的代码，在AbstractSqlManager
中，因为可能处理的文件的内容不同，所以将解析不同代码的方法实现放在了具体的类（XmlSqlManager
，PropertiesSqlManager 和TextSqlManager
）中，只在AbstractSqlManager中实现了getSql方法。</p>
<p goog_ds_charindex="1172" align="justify">&nbsp;</p>
<p goog_ds_charindex="1173" align="justify">我们在来考虑三个具体的实现类，在这些类实现的时候，需要从AbstractSqlManager集成，所以必须实现initSqlMap这个方法，并且必须按照AbstractSqlManager中定义的格式（<strong goog_ds_charindex="1275">模板</strong>）来实现。</p>
<p goog_ds_charindex="1285" align="justify">&nbsp;</p>
<p goog_ds_charindex="1286" align="justify">这样可以称initSqlMap为模板方法，也可以称上述的设计为模板方法。</p>
<p goog_ds_charindex="1324" align="justify">&nbsp;</p>
<p goog_ds_charindex="1325" align="justify">模板方法设计的好处有那些呢？</p>
<p goog_ds_charindex="1341" align="justify">第一，也是继承的好处，可以重用代码</p>
<p goog_ds_charindex="1360" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上述的例子，使用了模板方法之后，可以将公共的方法和流程在基类中编写，这样可以重用这些代码。<strong goog_ds_charindex="1412">（关于继承和组合重用代码的问题参看另外的相关讨论）</strong></p>
<p goog_ds_charindex="1440" align="justify">第二，可以灵活的对应变更</p>
<p goog_ds_charindex="1454" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为使用了模板方法，所以相同的操作可以在基类中
完成，具体的不同实现可以在具体类中完成。所以首先有了变更修改的范围很容易确定，如果是通用的操作则需要在基类中完成，例如initSqlMap之前需
要使用日志记录文件的信息。如果是特殊的操作则需要在具体类中完成，例如XML文件格式发生了变更。</p>
<p goog_ds_charindex="1603" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_ds_charindex="1610" align="justify">第三，规范处理流程（例如有三个模板方法）</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用模板方法可以规范处理流程，例如要对输入的数进行相关的操作，我们可以定义这样的几个过程，（1）数据格式校验（2）数据逻辑校验（3）预处理（4）处理（5）处理输出值（6）结束</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们可以定义这样子一个基类，包含需要的模板方法：</p>
<p goog_ds_charindex="1632" align="justify">public class BaseTarget{</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void execute(InputVO vo) throw ExecuteException&nbsp;{</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formatCheck(vo);</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logicCheck(vo);</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preProcess(vo);</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputVO out = process(vo);</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formatCheck(out);</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch(FormatException ex) {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 异常处理</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch(LogicException ex) {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 异常处理&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch(PreProcessExceptionex) {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 异常处理</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch(ProcessExceptionex) {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 异常处理</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch(PostProcessExceptionex) {</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 异常处理</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public abstract void formatCheck(InputVO vo) throw FormatException ;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public abstract void logicCheck(InputVO vo) throw LogicException ;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public abstract void preProcess(InputVO vo) throw PreProcessException;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public abstract OutputVO process(InputVO vo) throw ProcessException;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;</p>
<p goog_ds_charindex="1632" align="justify">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public abstract void postProcess(OutputVO vo) throw PostProcessException;</p>
<p goog_ds_charindex="1632" align="justify">}</p>
<p goog_ds_charindex="1633" align="justify">&nbsp;</p>
<p goog_ds_charindex="1633" align="justify">通过上述基类的定义，我们规定了子类型的处理内容（五个需要实现的抽象方法）和处理的顺序（按照execute方法定义的处理顺序执行）。</p>
<p goog_ds_charindex="1633" align="justify">&nbsp;</p><img src ="http://www.blogjava.net/super2/aggbug/237988.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:22 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237988.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十二章Singleton和对象创建 </title><link>http://www.blogjava.net/super2/archive/2008/11/01/237989.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:22:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237989.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237989.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237989.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237989.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237989.html</trackback:ping><description><![CDATA[<h2 goog_ds_charindex="23">什么是Singleton呢？ </h2>
<div>
<table id="pojv" border="1" bordercolor="#666666" cellpadding="3" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td width="100%">
            <p goog_ds_charindex="40">In
            software engineering, the singleton pattern is a design pattern that is
            used to restrict instantiation of a class to one object. This is useful
            when exactly one object is needed to coordinate actions across the
            system. Sometimes it is generalized to systems that operate more
            efficiently when only one or a few objects exist. It is also considered
            an anti-pattern since it is often used as a euphemism for global
            variable.</p>
            <p goog_ds_charindex="40" align="right"><a href="http://en.wikipedia.org/wiki/Singleton_pattern"><font color="#551a8b">http://en.wikipedia.org/wiki/Singleton_pattern</font></a></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">翻译：</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在软件工程领域，Singleton是一种将对象的实例限制为只有一个的一种模式。当系统的所有处理只需要某个对象的一个实例的时候可以适用这种模式。通常情况下，实例存在的越少（最好是一个）系统的性能越好。针对于Singleton的反模式是使用全局变量。</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">在wikipedia上Java的标准实现是：</p>
<p goog_ds_charindex="467">public class Singleton<br />
{ <br />
&nbsp; //&nbsp;通过私有化构造方法，防止在Singleton类之外构造类的实例。<br />
&nbsp; private Singleton() {}<br />
&nbsp;<br />
&nbsp; /**<br />
&nbsp;&nbsp; * SingletonHolder 在Singleton.getInstance()第一次调用的时候被初始化。<br />
&nbsp;&nbsp; */<br />
&nbsp; private static class SingletonHolder<br />
&nbsp; { <br />
&nbsp;&nbsp;&nbsp; private final static Singleton INSTANCE = new Singleton();<br />
&nbsp; }<br />
&nbsp;<br />
&nbsp; public static Singleton getInstance()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; return SingletonHolder.INSTANCE;<br />
&nbsp; }<br />
}<br />
</p>
<p goog_ds_charindex="467">或者更常见的是：</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">public class Singleton {<br />
&nbsp;&nbsp; private final static Singleton INSTANCE = new Singleton();<br />
&nbsp;<br />
&nbsp;&nbsp; //&nbsp;通过私有化构造方法，防止在Singleton类之外构造类的实例。<br />
&nbsp;&nbsp; private Singleton() {}<br />
&nbsp;<br />
&nbsp;&nbsp; public static Singleton getInstance() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; return INSTANCE;<br />
&nbsp;&nbsp; }<br />
&nbsp;}<br />
</p>
<h2 goog_ds_charindex="467">关于Singleton的说明</h2>
<p goog_ds_charindex="467">第一，必须保证在类的外部不能调用构造方法。</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;在默认无构造方法的情况下，Java编译器会给类加上一个没有参数的共有的
（Public）构造方法（默认构造方法），有构造方法的情况下Java编译器保留定义的构造方法。所以在使用Singleton的时候，如果有构造参数
则需要将访问修饰符改为private的，没有构造参数的情况下，需要添加一个私有的默认构造方法。私有的默认构造方法参看上述代码。</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">&nbsp;&nbsp; private Singleton() {}<br />
</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">第二，必须有一个类的实例</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了避免在累得外面实例化类，所以在第一步中将构造参数设置为了私有，所以只能在类的内部实例化，参看上述代码。</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_ds_charindex="467">&nbsp;&nbsp; private final static Singleton INSTANCE = new Singleton();<br />
</p>
<p goog_ds_charindex="467">第三，在类的外部必须能够访问到第二步中创建的实例。</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于类不能被实例化，所以获取类内部的实例的方法必须为静态的。参看代码：</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">&nbsp;&nbsp;&nbsp;&nbsp;public static Singleton getInstance() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return INSTANCE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;这个时候也明白了第二步中，INSTANCE实例为什么是static的了，final只是为了强调INSTANCE被初始化之后即不可改变，更见强调了singleton的含义。</p>
<p goog_ds_charindex="467">&nbsp;</p>
<h2 goog_ds_charindex="467">关于Singleton的一些变化</h2>
<h3 goog_ds_charindex="467">如果一个Singleton类需要初始话怎么办呢？有两个方法</h3>
<p goog_ds_charindex="467">第一种方法，添加静态代码段</p>
<p goog_ds_charindex="467">&nbsp;</p>
<p goog_ds_charindex="467">public class Singleton {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private final static Singleton INSTANCE = new Singleton();<br />
&nbsp;</p>
<p goog_ds_charindex="467"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static{</strong></p>
<p goog_ds_charindex="467"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 在这里初始化Singleton的实例INSTANCE</strong></p>
<p goog_ds_charindex="467"><strong>&nbsp;&nbsp;&nbsp;&nbsp; }</strong></p>
<p goog_ds_charindex="467"><br />
&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;通过私有化构造方法，防止在Singleton类之外构造类的实例。<br />
&nbsp;&nbsp;&nbsp;&nbsp; private Singleton() {}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static Singleton getInstance() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return INSTANCE;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;}<br />
</p>
<p goog_ds_charindex="467">第二种方法，在getInstance的时候初始化</p>
<p goog_ds_charindex="468">public class Singleton {<br />
&nbsp;&nbsp; private static Singleton INSTANCE;<br />
&nbsp;<br />
&nbsp;&nbsp; //&nbsp;通过私有化构造方法，防止在Singleton类之外构造类的实例。<br />
&nbsp;&nbsp; private Singleton() {}<br />
&nbsp;<br />
&nbsp;&nbsp; public static Singleton getInstance() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(INSTANCE == null) {</p>
<p goog_ds_charindex="468">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INSTANCE = new Singleton();</p>
<p goog_ds_charindex="468">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>//初始化代码</strong></p>
<p goog_ds_charindex="468">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p goog_ds_charindex="468">&nbsp;&nbsp;&nbsp;&nbsp; return INSTANCE;<br />
&nbsp;&nbsp; }<br />
&nbsp;}</p>
<p goog_ds_charindex="468">&nbsp;</p>
<p goog_ds_charindex="468">另种方法采用的原则是，如果肯定会使用到这个实例，可以采用第一种方法；如果可能使用到这个实例，可以使用第二种方法。<br />
</p>
<h3 goog_ds_charindex="468">Singleton初始化异常处理</h3>
<p goog_ds_charindex="468">&nbsp;Singleton实例初始化的时候可能会出现一些异常，通常情况下可以不考虑，如果使用上述
的第一种方法，实例化时发生在代码装载的时候，除了日志不可能给用户反馈。如果使用第二种方法，可以在用户调用的时候处理，可以在getInstance
方法接口添加抛出异常便于用户处理。</p>
<p goog_ds_charindex="468">所以如果Singleton初始化会抛出异常，且此类异常需要客户处理的时候需要使用上述的第二种方法。</p><img src ="http://www.blogjava.net/super2/aggbug/237989.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:22 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237989.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二十章 JDBC DAO设计</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237987.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:21:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237987.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237987.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237987.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237987.html</trackback:ping><description><![CDATA[<span style="font-weight: bold;">Connection的含义</span><br />
&nbsp;&nbsp;&nbsp; Connection表示了一个和数据库的链接，底层需要有操作系统的Socket支持，所以Connection是一种资源，既然是一种资源，就需要按照建立，打开，使用，关闭的顺序合理的使用。<br />
&nbsp;&nbsp;&nbsp; Connection是Java数据库操作的基础，是进行一系列操作的基础，所有的派生的操作，例如Statement，PreparedStatement，ResultSet等都由Connection直接或者间接的衍生。<br />
<br />
&nbsp;&nbsp;&nbsp; 如何获得Connection呢？<br />
&nbsp;&nbsp;&nbsp; 方法一，使用DriverManager类来获取，前提条件是数据库驱动程序需要在classpath下（即使用数据库链接的程序按照Java的方式可以访问到）。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  Connection conn = DriverManager.getConnection(  "jdbc:oracle:thin:@192.168.0.1:1521:ORCL", user, pwd );<br />
&nbsp;&nbsp;&nbsp; 方法二，使用数据库连接池来获取<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
什么是数据库连接池呢，数据库连接池是标准JavaEE容器的一种服务，例如Webspher，Weblogic，Tomcat等，容器预先建立一些数据
库链接，以便应用程序使用的时候从中借取，注意有借有还，当应用程序使用完了之后会将数据库链接还回连接池。（数据源配置请参考其他文档）<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  使用连接池的好处是，可以预先建立链接，减小在数据库获取上的相对时间。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  使用连接池获取数据库链接的方式为：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; InitialContext ctx = new InitialContext();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/DataSource");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Connection conn = ds.getConnection();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  由于在配置数据库连接池的时候已经定义了URL，用户名，密码等信息，所以在程序中使用的时候不需要传入这些信息。<br />
<br />
<span style="font-weight: bold;">ConnectionManager定义</span><br />
&nbsp;&nbsp;&nbsp;
Connection用来专门管理数据库链接，通常情况下ConnectionManager只有一个方法，调用这个方法将返回一个Connection
的实例。通过ConnectionManager可以封装Connection的获取方式（例如开发的时候使用DriverManager，运用的时候使
用DataSource的方式，但是不需要修改ConnectionManager之外的其他代码）和追加Connection获取之前之后的操作（例如
针对Connection的属性的设置）。<br />
&nbsp;&nbsp;&nbsp; 下面的代码是一个ConnectionManager的代码示例：<br />
<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
import java.sql.DriverManager;<br />
import java.sql.SQLException;<br />
<br />
public class ConnectionManager {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Connection getConnection() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Connection conn = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn = DriverManager.getConnection("", "", "");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not get database connection", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return conn;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
&nbsp;&nbsp;&nbsp; 如果需要从开发模式变为运用模式，只需要将上述代码修改为：<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
import java.sql.DriverManager;<br />
import java.sql.SQLException;<br />
<br />
public class ConnectionManager {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Connection getConnection() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Connection conn = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span style="font-weight: bold;">try {</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; Context ctx = new InitialContext();</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; DataSource ds = (DataSource)ctx.lookup("jdbc/dsname");</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; conn = ds.getConnection();</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; } catch(NamingException e) {</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; throw new DaoException("can not find datasource", e);</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; }</span>catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new DaoException("can not get database connection", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return conn;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
如果需要预先设定Connection的一些属性，也可以在上述代码中设定，例如：<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
import java.sql.DriverManager;<br />
import java.sql.SQLException;<br />
<br />
public class ConnectionManager {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Connection getConnection() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Connection conn = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; Context ctx = new InitialContext();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; DataSource ds = (DataSource)ctx.lookup("jdbc/dsname");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; conn = ds.getConnection();<br />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  conn.setAutoCommit(false);</span><br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; } catch(NamingException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; throw new DaoException("can not find datasource", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; }catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new DaoException("can not get database connection", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return conn;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
<span style="font-weight: bold;">CommonDao定义</span><br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">属性和构造方法</span><br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
通常情况下，CommonDao要有一个Connection的引用。所有一个CommonDao的实例的所有方法的调用都需要依赖于这个
Connection。需要一个Connection的另外一个原因是如果各个方法需要保证在一个事务环境中（上下文中），必须保证所有的操作都在一个
Connection上。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  构造方法通常需要将类型为Connection的属性实例化，例如：<br />
<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
<br />
public class CommonDao {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Connection conn;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public CommonDao() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.conn = ConnectionManager.getConnection();<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">事务方法</span><br style="font-weight: bold;" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin（）<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  开始一个事务，调用CommonDao的begin方法之后，所以的后续操作将会在一个事务环境内，要么全部提交，要么全部回滚。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commit（）<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  提交一个事务，必须在begin调用之后调用。且和rollback方法互斥。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rollback（） &nbsp;  <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  回滚一个事务，必须在begin方法调用之后调用。且和commit方法互斥。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 事务的实现有两种方法，一种是使用基于单一Connection的事务，另外一种方法是使用容器的JTA（Java
Transaction
API）。需要注意的是第一种方法可以在任何环境下使用，但是只能是针对单一的数据库链接。第二种方法智能在支持JTA的Java
EE容器中使用（例如Websphere，Weblogic等，Tomcat默认不支持），但是支持多个Connection实例。<br />
&nbsp;&nbsp;&nbsp; 第一种方法代码为：<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
import java.sql.SQLException;<br />
<br />
public class CommonDao {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Connection conn;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public CommonDao() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.conn = ConnectionManager.getConnection();<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; public void begin() throws DaoException{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(conn != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn.setAutoCommit(false);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not begin transaction", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("connection not opened!");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void commit() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (conn != null &amp;&amp; !conn.getAutoCommit()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn.commit();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn.setAutoCommit(true);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (conn == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("connection not opened!");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("first begin then commit please!");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not commit transaction!", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void rollback() throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (conn != null &amp;&amp; !conn.getAutoCommit()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn.rollback();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; conn.setAutoCommit(true);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (conn == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("connection not opened!");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("first begin then rollback please!");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not rollback transaction!", e);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
<br />
&nbsp;&nbsp;&nbsp; 第二种我们在使用DAO的实例中介绍如何使用（@TODO）<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 新建两个DAO，做不同的操作，使用JTA保证事务完整。<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">查询方法</span><br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 查询方法也许是CommonDao最常用的方法，查询方法需要将数据库的结果返回给画面。返回值我们一般不使用ResultSet，因为
ResultSet依赖于Connection，如果Connection关闭，ResultSet将不再有效，所以我们通常将ResultSet转变为
一个List之后返回。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  在说明查询方法之前，我们先说说如何将数据库中的内容放在List中，我们使用一个List表示一个查询结果集合，使用一个Map表示集合中的一行，Map的key表示数据库表的字段名字，Value表示数据库字段的内容。代码为：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; private List convert(ResultSet rs) throws DaoException {<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // record list<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List retList = new ArrayList();<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ResultSetMetaData meta = rs.getMetaData();<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // column count<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int colCount = meta.getColumnCount();<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // each record<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (rs.next()) {<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Map recordMap = new HashMap();<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // each column<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 1; i &lt;= colCount; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // column name<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String name = meta.getColumnName(i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // column value<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object value = rs.getObject(i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // add column to record<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; recordMap.put(name, value);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // ad record to list<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retList.add(recordMap);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException ex) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not convert result set to list of map", ex);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return retList;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; 为了避免Sql注入的安全问题，我们通常使用PreparedStatement，在使用PreparedStatement的时候涉及到如何将传入参数设置到PreparedStatement上面，参看以下的共通方法：<br />
&nbsp;&nbsp;&nbsp; private void apply(PreparedStatement pstmt, List params) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // if params exist<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (params != null &amp;&amp; params.size() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // parameters iterator<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Iterator it = params.iterator();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // parameter index<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int index = 1;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while(it.hasNext()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object obj = it.next();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // if null set ""<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (obj == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt.setObject(index, "");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // else set object<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt.setObject(index, obj);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //next index<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index++;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException ex) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not apply parameter", ex);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; 接着我们继续说我们的查询方法，有了上述两个方法，我们的查询方法就非常简单了：<br />
&nbsp;&nbsp;&nbsp; public List query(String sql, List params) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List result = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PreparedStatement pstmt = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ResultSet rs = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt = conn.prepareStatement(sql);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.apply(pstmt, params);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; rs = pstmt.executeQuery();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; result = this.convert(rs);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException ex) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("can not execute query", ex);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } finally {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (rs != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; rs.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // nothing<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (pstmt != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // nothing<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return result;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">特殊的查询方法（返回单值）</span><br style="font-weight: bold;" />
&nbsp;&nbsp;&nbsp; 有时候为了方便使用，我们需要返回单值的产寻方法，例如 select max(id) from table_a, select count(id) from table_b等。以下的代码使用了上述通用的查询方法，代码为：<br />
&nbsp;&nbsp;&nbsp; public Object queryOne(String sql, List params) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List list = this.query(sql, params);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(list == null || list.size() == 0) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("data not exist");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Map record = (Map)list.get(0);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(record == null || record.size() == 0 ) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("data not exist");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return record.values().toArray()[0];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">更新，删除，插入方法</span><br style="font-weight: bold;" />
&nbsp;&nbsp;&nbsp; 由于在JDBC中这三个方法都是用了一个execute完成，所以这里我们也使用一个方法来完成这些功能。代码为：<br />
&nbsp;&nbsp;&nbsp; public int execute(String sql, List params) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int ret = 0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PreparedStatement pstmt = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt = conn.prepareStatement(sql);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.apply(pstmt, params);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ret = pstmt.executeUpdate();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }catch(SQLException ex) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("", ex);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } finally {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (pstmt != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // nothing.<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ret;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">批处理方法（查询）</span><br />
&nbsp;&nbsp;&nbsp; 有些时候为了便于操作，需要一次查询多条SQL语句，我们称之为批处理，实现参看以下方法，其中为了和query方法做区分，将参数和返回值都改为了数组形式。<br />
<br />
&nbsp;&nbsp;&nbsp; public List[] queryBatch(String[] sqlArray, List[] paramArray) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List rets = new ArrayList();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sqlArray.length != paramArray.length) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("sql size not equal parameter size");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; sqlArray.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String sql = sqlArray[i];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List param = paramArray[i];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List ret = this.query(sql, param);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; rets.add(ret);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return (List[])rets.toArray();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">批处理方法（更新）</span><br />
&nbsp;&nbsp;&nbsp; 有些时候需要一次更新多条Sql语句，为了便于操作，添加了批处理更新操作，参看以下代码，为了和更新方法区分，将参数和返回值都改为了数组形式。<br />
&nbsp;&nbsp;&nbsp; public int[] executeBatch(String[] sqlArray, List[] paramArray) throws DaoException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List rets = new ArrayList();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sqlArray.length != paramArray.length) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new DaoException("sql size not equal parameter size");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; sqlArray.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int ret = this.execute(sqlArray[i], paramArray[i]);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; rets.add(new Integer(ret));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int[] retArray = new int[rets.size()];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; retArray.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retArray[i] = ((Integer)rets.get(i)).intValue();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return retArray;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">资源释放<br />
</span>&nbsp;&nbsp;&nbsp; 由于CommonDao有一个Connection的属性，且Connection属于稀缺资源，所以在CommonDao不需要在使用的时候需要显示的关闭Connection。代码如下：<span style="font-weight: bold;"><br />
</span>&nbsp;&nbsp;&nbsp; public void close() throws DaoException{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (conn != null &amp;&amp; conn.getAutoCommit()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;conn.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(conn == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new DaoException("can not close null connection, first new then close");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new DaoException("transaction is running, rollbakc or commit befor close please.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} catch (SQLException ex) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new DaoException("Can not close common dao");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  <br />
<span style="font-weight: bold;">JDBC工具类（JDBCUtil Class）</span><br />
&nbsp;&nbsp;&nbsp; 在上述的代码中我们看到有很多的无用的处理，例如：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (pstmt != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pstmt.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // nothing.<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;
为什么要有这些处理呢？说先这些处理发生的位置都是在正常处理完成之后，这些处理（例如pstmt.close（））即使失败也没有影响，这个时候我们需
要做上述的无用处理，这正是JDBC API的一个小小的瑕疵。我们通常使用一个特殊的静态工具来来做补充，例如：<br />
<br />
package com.jpleasure.jdbc.dao;<br />
<br />
import java.sql.Connection;<br />
import java.sql.PreparedStatement;<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
<br />
public class JDBCUtil {<br />
&nbsp;&nbsp;&nbsp; public void safelyClose(Connection conn) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if(conn != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;conn.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void safelyClose(PreparedStatement pstmt) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if(pstmt != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pstmt.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void safelyClose(ResultSet rs) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if(rs != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;rs.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
&nbsp;<br />
<span style="font-weight: bold;">异常处理<br />
</span>&nbsp;&nbsp;&nbsp;
也许细心的你已经发现了一个问题，为什么所有抛出异常的地方我们都是将SQLException包装在了DaoException之内抛出呢，为什么不直
接抛出SQLException呢？有两个原因，第一，可以细化，分类Exception抛出合适的异常，添加合适的消息，第二，隔离和Dao和业务逻辑
的耦合，可以方便的修改Dao层而不会影响到业务逻辑层。另外需要注意，DaoExcetion中可以包含SQLException，这个时候可以为客户
提供更详细的错误信息，例如ORA-12524等内容，但是很少见到。<br />
<br />
package com.jpleasure.jdbc.dao;<br />
<br />
public class DaoException extends Exception {<br />
<br />
&nbsp;&nbsp;&nbsp; public DaoException() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; super();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public DaoException(String message, Throwable cause) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; super(message, cause);<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public DaoException(String message) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; super(message);<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public DaoException(Throwable cause) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; super(cause);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}<img src ="http://www.blogjava.net/super2/aggbug/237987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:21 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第十九章 SQL文保存方法</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237986.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237986.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237986.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237986.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237986.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237986.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在开发JavaWeb应用程序的过程中可能经常需要使用到SQL语句来访问数据库。为了屏蔽SQL注入带来的危险，在Java中通常使用PreparedStatement，使用预编译的SQL语句。预编译的SQL语句是那些包含？的语句，使用PreparedStatement可以让数据库预先编译这些SQL模板，只有调用的时候套用必须的参数即可。&nbsp;SQL文件的存放位置那么在JavaWeb项...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237986.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237986.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:20 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237986.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第十五章 AJAX JQuery</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237985.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:19:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237985.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237985.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237985.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237985.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JQuery是另外一个非常流行的JavaScript框架，相对于Dojo来说JQuery更加的轻便，JQuery代码文件的大小为20kb，但是丝毫没有影响到JQuery的强大功能，也许在了解JQuery之后你会有更深刻的体会。并且JQuery使用了插件的体系结构，开发人员可以在JQuery的基础上利用插件的机制扩展JQuery的功能。&nbsp;和JQuery详细的JavaScript框架...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237985.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:19 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第十四章 集成Dojotoolkit（Ajax框架）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237984.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237984.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237984.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237984.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237984.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237984.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Struts2内置对dojotoolkit的支持@TODO 基于Ajax标签做更详细的使用讲解，由于dojo ajax标签在struts2中还处于试验阶段，所以我们主要讲解dojo在不使用struts2内置功能的情况下怎么和struts2结合使用。&nbsp;Dojotoolkit介绍Dojotoolkit是当前比较流行的JavaScript框架，dojo主要提供了以下功能：Jav...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237984.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:18 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第十一章 集成Spring framework</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237982.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237982.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237982.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237982.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span lang="EN-US">Springframework </span><span style="font-family: 宋体;">是一个为了简化</span><span lang="EN-US">JavaEE</span><span style="font-family: 宋体;">开发而创建的一个框架，其中主要的功能为</span><span lang="EN-US">IOC</span><span style="font-family: 宋体;">。简单说明参看</span><span lang="EN-US">Springfremework </span><span style="font-family: 宋体;">的</span><span lang="EN-US">founder Rod Johnson </span><span style="font-family: 宋体;">写的</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">《</span><span lang="EN-US">Introduction to Springframwork</span><span style="font-family: 宋体;">》</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://www.theserverside.com/tt/articles/article.tss?l=SpringFramework">http://www.theserverside.com/tt/articles/article.tss?l=SpringFramework</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Sringframework</span><span style="font-family: 宋体;">总最著名的特性要数控制反转（</span><span lang="EN-US">Inversion of Control</span><span style="font-family: 宋体;">），也叫依赖注入（</span><span lang="EN-US">Dependency Injection</span><span style="font-family: 宋体;">），详细参看</span><span lang="EN-US">Martin Flower</span><span style="font-family: 宋体;">的文章：</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">《</span><span lang="EN-US">Inversion of Control Containers and the Dependency Injection pattern</span><span style="font-family: 宋体;">》</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://martinfowler.com/articles/injection.html">http://martinfowler.com/articles/injection.html</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="font-weight: bold;"><font size="4"><span lang="EN-US">Ioc</span></font><font size="4"><span style="font-family: 宋体;">的来源</span></font></p>
<p class="MsoNormal" style="font-weight: bold;"><font size="4"><span style="font-family: 宋体;"><br />
</span></font></p>
<p class="MsoNormal"><span style="font-weight: bold;">时代的变迁：</span><br />
</p>
<p class="MsoNormal"><span lang="EN-US">New </span><span style="font-family: 宋体;">&#8594;</span> <span style="font-family: 宋体;">基于接口的编程</span> <span style="font-family: 宋体;">&#8594;</span> <span lang="EN-US">工厂方法 </span><span style="font-family: 宋体;">&#8594;</span><span lang="EN-US"> Ioc</span></p>
<span lang="EN-US"><o:p></o:p></span>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">我们先看一个代码关系，例如：</p>
<p class="MsoNormal">TopLogic需要一个SecondLogic完成一定的业务。</p>
<p class="MsoNormal">SecondLogic需要TopDAO来完成数据库访问。</p>
<br />
<span style="font-weight: bold;">New时代：</span><br />
<p class="MsoNormal">那么一定会有这样的代码：</p>
<p class="MsoNormal">public class TopLogic{</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; private SecondLogic logic ;</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public TopLogic() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  logic = new SecondLogic();</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  //以下为初始化方法调用<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logic.XXX</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public topMethod() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  loggic.someMethod();<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }<br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">}<br />
</p>
<br />
<p class="MsoNormal">public class SecondLogic{</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; private TopDAO dao ;</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public SecondLogic() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; dao = new TopDAO();</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  //以下为初始化方法调用<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dao.XXX</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;  <br />
</p>
<p class="MsoNormal">}<br />
</p>
<br />
在New时代，对象间的关系通过New操作符链接，如果你需要一个对象，简单的New一个就好。<br />
New的好处是非常简单，不好的地方有两点，第一，你不知道New了多少个，在哪里New的。<br />
第二是，一旦对象的名字发生了变更，或者New的初始化发生了变更（更常见），所有使用到New的地方都需要修改。<br />
<br />
<span style="font-weight: bold;">基于接口的时代：</span><br />
接口是服务定义，接口是类型定义：一个接口定义了一种类型（接口名字），这种类型提供<br />
特定的服务（接口方法）。<br />
<br />
基于接口的编程一定要讲一个服务类（例如TopLogic，SecondLogic等）分成两部分，一个用于定义服务的接口，和<br />
一个实现了接口方法的实现类。<br />
例如<br />
public interface SecondLogic {<br />
&nbsp;&nbsp;&nbsp; public void someMethod();<br />
}<br />
<br />
public class SecondLogicImpl implements SecondLogic{<br />
&nbsp;&nbsp;&nbsp; public void someMethod() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  ....<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
在TopLogic中使用SecondLogic的时候，不需要使用SecondLogicImpl定义，而用接口定义，<br />
只是在实例化这个类型（接口）的时候才需要实例化类的名字（SecondLogicImpl）例如：<br />
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">public class TopLogic{</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; private SecondLogic logic ;</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public TopLogic() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  logic = new SecondLogicImpl();</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  //以下为初始化方法调用<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logic.XXX</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public topMethod() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  loggic.someMethod();<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }<br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">}<br />
</p>
通过使用基于接口的编程，减低了变量名字变更造成的影线，但是没有降低变量初始化<br />
过程变化的影响。<br />
<br />
<span style="font-weight: bold;">工厂方法和基于接口联合使用<br />
</span>为了将变量初始化过程变化的影响变为最小，必须把变量的初始化方法风中起来，于是<br />
产生了工厂方法<br />
<p class="MsoNormal">例如，我们会有SecondLogicFacotry工厂负责专门初始化SecondLogic的实例，代码为：</p>
public class SecondLogicFactory {<br />
&nbsp;&nbsp;&nbsp; public static SecondLogic createSecondLogic() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  SecondLogic logic = new SecondLogicImpl();
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  //以下为初始化方法调用<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logic.XXX</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...</p>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  return logic;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<p class="MsoNormal"><br />
</p>
这时，TopLogic中所有关于SecondLogic初始化的内容都被移除了，TopLogic变为：<br />
<p class="MsoNormal">public class TopLogic{</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; private SecondLogic logic ;</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public TopLogic() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  logic = SecondLogicFactory.createSecondLogic()</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public topMethod() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  loggic.someMethod();<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }<br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">通常上述逐步的简化代码变得越来越清楚。</p>
<p class="MsoNormal"><br />
</p>
Ioc时代（以Spring为例）<br />
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
Ioc将所有的对象之间的关系转移到了xml配置文件中来。<br />
在TopLogic中声明存储SecondLogic的属性<br />
<p class="MsoNormal">public class TopLogic{</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; private SecondLogic logic ;</p>
<br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; public void setSecondLogic(SecondLogic logic) {</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  this.logic = logic;</span><br style="font-weight: bold;" />
<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; }</span><br />
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public TopLogic() {</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
</p>
<br />
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; public topMethod() {</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  loggic.someMethod();<br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; }<br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">}</p>
<br />
声明变量之间的关系：<br />
<br />
&lt;beans&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="secondLogic" class="com.jpleasure.teamware.logic.SecondLogic"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &lt;property name="XXX" value = "11111"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &lt;property name="YYY" value = "22222"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="topLogic" class="com.jpleasure.teamware.logic.TopLogic"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &lt;property name="secondLogic" ref = "<span style="font-weight: bold;">secondLogic</span>"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&lt;/beans&gt;<br />
<br />
当我们从Spring IOC容器中取得topLogic的时候，其中的secondLogic属性自动的通过<br />
配置文件的配置得到了初始化。<br />
<br />
<span style="font-weight: bold;">为什么Strut2需要使用SpringFramework</span><br style="font-weight: bold;" />
在Struts2中Action是我们扩展的点，我们使用Action处理用户提交的请求，向用户展现数据。<br />
为了更好的组织代码的结构，我们一般情况下使用三层的构架：<br />
Action <span style="font-size: 10.5pt; font-family: 宋体;">&#8594; Logic </span><span style="font-size: 10.5pt; font-family: 宋体;">&#8594; Dao<br />
这样如果我们手动的管理这些对象之间的关系，以方便非常的繁琐，另外也很不利于管理<br />
变更，所以我们更倾向于使用Spring等类似的IOC框架类管理。<br />
<br />
<span style="font-weight: bold;">如何将Springframework和Struts2结合起来</span><br />
</span>回想第一章，我们指导在Struts2中每一个对象都是靠ObjectFactory创建的，而Springframework<br />
就是用来管理对象创佳的，我们只需要将ObjectFactory的对象创建方法改为Spring即可。<br />
<br />
1）在struts.properties或者struts.xml文件中将objectfactory的属性设置为spring方式：<br />
&nbsp;&nbsp;&nbsp; xml方式：<br />
&nbsp;&nbsp;&nbsp; &lt;constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" /&gt;<br />
&nbsp;&nbsp;&nbsp; properties方式：<br />
&nbsp;&nbsp;&nbsp; struts.objectFactory=org.apache.struts2.spring.StrutsSpringObjectFactory<br />
2）当然还需要将需要的Jar文件放在WEB-INF/lib目录下<br />
&nbsp;&nbsp;&nbsp; 这些文件包括：<br />
&nbsp;&nbsp;&nbsp; struts2-spring-plugin-2.0.9.jar<br />
&nbsp;&nbsp;&nbsp; spring.jar（为了省事，包含了所有的spring模块，实际项目中可以考虑使用具体的模块）<br />
3）剩余的就是Springframework的配置了<br />
&nbsp;&nbsp;&nbsp; 第一，告诉Spring，对象间关系的配置在那里存放<br />
&nbsp;&nbsp;&nbsp; 需要在web.xml文件中添加如下内容（注意顺序）：<br />
&nbsp;&nbsp;&nbsp; 这个Listener在应用程序启动的时候启动，用来读取配置文件。<br />
&nbsp;&nbsp;&nbsp; &lt;listener&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;listener-class&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; org.springframework.web.context.ContextLoaderListener<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/listener-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/listener&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; 这个参数配置了配置文件的路径，说明我们可以在classpath或者WEB-INF目录下<br />
&nbsp;&nbsp;&nbsp; 防止名字满足applicationContext-*.xml格式你的文件。<br />
&nbsp;&nbsp;&nbsp; &lt;context-param&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;param-value&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/context-param&gt;<br />
<br />
4）如何让Struts2的Action和Springframework的bean管理起来？<br />
&nbsp;&nbsp;&nbsp; Struts2会根据struts.xml中配置的class名字在springframeowrk中找id相同的bean，如果找不到<br />
&nbsp;&nbsp;&nbsp; 就按照普通的方式实例化Action类。<br />
&nbsp;&nbsp;&nbsp; 例如：<br />
&nbsp;&nbsp;&nbsp; struts-todo.xml<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;action name="forward" method="forward"<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; class="todo"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;result name="insert"&gt;/todo/insert.jsp&lt;/result&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;result name="update"&gt;/todo/insert.jsp&lt;/result&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;result name="delete"&gt;/todo/insert.jsp&lt;/result&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/action&gt;<br />
&nbsp;&nbsp;&nbsp; applicationContext-todo.xml<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;bean id="todo" class="com.jpleasure.teamware.action.TodoAction"<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; singleton="false"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;property name="todoLogic" ref="todoLogic"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; 则class=&#8220;todo&#8221;的Action会使用com.jpleasure.teamware.action.TodoAction。<br />
<br />
<span style="font-weight: bold;">基本程序结构:</span><br />
│&nbsp; .classpath<br />
│&nbsp; .project<br />
├─src<br />
│&nbsp; │&nbsp; applicationContext-todo.xml<br />
│&nbsp; │&nbsp; struts-todo.xml<br />
│&nbsp; │&nbsp; struts.properties<br />
│&nbsp; │&nbsp; struts.xml<br />
│&nbsp; │&nbsp; teamware.properties<br />
│&nbsp; │&nbsp; <br />
│&nbsp; └─com<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; └─jpleasure<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; └─teamware<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ├─action<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ├─dao<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ├─fw<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ├─logic<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ├─util<br />
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; └─vo<br />
└─WebContent<br />
&nbsp;&nbsp;&nbsp; │&nbsp; Index.html<br />
&nbsp;&nbsp;&nbsp; │&nbsp; Index.jsp<br />
&nbsp;&nbsp;&nbsp; │&nbsp; <br />
&nbsp;&nbsp;&nbsp; ├─META-INF<br />
&nbsp;&nbsp;&nbsp; │&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MANIFEST.MF<br />
&nbsp;&nbsp;&nbsp; │&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ├─todo<br />
&nbsp;&nbsp;&nbsp; │&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.jsp<br />
&nbsp;&nbsp;&nbsp; │&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; └─WEB-INF<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; │&nbsp; web.xml<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; │&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; └─lib<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commons-logging-1.0.4.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; freemarker-2.3.8.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ognl-2.6.11.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spring.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struts2-core-2.0.9.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struts2-spring-plugin-2.0.9.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xwork-2.0.4.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
关于Spring的内容，请参看www.springframework.org<img src ="http://www.blogjava.net/super2/aggbug/237982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:17 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第十二章 集成iBatis </title><link>http://www.blogjava.net/super2/archive/2008/11/01/237983.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237983.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237983.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237983.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237983.html</trackback:ping><description><![CDATA[<p goog_ds_charindex="18">iBatis是众多OR Mapping工具中的一个。 </p>
<p goog_ds_charindex="47">&nbsp;</p>
<p goog_ds_charindex="48">OR Mapping产生源自于面向对象的计算机语言（Object-Oriented Language，例如Java）和 </p>
<p goog_ds_charindex="110">关系型数据库（Relationship Database）之间的矛盾，即面向对象的操作和SQL语句之间的矛盾。</p>
<p goog_ds_charindex="167">&nbsp;</p>
<p goog_ds_charindex="168">iBatis有Java版本和.NET两个版本可供选择。&nbsp;</p>
<p goog_ds_charindex="198">&nbsp;</p>
<p goog_ds_charindex="199">以下以Java本本为例讲解。</p>
<p goog_ds_charindex="215">&nbsp;</p>
<p goog_ds_charindex="216"><strong>原理</strong></p>
<p goog_ds_charindex="216">&nbsp;</p>
<p goog_ds_charindex="220">iBatis中需要涉及到以下几部分</p>
<p goog_ds_charindex="239">1.&nbsp;Object 面向对象的概念，表示某一类的实例（下图中的Hashtable，Java/.Net object，Primitive）。</p>
<p goog_ds_charindex="268">2. Table 数据库表，用来以关系化的方式存储Object（下图中的数据库部分）。</p>
<p goog_ds_charindex="302">3. Object到Table的映射信息，例如将哪个Object映射到哪个表，</p>
<p goog_ds_charindex="343">&nbsp;&nbsp;&nbsp; Object的哪个属性映射到表的哪个字段等（下图中的SqlMap.xml）。</p>
<p goog_ds_charindex="371">4. iBatis引擎（下图中SqlMap config 和 SqlMap Statement两部分之和）。</p>
<p goog_ds_charindex="385">&nbsp;</p>
<p goog_ds_charindex="386">图表如下</p>
<div style="padding: 1em 0px; text-align: left;" goog_ds_charindex="390"><img alt="" goog_ds_charindex="391" src="http://docs.google.com/File?id=dd4s87gd_9d2xnwnd5" /></div>
<p>以Insert为例说明</p>
<p>第一步，SqlMap Statement根据SqlMap Config配置自己，配置信息包括数据库信息，等内容。</p>
<p>第二步，将Java Object传递给SqlMap Statement</p>
<p>第三步，SqlMap Statement根据当前传入Java Object在SqlMap.xml 文件中找到对应的配置信息</p>
<p>第四步，根据SqlMap.xml中的配置信息，自动生成 Insert Sql语句</p>
<p>第五部，针对当前配置的数据库执行第四步中生成的Sql语句，将数据插入到数据库中</p>
<p>&nbsp;</p>
<p>以Select为例说明：</p>
<p>第一步，同上</p>
<p>第二步，将包含部分字段(查询条件)内容的Java Object传递给SqlMap Statement</p>
<p>第三步，同上</p>
<p>第四步，根据SqlMap中的配置信息，生成Select Sql语句</p>
<p>第五部，执行第四步中生成的Sql语句</p>
<p>第六步，根据SqlMap.xml 文件中的配置信息，将第五步中查询出来的ResultSet抓变为对应对象的列表，之后返回给调用端</p>
<p>&nbsp;</p>
<p><strong>具体使用</strong></p>
<p>首先是一个SqlMap Config的配置文件，配置了数据库等信息，例如：</p>
<p>&nbsp;&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</p>
<p>&lt;!DOCTYPE sqlMapConfig&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; "<a href="http://ibatis.apache.org/dtd/sql-map-config-2.dtd">http://ibatis.apache.org/dtd/sql-map-config-2.dtd</a>"&gt;</p>
<p>&lt;sqlMapConfig&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;数据库等信息 --&gt;</p>
<p>&nbsp; &lt;transactionManager type="JDBC" commitRequired="false"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;dataSource type="SIMPLE"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="JDBC.Driver" value="org.hsqldb.jdbcDriver"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="JDBC.ConnectionURL" value="jdbc:hsqldb:."/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="JDBC.Username" value="sa"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="JDBC.Password" value="sa"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/dataSource&gt;<br />
&nbsp; &lt;/transactionManager&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;SqlMap.sql&nbsp;OR 映射文件的位置&nbsp;--&gt;</p>
<p>&nbsp; &lt;sqlMap resource="com/mydomain/data/Account.xml"/&gt;<br />
&lt;/sqlMapConfig&gt;<br />
</p>
<p>Java Object对象</p>
<p>package com.mydomain.domain;</p>
<p>public class Account {</p>
<p>&nbsp; private int id;<br />
&nbsp; private String firstName;<br />
&nbsp; private String lastName;<br />
&nbsp; private String emailAddress;</p>
<p>&nbsp; public int getId() {<br />
&nbsp;&nbsp;&nbsp; return id;<br />
&nbsp; }</p>
<p>&nbsp; public void setId(int id) {<br />
&nbsp;&nbsp;&nbsp; this.id = id;<br />
&nbsp; }</p>
<p>&nbsp; public String getFirstName() {<br />
&nbsp;&nbsp;&nbsp; return firstName;<br />
&nbsp; }</p>
<p>&nbsp; public void setFirstName(String firstName) {<br />
&nbsp;&nbsp;&nbsp; this.firstName = firstName;<br />
&nbsp; }</p>
<p>&nbsp; public String getLastName() {<br />
&nbsp;&nbsp;&nbsp; return lastName;<br />
&nbsp; }</p>
<p>&nbsp; public void setLastName(String lastName) {<br />
&nbsp;&nbsp;&nbsp; this.lastName = lastName;<br />
&nbsp; }</p>
<p>&nbsp; public String getEmailAddress() {<br />
&nbsp;&nbsp;&nbsp; return emailAddress;<br />
&nbsp; }</p>
<p>&nbsp; public void setEmailAddress(String emailAddress) {<br />
&nbsp;&nbsp;&nbsp; this.emailAddress = emailAddress;<br />
&nbsp; }</p>
<p>}<br />
</p>
<p>Account对应到数据库表的映射文件，即com/mydomain/data/Account.xml</p>
<p>&nbsp;&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</p>
<p>&lt;!DOCTYPE sqlMap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; "<a href="http://ibatis.apache.org/dtd/sql-map-2.dtd">http://ibatis.apache.org/dtd/sql-map-2.dtd</a>"&gt;</p>
<p>&lt;sqlMap namespace="Account"&gt;</p>
<p>&nbsp; &lt;!-- 对类型定义的别名 --&gt;<br />
&nbsp; &lt;typeAlias alias="Account" type="com.mydomain.domain.Account"/&gt;</p>
<p>&nbsp; &lt;!-- 数据库中的字段名和Java Object中的属性明的对应关系 --&gt;<br />
&nbsp; &lt;resultMap id="AccountResult" class="Account"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;result property="id" column="ACC_ID"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;result property="firstName" column="ACC_FIRST_NAME"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;result property="lastName" column="ACC_LAST_NAME"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;result property="emailAddress" column="ACC_EMAIL"/&gt;<br />
&nbsp; &lt;/resultMap&gt;</p>
<p>&nbsp; &lt;!-- 查询 SQL语句 --&gt;<br />
&nbsp; &lt;select id="selectAllAccounts" resultMap="AccountResult"&gt;<br />
&nbsp;&nbsp;&nbsp; select * from ACCOUNT<br />
&nbsp; &lt;/select&gt;</p>
<p>&nbsp; &lt;!-- 基于ID的查询Sql语句 --&gt;<br />
&nbsp; &lt;select id="selectAccountById" parameterClass="int" resultClass="Account"&gt;<br />
&nbsp;&nbsp;&nbsp; select<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_ID as id,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_FIRST_NAME as firstName,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_LAST_NAME as lastName,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_EMAIL as emailAddress<br />
&nbsp;&nbsp;&nbsp; from ACCOUNT<br />
&nbsp;&nbsp;&nbsp; where ACC_ID = #id#<br />
&nbsp; &lt;/select&gt;<br />
&nbsp;&nbsp; <br />
&nbsp; &lt;!-- 插入SQL语句 --&gt;<br />
&nbsp; &lt;insert id="insertAccount" parameterClass="Account"&gt;<br />
&nbsp;&nbsp;&nbsp; insert into ACCOUNT (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_ID,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_FIRST_NAME,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_LAST_NAME,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_EMAIL<br />
&nbsp;&nbsp;&nbsp; values (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #id#, #firstName#, #lastName#, #emailAddress#<br />
&nbsp;&nbsp;&nbsp; )<br />
&nbsp; &lt;/insert&gt;</p>
<p>&nbsp; &lt;!-- 更新SQL语句 --&gt;<br />
&nbsp; &lt;update id="updateAccount" parameterClass="Account"&gt;<br />
&nbsp;&nbsp;&nbsp; update ACCOUNT set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_FIRST_NAME = #firstName#,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_LAST_NAME = #lastName#,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_EMAIL = #emailAddress#<br />
&nbsp;&nbsp;&nbsp; where<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACC_ID = #id#<br />
&nbsp; &lt;/update&gt;</p>
<p>&nbsp; &lt;!-- 删除SQL语句 --&gt;<br />
&nbsp; &lt;delete id="deleteAccountById" parameterClass="int"&gt;<br />
&nbsp;&nbsp;&nbsp; delete from ACCOUNT where ACC_ID = #id#<br />
&nbsp; &lt;/delete&gt;</p>
<p>&lt;/sqlMap&gt;</p>
<p>&nbsp;</p>
<p>使用代码：</p>
<p>首先装在配置文件：</p>
<p>try {<br />
&nbsp; Reader reader = Resources.getResourceAsReader("com/mydomain/data/SqlMapConfig.xml");<br />
&nbsp; sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);<br />
&nbsp; reader.close(); <br />
} catch (IOException e) {<br />
&nbsp; // Fail fast.<br />
&nbsp; throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);<br />
}</p>
<p>各种方法的使用：</p>
<p>查询列表，返回List</p>
<p>sqlMapper.queryForList("selectAllAccounts");<br />
查询对象</p>
<p>(Account) sqlMapper.queryForObject("selectAccountById", id);<br />
插入</p>
<p>sqlMapper.insert("insertAccount", account);<br />
更新</p>
<p>sqlMapper.update("updateAccount", account);<br />
删除</p>
<p>sqlMapper.delete("deleteAccount", id);</p>
<p>&nbsp;</p>
<p><strong>在Struts2环境中结合Springframework使用ibatis</strong></p>
<p>&nbsp;</p>
<p goog_ds_charindex="4783"><strong goog_ds_charindex="4784">在Struts2环境中结合Springframework使用ibatis</strong></p>
<p goog_ds_charindex="4823"><strong goog_ds_charindex="4824"><span style="font-weight: normal;" goog_ds_charindex="4825">想要使用ibatis必须首先定义数据源，这里使用DBCP数据源。</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="4861"><strong goog_ds_charindex="4862"><span style="font-weight: normal;" goog_ds_charindex="4863">DBCP是apache jakarta下面的一个opensouce 名字叫做Database Connection Pool</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="4929"><strong goog_ds_charindex="4930"><span style="font-weight: normal;" goog_ds_charindex="4931">使用DBCP需要将以下两个文件拷贝到WEB-INF/lib目录下：</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="4968"><strong goog_ds_charindex="4969"><span style="font-weight: normal;" goog_ds_charindex="4970">commons-dbcp.jar</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="4990"><strong goog_ds_charindex="4991"><span style="font-weight: normal;" goog_ds_charindex="4992">commons-pool.jar</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5012"><strong goog_ds_charindex="5013"><span style="font-weight: normal;" goog_ds_charindex="5014"><br goog_ds_charindex="5015" />
</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5019"><span style="font-weight: normal;" goog_ds_charindex="5020"><strong goog_ds_charindex="5021">在Spring配置文件中可以使用Ioc的方式配置数据库连接池（DBCP）</strong></span></p>
<p style="font-weight: bold;" goog_ds_charindex="5061"><strong goog_ds_charindex="5062"><span style="font-weight: normal;" goog_ds_charindex="5063"><br goog_ds_charindex="5064" />
</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5068"><strong goog_ds_charindex="5069"><span style="font-weight: normal;" goog_ds_charindex="5070">通常将数据库链接信息放在database.properties文件中，该文件通常放在WEB-INF目录下</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5126"><strong goog_ds_charindex="5127"><span style="font-weight: normal;" goog_ds_charindex="5128">文件内容为：</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5138"><strong goog_ds_charindex="5139"><span style="font-weight: normal;" goog_ds_charindex="5140">jdbc.driverClassName=com.mysql.jdbc.Driver<br goog_ds_charindex="5183" />
jdbc.url=jdbc:mysql://localhost:3306/teamware<br goog_ds_charindex="5229" />
jdbc.username=teamware<br goog_ds_charindex="5252" />
jdbc.password=teamware</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5278"><strong goog_ds_charindex="5279"><span style="font-weight: normal;" goog_ds_charindex="5280"><br goog_ds_charindex="5281" />
</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5285"><strong goog_ds_charindex="5286"><span style="font-weight: normal;" goog_ds_charindex="5287">为了在spring配置文件中读取这些信息需要如下配置：</span></strong></p>
<p style="font-weight: bold;" goog_ds_charindex="5318"><strong goog_ds_charindex="5319"><span style="font-weight: normal;" goog_ds_charindex="5320">&lt;bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;<br goog_ds_charindex="5430" />
&nbsp;&lt;property name="locations"&gt;<br goog_ds_charindex="5459" />
&nbsp;&nbsp;&lt;list&gt;<br goog_ds_charindex="5468" />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&lt;value&gt;WEB-INF/database.properties&lt;/value&gt;<br goog_ds_charindex="5517" />
&nbsp;&nbsp;&lt;/list&gt;<br goog_ds_charindex="5527" />
&nbsp;&lt;/property&gt;<br goog_ds_charindex="5540" />
&lt;/bean&gt;</span></strong></p>
<p goog_ds_charindex="5551"><strong goog_ds_charindex="5552"></strong>&nbsp;</p>
<p goog_ds_charindex="5556"><strong goog_ds_charindex="5557"><span style="font-weight: normal;" goog_ds_charindex="5558">配置数据库链接池：</span></strong></p>
<p goog_ds_charindex="5571"><strong goog_ds_charindex="5572"><span style="font-weight: normal;" goog_ds_charindex="5573">&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;<br goog_ds_charindex="5667" />
&nbsp;&lt;property name="driverClassName" value="${jdbc.driverClassName}"/&gt;<br goog_ds_charindex="5735" />
&nbsp;&lt;property name="url" value="${jdbc.url}"/&gt;<br goog_ds_charindex="5779" />
&nbsp;&lt;property name="username" value="${jdbc.username}"/&gt;<br goog_ds_charindex="5833" />
&nbsp;&lt;property name="password" value="${jdbc.password}"/&gt;<br goog_ds_charindex="5887" />
&lt;/bean&gt;</span></strong></p>
<p goog_ds_charindex="5898"><strong goog_ds_charindex="5899"></strong>&nbsp;</p>
<p goog_ds_charindex="5903"><strong goog_ds_charindex="5904"><span style="font-weight: normal;" goog_ds_charindex="5905">其中${}部分内容引用了database.properties文件中的内容。</span></strong></p>
<p goog_ds_charindex="5947"><strong goog_ds_charindex="5948"></strong>&nbsp;</p>
<p goog_ds_charindex="5952"><span style="font-weight: normal;" goog_ds_charindex="5953"><strong goog_ds_charindex="5954">配置ibatis</strong></span></p>
<p goog_ds_charindex="5966"><strong goog_ds_charindex="5967"><span style="font-weight: normal;" goog_ds_charindex="5968">配置ibatis需要的sqlmap-config.xml和TodoVO.xml</span></strong></p>
<p goog_ds_charindex="6011"><strong goog_ds_charindex="6012"><span style="font-weight: normal;" goog_ds_charindex="6013">sqlmap-config.xml</span></strong></p>
<p goog_ds_charindex="6034"><strong goog_ds_charindex="6035"><span style="font-weight: normal;" goog_ds_charindex="6036">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span></strong></p>
<p goog_ds_charindex="6079"><strong goog_ds_charindex="6080"><span style="font-weight: normal;" goog_ds_charindex="6081">&lt;!DOCTYPE sqlMapConfig&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="6110" />
&nbsp;&nbsp;&nbsp; PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="6178" />
&nbsp;&nbsp;&nbsp; "<a href="http://ibatis.apache.org/dtd/sql-map-config-2.dtd" goog_ds_charindex="6184">http://ibatis.apache.org/dtd/sql-map-config-2.dtd</a>"&gt;</span></strong></p>
<p goog_ds_charindex="6240"><strong goog_ds_charindex="6241"><span style="font-weight: normal;" goog_ds_charindex="6242">&lt;sqlMapConfig&gt;<br goog_ds_charindex="6257" />
&nbsp;&lt;sqlMap resource="com/jpleasure/teamware/vo/TodoVO.xml" /&gt;</span></strong></p>
<p goog_ds_charindex="6320"><strong goog_ds_charindex="6321"><span style="font-weight: normal;" goog_ds_charindex="6322">&lt;/sqlMapConfig&gt;</span></strong></p>
<p goog_ds_charindex="6341"><strong goog_ds_charindex="6342"></strong>&nbsp;</p>
<p goog_ds_charindex="6346"><strong goog_ds_charindex="6347"><span style="font-weight: normal;" goog_ds_charindex="6348">TodoVO.xml</span></strong></p>
<p goog_ds_charindex="6362"><strong goog_ds_charindex="6363"><span style="font-weight: normal;" goog_ds_charindex="6364">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span></strong></p>
<p goog_ds_charindex="6407"><strong goog_ds_charindex="6408"><span style="font-weight: normal;" goog_ds_charindex="6409">&lt;!DOCTYPE sqlMap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="6432" />
&nbsp;&nbsp;&nbsp; PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="6493" />
&nbsp;&nbsp;&nbsp; "<a href="http://ibatis.apache.org/dtd/sql-map-2.dtd" goog_ds_charindex="6499">http://ibatis.apache.org/dtd/sql-map-2.dtd</a>"&gt;</span></strong></p>
<p goog_ds_charindex="6548"><strong goog_ds_charindex="6549"><span style="font-weight: normal;" goog_ds_charindex="6550">&lt;sqlMap namespace="TodoVO"&gt;</span></strong></p>
<p goog_ds_charindex="6581"><strong goog_ds_charindex="6582"><span style="font-weight: normal;" goog_ds_charindex="6583">&nbsp; &lt;typeAlias alias="TodoVO" type="com.jpleasure.teamware.vo.TodoVO"/&gt;</span></strong></p>
<p goog_ds_charindex="6656"><strong goog_ds_charindex="6657"><span style="font-weight: normal;" goog_ds_charindex="6658">&nbsp; &lt;resultMap id="TodoVOResult" class="TodoVO"&gt;<br goog_ds_charindex="6705" />
&nbsp;&nbsp;&nbsp; &lt;result property="startDate" column="start_date"/&gt;<br goog_ds_charindex="6760" />
&nbsp;&nbsp;&nbsp; &lt;result property="startTime" column="start_time"/&gt;<br goog_ds_charindex="6815" />
&nbsp;&nbsp;&nbsp; &lt;result property="endDate" column="end_date"/&gt;<br goog_ds_charindex="6866" />
&nbsp;&nbsp;&nbsp; &lt;result property="endTime" column="end_time"/&gt;<br goog_ds_charindex="6917" />
&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="6922" />
&nbsp;&nbsp;&nbsp; &lt;result property="status" column="status"/&gt;<br goog_ds_charindex="6970" />
&nbsp;&nbsp;&nbsp; &lt;result property="priority" column="priority"/&gt;<br goog_ds_charindex="7022" />
&nbsp;&nbsp;&nbsp; &lt;result property="category" column="category"/&gt;<br goog_ds_charindex="7074" />
&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="7079" />
&nbsp;&lt;result property="title" column="title"/&gt;<br goog_ds_charindex="7122" />
&nbsp;&lt;result property="content" column="content"/&gt;<br goog_ds_charindex="7169" />
&nbsp; &lt;/resultMap&gt;</span></strong></p>
<p goog_ds_charindex="7187"><strong goog_ds_charindex="7188"><span style="font-weight: normal;" goog_ds_charindex="7189">&nbsp; &lt;select id="selectAllTodoVOs" resultMap="TodoVOResult"&gt;<br goog_ds_charindex="7247" />
&nbsp;&nbsp;&nbsp; select * from todo<br goog_ds_charindex="7270" />
&nbsp; &lt;/select&gt;</span></strong></p>
<p goog_ds_charindex="7285"><strong goog_ds_charindex="7286"><span style="font-weight: normal;" goog_ds_charindex="7287">&lt;/sqlMap&gt;</span></strong></p>
<p goog_ds_charindex="7300"><strong goog_ds_charindex="7301"></strong>&nbsp;</p>
<p goog_ds_charindex="7305"><strong goog_ds_charindex="7306"></strong>
</p>
<p goog_ds_charindex="7348"><strong goog_ds_charindex="7349"></strong>&nbsp;</p>
<p goog_ds_charindex="7353"><strong goog_ds_charindex="7354"><span style="font-weight: normal;" goog_ds_charindex="7355">package com.jpleasure.teamware.dao;</span></strong></p>
<p goog_ds_charindex="7394"><strong goog_ds_charindex="7395"><span style="font-weight: normal;" goog_ds_charindex="7396">import java.sql.SQLException;<br goog_ds_charindex="7426" />
import java.util.ArrayList;<br goog_ds_charindex="7454" />
import java.util.List;</span></strong></p>
<p goog_ds_charindex="7480"><strong goog_ds_charindex="7481"><span style="font-weight: normal;" goog_ds_charindex="7482">import com.ibatis.sqlmap.client.SqlMapClient;<br goog_ds_charindex="7528" />
import com.jpleasure.teamware.vo.TodoVO;</span></strong></p>
<p goog_ds_charindex="7572"><strong goog_ds_charindex="7573"><span style="font-weight: normal;" goog_ds_charindex="7574">public class TodoDao {<br goog_ds_charindex="7597" />
<strong goog_ds_charindex="7598">&nbsp;private SqlMapClient sqlMap = null;<br goog_ds_charindex="7635" />
&nbsp;<br goog_ds_charindex="7637" />
&nbsp;public SqlMapClient getSqlMap() {<br goog_ds_charindex="7672" />
&nbsp;&nbsp;return sqlMap;<br goog_ds_charindex="7689" />
&nbsp;}</strong></span></strong></p>
<p goog_ds_charindex="7696"><span style="font-weight: normal;" goog_ds_charindex="7697"><strong goog_ds_charindex="7698">&nbsp;public void setSqlMap(SqlMapClient sqlMap) {<br goog_ds_charindex="7744" />
&nbsp;&nbsp;this.sqlMap = sqlMap;<br goog_ds_charindex="7768" />
&nbsp;}</strong></span></p>
<p goog_ds_charindex="7774"><strong goog_ds_charindex="7775"><span style="font-weight: normal;" goog_ds_charindex="7776">&nbsp;public List&lt;TodoVO&gt; listAll() {</span></strong></p>
<p goog_ds_charindex="7812"><strong goog_ds_charindex="7813"><span style="font-weight: normal;" goog_ds_charindex="7814">&nbsp;&nbsp;List todos = new ArrayList();<br goog_ds_charindex="7846" />
&nbsp;&nbsp;try {<br goog_ds_charindex="7854" />
&nbsp;&nbsp;&nbsp;todos = sqlMap.queryForList("selectAllTodoVOs");<br goog_ds_charindex="7906" />
&nbsp;&nbsp;} catch (SQLException e) {<br goog_ds_charindex="7935" />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br goog_ds_charindex="7973" />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br goog_ds_charindex="7997" />
&nbsp;&nbsp;}</span></strong></p>
<p goog_ds_charindex="8004"><strong goog_ds_charindex="8005"><span style="font-weight: normal;" goog_ds_charindex="8006">&nbsp;&nbsp;return todos;<br goog_ds_charindex="8022" />
&nbsp;}</span></strong></p>
<p goog_ds_charindex="8028"><strong goog_ds_charindex="8029"><span style="font-weight: normal;" goog_ds_charindex="8030">&nbsp;public TodoVO insert(TodoVO todo) {<br goog_ds_charindex="8067" />
&nbsp;&nbsp;return todo;<br goog_ds_charindex="8082" />
&nbsp;}</span></strong></p>
<p goog_ds_charindex="8088"><strong goog_ds_charindex="8089"><span style="font-weight: normal;" goog_ds_charindex="8090">&nbsp;public TodoVO update(TodoVO todo) {<br goog_ds_charindex="8127" />
&nbsp;&nbsp;return todo;<br goog_ds_charindex="8142" />
&nbsp;}</span></strong></p>
<p goog_ds_charindex="8148"><strong goog_ds_charindex="8149"><span style="font-weight: normal;" goog_ds_charindex="8150">&nbsp;public TodoVO delete(TodoVO todo) {<br goog_ds_charindex="8187" />
&nbsp;&nbsp;return todo;<br goog_ds_charindex="8202" />
&nbsp;}<br goog_ds_charindex="8205" />
}<br goog_ds_charindex="8207" />
</span></strong></p>
<p goog_ds_charindex="8211"><strong goog_ds_charindex="8212"><span style="font-weight: normal;" goog_ds_charindex="8213">配置DAO</span></strong></p>
<p goog_ds_charindex="8222"><strong goog_ds_charindex="8223"><span style="font-weight: normal;" goog_ds_charindex="8224">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br goog_ds_charindex="8263" />
&lt;!DOCTYPE beans PUBLIC <br goog_ds_charindex="8287" />
&nbsp;"-//SPRING//DTD BEAN//EN" <br goog_ds_charindex="8315" />
&nbsp;"<a href="http://www.springframework.org/dtd/spring-beans.dtd" goog_ds_charindex="8318"><font color="#551a8b">http://www.springframework.org/dtd/spring-beans.dtd</font></a>"&gt;</span></strong></p>
<p goog_ds_charindex="8376"><strong goog_ds_charindex="8377"><span style="font-weight: normal;" goog_ds_charindex="8378">&lt;beans&gt;<br goog_ds_charindex="8386" />
&nbsp;&lt;bean id="todo" class="com.jpleasure.teamware.action.TodoAction"<br goog_ds_charindex="8452" />
&nbsp;&nbsp;singleton="false"&gt;<br goog_ds_charindex="8473" />
&nbsp;&nbsp;&lt;property name="todoLogic" ref="<strong goog_ds_charindex="8508">todoLogic</strong>"&gt;&lt;/property&gt;<br goog_ds_charindex="8532" />
&nbsp;&lt;/bean&gt;<br goog_ds_charindex="8541" />
&nbsp;&lt;bean id="<strong goog_ds_charindex="8553">todoLogic</strong>"<br goog_ds_charindex="8565" />
&nbsp;&nbsp;class="com.jpleasure.teamware.logic.TodoLogic"&gt;<br goog_ds_charindex="8615" />
&nbsp;&nbsp;&lt;property name="todoDao" ref="<strong goog_ds_charindex="8648">todoDao</strong>"&gt;&lt;/property&gt;<br goog_ds_charindex="8670" />
&nbsp;&lt;/bean&gt;<br goog_ds_charindex="8679" />
&nbsp;<strong goog_ds_charindex="8681">&lt;bean id="todoDao" class="com.jpleasure.teamware.dao.TodoDao"&gt;<br goog_ds_charindex="8744" />
&nbsp;&nbsp;&lt;property name="sqlMap" ref="sqlMapClient"&gt;&lt;/property&gt;<br goog_ds_charindex="8801" />
&nbsp;&lt;/bean&gt;</strong></span></strong></p>
<p goog_ds_charindex="8814"><strong goog_ds_charindex="8815"></strong></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">&lt;/beans&gt;</span></p>
<p goog_ds_charindex="8814">&nbsp;</p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816"><strong>使用DAO</strong></span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">package com.jpleasure.teamware.logic;</span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">import java.util.List;</span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">import com.jpleasure.teamware.dao.TodoDao;<br />
import com.jpleasure.teamware.vo.TodoVO;</span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">public class TodoLogic {<br />
&nbsp;<br />
&nbsp;/****************************************<br />
&nbsp; * TodoDao<br />
&nbsp; ****************************************/<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;private TodoDao todoDao;<br />
&nbsp;<br />
&nbsp;public TodoDao getTodoDao() {<br />
&nbsp; return todoDao;<br />
&nbsp;}</span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">&nbsp;public void setTodoDao(TodoDao todoDao) {<br />
&nbsp; this.todoDao = todoDao;<br />
&nbsp;}</span></p>
<p goog_ds_charindex="8814"><span style="font-weight: normal;" goog_ds_charindex="8816">&nbsp;/****************************************<br />
&nbsp; * Logic Method<br />
&nbsp; ****************************************/<br />
&nbsp;<br />
&nbsp;public List&lt;TodoVO&gt; listAll() {<br />
&nbsp; List&lt;TodoVO&gt; todos = todoDao.listAll();<br />
&nbsp; <br />
&nbsp; return todos;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public TodoVO insert(TodoVO todo) {<br />
&nbsp; return todo;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public TodoVO update(TodoVO todo) {<br />
&nbsp; return todo;<br />
&nbsp;}<br />
&nbsp;public TodoVO delete(TodoVO todo) {<br />
&nbsp; return todo;<br />
&nbsp;}<br />
}<br />
</span></p>
<p>&nbsp;</p>
&nbsp;
<p goog_ds_charindex="7305"><span style="font-weight: normal;" goog_ds_charindex="7307">由于使用了Spring配置的DBCP，所以其中的数据库链接部分不需要再配置。</span>
</p>
<p>&nbsp;</p>
<p>只需要配置使用的映射文件即可。</p>
<p>&nbsp;</p>
<p>spring中配置ibatis</p>
<p>&lt;bean id="sqlMapClient"<br />
&nbsp;class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;<br />
&nbsp;&lt;property name="configLocation" value="sqlmap-config.xml"/&gt;<br />
&nbsp;&lt;property name="dataSource" ref="dataSource" /&gt;<br />
&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p><strong>使用Ibatis做数据库访问</strong><br />
定义DAO</p><img src ="http://www.blogjava.net/super2/aggbug/237983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:17 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第九章 拦截器（Interceptors）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237981.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:12:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237981.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237981.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237981.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237981.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237981.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第九章 拦截器&nbsp;拦截器的工作原理如上图，每一个Action请求都包装在一系列的拦截器的内部。拦截器可以在Action执行直线做相似的操作也可以在Action执行直后做回收操作。&nbsp;每一个Action既可以将操作转交给下面的拦截器，Action也可以直接退出操作返回客户既定的画面。&nbsp;如何自定义一个拦截器？自定义一个拦截器需要三步：1...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237981.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237981.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:12 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237981.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第八章 Result Types</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237978.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237978.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237978.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237978.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237978.html</trackback:ping><description><![CDATA[<div>第八章 Result Types</div>
<div>一个提交到服务器的处理通常可以分为两个阶段，第一个阶段查询服务器状态（查询或者更新数据库），第二个阶段选择一个合适的结果页面其返回给用户（这里要讲的Result的内容）。</div>
<div>&nbsp;</div>
<div>Struts2提供了对不同种类返回结果的支持，常见的有JSP，FreeMarker，Velocity等。</div>
<div>Struts2支持的不同类型的返回结果为：</div>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="border: 1pt solid black; padding: 0cm 5.4pt; background: #bfbfbf none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 113.3pt;" valign="top" width="151">
            <div><strong>名字</strong></div>
            </td>
            <td style="border-style: solid solid solid none; border-color: black black black -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; background: #bfbfbf none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 274.2pt;" valign="top" width="366">
            <div><strong>说明</strong></div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Chain Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>用来处理Action链</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Dispatcher Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>用来转向页面，通常处理JSP</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>FreeMarker Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>处理FreeMarker模板</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>HttpHeader Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>用来控制特殊的Http行为</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Redirect Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>重定向到一个URL</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Redirect Action Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>重定向到一个Action</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Stream Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>向浏览器发送InputSream对象，通常用来处理文件下载</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>Velocity Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>处理Velocity模板</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>XLS Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>处理XML/XLST模板</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>PlainText Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>显示原始文件内容，例如文件源代码</div>
            </td>
        </tr>
        <tr>
            <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 113.3pt;" valign="top" width="151">
            <div>S2PLUGINS:Tiles Result</div>
            </td>
            <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 274.2pt;" valign="top" width="366">
            <div>结合Tile使用</div>
            </td>
        </tr>
    </tbody>
</table>
<div>另外第三方的Result类型还包括JasperReports Plugin，专门用来处理JasperReport类型的报表输出。</div>
<div>&nbsp;</div>
<div>在struts-default.xml文件中已经有了对于所有类型Result的定义：</div>
<div>&lt;result-types&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="chain" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.opensymphony.xwork2.ActionChainResult"/&gt;</span></div>
<div><strong><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="dispatcher" </span></strong></div>
<div><strong><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletDispatcherResult" </span></strong></div>
<div><strong><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default="true"/&gt;</span></strong></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="freemarker" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.views.freemarker.FreemarkerResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="httpheader" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.HttpHeaderResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="redirect" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletRedirectResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="redirectAction" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="stream" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.StreamResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="velocity" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.VelocityResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="xslt" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.views.xslt.XSLTResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="plainText" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.PlainTextResult" /&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;!-- Deprecated name form scheduled for removal in Struts 2.1.0. </span></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The camelCase versions are preferred. See ww-1707 --&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="redirect-action" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;result-type name="plaintext" </span></div>
<div><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.PlainTextResult" /&gt;</span></div>
<div>&lt;/result-types&gt;</div>
<div>&nbsp;</div>
<div>从上述代码中可以看出在不指定Result类型的时候使用dispatcher类型。</div>
<div>&nbsp;</div>
<div>定义一个Result值，</div>
<div>&lt;result name="success" type="dispatcher"&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;param name="location"&gt;/ThankYou.jsp&lt;/param&gt;</span></div>
<div>&lt;/result&gt;</div>
<div>由于type默认值是dispatcher，所以这里不需要定义，另外name的默认值为success所以这里也不需要定义。</div>
<div>上述代码可以简写为：</div>
<div>&lt;result&gt;</div>
<div><span>&nbsp;&nbsp;&nbsp; &lt;param name="location"&gt;/ThankYou.jsp&lt;/param&gt;</span></div>
<div>&lt;/result&gt;</div>
<div>另外location参数也可以直接卸载result标签内部，所以上述代码的最简单的写法为：</div>
<div>&lt;result&gt;/ThankYou.jsp&lt;/result&gt;</div>
<div>&nbsp;</div>
<div>我们也可以定义多个不同的Result</div>
<div>&lt;action name="Hello"&gt;</div>
<div>&nbsp;&lt;result&gt;/hello/Result.jsp&lt;/result&gt;</div>
<div>&nbsp;&lt;result name="error"&gt;/hello/Error.jsp&lt;/result&gt;</div>
<div>&nbsp;&lt;result name="input"&gt;/hello/Input.jsp&lt;/result&gt;</div>
<div>&lt;/action&gt;</div>
<div>上述代码的含义为，名字为Hello的Action有三个返回结果，并且都是dispatcher类型（默认类型），这三个返回值的名字分别为
success（默认值），error，input，对应的页面的路径分别为/hello/Result.jsp，/hello/Error.jsp，
/hello/Input.jsp。</div>
<div>&nbsp;</div>
<div>有些时候我们需要一个定义在全局的Result，这个时候我们可以在package内部定义全局的Result，例如：</div>
<div>&lt;global-results&gt;</div>
<div>&nbsp;&lt;result name="error"&gt;/Error.jsp&lt;/result&gt;</div>
<div>&nbsp;&lt;result name="invalid.token"&gt;/Error.jsp&lt;/result&gt;</div>
<div>&nbsp;&lt;result name="login" type="redirect-action"&gt;Logon!input&lt;/result&gt;</div>
<div>&lt;/global-results&gt;</div>
<div>&nbsp;</div>
<div><strong>动态返回结果</strong></div>
<div>有些时候，只有当Action执行完璧的时候我们才知道要返回哪个结果，这个时候我们可以在Action内部定义一个属性，这个属性用来存储Action执行完璧之后的Result值，例如：</div>
<div>private String nextAction;</div>
<div>&nbsp;</div>
<div>public String getNextAction() {</div>
<div><span>&nbsp;&nbsp;&nbsp; return nextAction;</span></div>
<div>}</div>
<div>&nbsp;</div>
<div>在strutx.xml配置文件中，我们可以使用${nextAction}来引用到Action中的属性，通过${nextAction}表示的内容来动态的返回结果，例如：</div>
<div>&lt;action name="fragment" class="FragmentAction"&gt;</div>
<div>&nbsp;&lt;result name="next" type="redirect-action"&gt;${nextAction}&lt;/result&gt;</div>
<div>&lt;/action&gt;</div>
<div>&nbsp;</div>
<div>上述Action的execute方法返回next的时候，还需要根据nextAction的属性来判断具体定位到哪个Action。</div><img src ="http://www.blogjava.net/super2/aggbug/237978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:11 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第七章 (类型转换)Type Convertion</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237975.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237975.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237975.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237975.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237975.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237975.html</trackback:ping><description><![CDATA[<div style="text-align: center;" goog_ds_charindex="1">
<h1 goog_ds_charindex="2"><strong goog_ds_charindex="3"><span style="font-size: 10.5pt;" goog_ds_charindex="4">第七章 Type Convertion</span></strong> </h1>
</div>
<div goog_ds_charindex="29">
<h2 goog_ds_charindex="30"><span style="font-size: 10.5pt;" goog_ds_charindex="31">为什么会有类型转换？</span></h2>
</div>
<div goog_ds_charindex="45"><span style="font-size: 10.5pt;" goog_ds_charindex="46">HTTP</span><span style="font-size: 10.5pt;" goog_ds_charindex="52">协
议中传递的任何内容都是String类型的，所以一旦我们在服务器上需要一个非String类型的对象，例如：int或者Date，那么我们就需要在收到
HTTP请求的数据的时候，首先将String类型的数据变换为我们需要的对应类型的数据，之后再使用。这个过程就是类型转换</span> </div>
<br goog_ds_charindex="188" />
<div goog_ds_charindex="189"><span style="font-size: 10.5pt;" goog_ds_charindex="190">类型转换在Struts2中是透明的，即Struts2内置了类型转换机制。</span> </div>
<div goog_ds_charindex="230"><br goog_ds_charindex="231" />
&nbsp; </div>
<div goog_ds_charindex="235"><strong goog_ds_charindex="236"><span style="font-size: 10.5pt;" goog_ds_charindex="237">转换原理：</span></strong> </div>
<div goog_ds_charindex="247"><span style="font-size: 10.5pt;" goog_ds_charindex="248">以一个例子来说明如何使用Struts2内置的类型转换功能。加入我们希望用户在画面上输入一个字符形式的坐标点，例如（33，2）而我们希望在程序中得到一个Point（33， 2）的类型与之对应。</span> </div>
<div goog_ds_charindex="348"><span style="font-size: 10.5pt;" goog_ds_charindex="349">要想达到上面的功能我们需要一个名字位：ActionName-conversion.properties的文件，在文件中定义Action中的属性和画面字段之间的转换关系。例如：</span> </div>
<div goog_ds_charindex="440"><span style="font-size: 10.5pt;" goog_ds_charindex="441"><br goog_ds_charindex="442" />
point = com.jpleasure.convertor.PointConverter</span> </div>
<div goog_ds_charindex="492"><span style="font-size: 10.5pt;" goog_ds_charindex="493"><br goog_ds_charindex="494" />
也
就是说画面一个叫做point的项目（input类型，name为point）提交到服务器上之后，在向Action中的point属性赋值之前需要使用
PointConverter将字符串转换为Point类，在Action中的point属性向画面显示的时候需要使用PointConverter将
Point类转换为字符串类型。</span> </div>
<div goog_ds_charindex="658"><span style="font-size: 10.5pt;" goog_ds_charindex="659">其中PointConverter需要实现ognl.TypeConverter接口。TypeConverter有两个接口，一个负责将字符串转变为对象类型，另一个负责将对象类型转换为字符串类型，分别对应着内容的提交和显示。</span> </div>
<div goog_ds_charindex="773"><span style="font-size: 10.5pt;" goog_ds_charindex="774">有些时候我们希望所有的Point类在默认的情况下使用PointConverter来转换，这时候我们需要定义全局的Converter类。这可以在xwork-conversion.properties文件中定义，例如：</span> </div>
<div goog_ds_charindex="885"><span style="font-size: 10.5pt;" goog_ds_charindex="886">com.jpleasure.Point = com.jpleasure.convertor.PointConverter</span> </div>
<div goog_ds_charindex="951"><span style="font-size: 10.5pt;" goog_ds_charindex="952">在Struts2中提供了一个TypeConverter接口的默认实现:</span> </div>
<div goog_ds_charindex="991"><span style="font-size: 10.5pt;" goog_ds_charindex="992">org.apache.struts2.action.util.StrutsTypeConverter</span> </div>
<div goog_ds_charindex="1046"><span style="font-size: 10.5pt;" goog_ds_charindex="1047">这个类有两个默认的抽象转换方法和performFallbackConversion，performFallbackConversion方法负责处理类型转换出错的处理。</span> </div>
<div goog_ds_charindex="1135"><span style="font-size: 10.5pt;" goog_ds_charindex="1136">在
自定义TypeConverter的时候，可以实现TypeConverter接口，之后编写TypeConverter的转换方法，也可以从
StrutsTypeConverter继承而来，StrutsTypeConverter本身实现了TypeConverter接口，并且实现了基本的
转换方法。</span> </div>
<div goog_ds_charindex="1290"><strong goog_ds_charindex="1291"><span style="font-size: 10.5pt;" goog_ds_charindex="1292">内建的转换：</span></strong> </div>
<div goog_ds_charindex="1303"><span style="font-size: 10.5pt;" goog_ds_charindex="1304">Struts2</span><span style="font-size: 10.5pt;" goog_ds_charindex="1313">内建了对以下类型的转换的支持：</span> </div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1332"><span style="font-size: 10.5pt;" goog_ds_charindex="1333">String </span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1343"><span style="font-size: 10.5pt;" goog_ds_charindex="1344">boolean / Boolean </span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1365"><span style="font-size: 10.5pt;" goog_ds_charindex="1366">char / Character </span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1386"><span style="font-size: 10.5pt;" goog_ds_charindex="1387">int / Integer, float / Float, long / Long, double / Double </span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1449"><span style="font-size: 10.5pt;" goog_ds_charindex="1450">dates - 使用HTTP 请求对应地域（Locale）的SHORT形式转换字符串和日期类型。 </span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1502"><span style="font-size: 10.5pt;" goog_ds_charindex="1503">arrays -每一个字符串内容可以被转换为不同的对象</span></div>
<div style="margin-left: 11.8pt;" goog_ds_charindex="1533"><span style="font-size: 10.5pt;" goog_ds_charindex="1534">collections - 转换为Collection类型，默认为ArrayList类型，其中包含String类型。<br goog_ds_charindex="1593" />
</span></div>
<div goog_ds_charindex="1597"><span style="font-size: 10.5pt;" goog_ds_charindex="1598">对于Array类型和Collection类型，需要对其中的每一个元素进行单独的转换。</span> </div>
<div goog_ds_charindex="1645"><strong goog_ds_charindex="1646"><span style="font-size: 10.5pt;" goog_ds_charindex="1647">自定义TypeConverter：</span></strong> </div>
<div goog_ds_charindex="1669"><span style="font-size: 10.5pt;" goog_ds_charindex="1670">使用如下的代码自定义需要的TypeConverter</span> </div>
<div goog_ds_charindex="1700"><span style="font-size: 10.5pt;" goog_ds_charindex="1701">public class MyConverter extends StrutsTypeConverter {</span> </div>
<div goog_ds_charindex="1759"><span style="font-size: 10.5pt;" goog_ds_charindex="1760">&nbsp;&nbsp;&nbsp; public Object convertFromString(Map context, String[] values, Class toClass) {</span> </div>
<div goog_ds_charindex="1846"><span style="font-size: 10.5pt;" goog_ds_charindex="1847">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....</span> </div>
<div goog_ds_charindex="1863"><span style="font-size: 10.5pt;" goog_ds_charindex="1864">&nbsp;&nbsp;&nbsp; }</span> </div>
<div goog_ds_charindex="1874"><span style="font-size: 10.5pt;" goog_ds_charindex="1875">&nbsp;&nbsp;&nbsp; public String convertToString(Map context, Object o) {</span> </div>
<div goog_ds_charindex="1937"><span style="font-size: 10.5pt;" goog_ds_charindex="1938">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....</span> </div>
<div goog_ds_charindex="1954"><span style="font-size: 10.5pt;" goog_ds_charindex="1955">&nbsp;&nbsp;&nbsp; }</span> </div>
<div goog_ds_charindex="1964"><span style="font-size: 10.5pt;" goog_ds_charindex="1965">&nbsp;}</span> </div>
<div goog_ds_charindex="1971"><span style="font-size: 10.5pt;" goog_ds_charindex="1972">为了让Struts2框架发现类型转换的错误，需要在出错的情况下在上述的两个方法中抛出XWorkException或者TypeConversionException。</span> </div>
<div goog_ds_charindex="2058"><br goog_ds_charindex="2059" />
我们使用一个例子来展现如何实现TypeConvertor类型：<br goog_ds_charindex="2091" />
<br goog_ds_charindex="2092" />
// Point 类<br goog_ds_charindex="2103" />
package com.jpleasure.conversion;<br goog_ds_charindex="2137" />
<br goog_ds_charindex="2138" />
/**<br goog_ds_charindex="2142" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="2171" />
&nbsp;* User: ma.zhao@dl.cn<br goog_ds_charindex="2194" />
&nbsp;* Date: 2007/09/04<br goog_ds_charindex="2214" />
&nbsp;* Time: 12:33:43<br goog_ds_charindex="2232" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="2297" />
&nbsp;*/<br goog_ds_charindex="2301" />
public class Point {<br goog_ds_charindex="2322" />
&nbsp;&nbsp;&nbsp; private int x;<br goog_ds_charindex="2341" />
&nbsp;&nbsp;&nbsp; private int y;<br goog_ds_charindex="2360" />
<br goog_ds_charindex="2361" />
&nbsp;&nbsp;&nbsp; public Point() {<br goog_ds_charindex="2382" />
<br goog_ds_charindex="2383" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2389" />
&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="2394" />
&nbsp;&nbsp;&nbsp; public Point(int x, int y) {<br goog_ds_charindex="2427" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x = x;<br goog_ds_charindex="2447" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y = y;<br goog_ds_charindex="2467" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2473" />
<br goog_ds_charindex="2474" />
&nbsp;&nbsp;&nbsp; public int getX() {<br goog_ds_charindex="2498" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x;<br goog_ds_charindex="2516" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2522" />
<br goog_ds_charindex="2523" />
&nbsp;&nbsp;&nbsp; public void setX(int x) {<br goog_ds_charindex="2553" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x = x;<br goog_ds_charindex="2573" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2579" />
<br goog_ds_charindex="2580" />
&nbsp;&nbsp;&nbsp; public int getY() {<br goog_ds_charindex="2604" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return y;<br goog_ds_charindex="2622" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2628" />
<br goog_ds_charindex="2629" />
&nbsp;&nbsp;&nbsp; public void setY(int y) {<br goog_ds_charindex="2659" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y = y;<br goog_ds_charindex="2679" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2685" />
<br goog_ds_charindex="2686" />
&nbsp;&nbsp;&nbsp; public String toString() {<br goog_ds_charindex="2717" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer sb = new StringBuffer("Point(");<br goog_ds_charindex="2771" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append(x).append(", ").append(y).append(")");<br goog_ds_charindex="2828" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sb.toString();<br goog_ds_charindex="2858" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="2864" />
}<br goog_ds_charindex="2866" />
<br goog_ds_charindex="2867" />
// PointConvertor 类<br goog_ds_charindex="2887" />
package com.jpleasure.conversion;<br goog_ds_charindex="2921" />
<br goog_ds_charindex="2922" />
import org.apache.struts2.util.StrutsTypeConverter;<br goog_ds_charindex="2974" />
<br goog_ds_charindex="2975" />
import java.util.Map;<br goog_ds_charindex="2997" />
<br goog_ds_charindex="2998" />
/**<br goog_ds_charindex="3002" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="3031" />
&nbsp;* User: ma.zhao@dl.cn<br goog_ds_charindex="3054" />
&nbsp;* Date: 2007/09/04<br goog_ds_charindex="3074" />
&nbsp;* Time: 12:34:18<br goog_ds_charindex="3092" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="3157" />
&nbsp;*/<br goog_ds_charindex="3161" />
public class PointConvertor extends StrutsTypeConverter {<br goog_ds_charindex="3219" />
&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="3224" />
&nbsp;&nbsp;&nbsp; // 从字符串转换为对象的方法。<br goog_ds_charindex="3245" />
&nbsp;&nbsp;&nbsp; public Object convertFromString(Map map, String[] strings, Class aClass) {<br goog_ds_charindex="3324" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strings.length &gt; 0) {<br goog_ds_charindex="3358" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pointStr = strings[0];<br goog_ds_charindex="3400" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] pointStrArray = pointStr.split(",");<br goog_ds_charindex="3458" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pointStrArray.length == 2) {<br goog_ds_charindex="3503" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point p = new Point();<br goog_ds_charindex="3542" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.setX(Integer.parseInt(pointStrArray[0]));<br goog_ds_charindex="3602" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.setY(Integer.parseInt(pointStrArray[1]));<br goog_ds_charindex="3662" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return p;<br goog_ds_charindex="3688" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br goog_ds_charindex="3709" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br goog_ds_charindex="3738" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="3752" />
<br goog_ds_charindex="3753" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br goog_ds_charindex="3770" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br goog_ds_charindex="3795" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="3805" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="3811" />
&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="3816" />
&nbsp;&nbsp;&nbsp; // 从对象转换为字符串的方法。<br goog_ds_charindex="3837" />
&nbsp;&nbsp;&nbsp; public String convertToString(Map map, Object o) {<br goog_ds_charindex="3892" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (o instanceof Point) {<br goog_ds_charindex="3926" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return o.toString();<br goog_ds_charindex="3959" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br goog_ds_charindex="3976" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "";<br goog_ds_charindex="3999" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4009" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4015" />
}<br goog_ds_charindex="4017" />
<br goog_ds_charindex="4018" />
// 测试用PointAction类<br goog_ds_charindex="4037" />
package com.jpleasure.action;<br goog_ds_charindex="4067" />
<br goog_ds_charindex="4068" />
import com.jpleasure.conversion.Point;<br goog_ds_charindex="4107" />
import com.opensymphony.xwork2.ActionSupport;<br goog_ds_charindex="4153" />
<br goog_ds_charindex="4154" />
/**<br goog_ds_charindex="4158" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="4187" />
&nbsp;* User: ma.zhao@dl.cn<br goog_ds_charindex="4210" />
&nbsp;* Date: 2007/09/04<br goog_ds_charindex="4230" />
&nbsp;* Time: 12:45:11<br goog_ds_charindex="4248" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="4313" />
&nbsp;*/<br goog_ds_charindex="4317" />
public class PointAction extends ActionSupport {<br goog_ds_charindex="4366" />
&nbsp;&nbsp;&nbsp; private Point point;<br goog_ds_charindex="4391" />
<br goog_ds_charindex="4392" />
&nbsp;&nbsp;&nbsp; public Point getPoint() {<br goog_ds_charindex="4422" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return point;<br goog_ds_charindex="4444" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4450" />
<br goog_ds_charindex="4451" />
&nbsp;&nbsp;&nbsp; public void setPoint(Point point) {<br goog_ds_charindex="4491" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.point = point;<br goog_ds_charindex="4519" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4525" />
<br goog_ds_charindex="4526" />
&nbsp;&nbsp;&nbsp; public String execute() {<br goog_ds_charindex="4556" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="4580" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="4586" />
}<br goog_ds_charindex="4588" />
<br goog_ds_charindex="4589" />
// JSP文件<br goog_ds_charindex="4598" />
&lt;%--<br goog_ds_charindex="4603" />
&nbsp; Created by IntelliJ IDEA.<br goog_ds_charindex="4631" />
&nbsp; User: ma.zhao@dl.cn<br goog_ds_charindex="4653" />
&nbsp; Date: 2007/09/04<br goog_ds_charindex="4672" />
&nbsp; Time: 12:47:40<br goog_ds_charindex="4689" />
&nbsp; To change this template use File | Settings | File Templates.<br goog_ds_charindex="4753" />
--%&gt;<br goog_ds_charindex="4758" />
&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;<br goog_ds_charindex="4824" />
&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;<br goog_ds_charindex="4868" />
&lt;html&gt;<br goog_ds_charindex="4875" />
&lt;head&gt;&lt;title&gt;Point Page&lt;/title&gt;&lt;/head&gt;<br goog_ds_charindex="4914" />
&lt;body&gt;<br goog_ds_charindex="4921" />
&lt;s:form action="point" namespace="/point" method="post"&gt;<br goog_ds_charindex="4978" />
&nbsp;&nbsp;&nbsp; &lt;s:textfield name="point"/&gt;<br goog_ds_charindex="5010" />
<br goog_ds_charindex="5011" />
&nbsp;&nbsp;&nbsp; &lt;s:property value="point"/&gt;<br goog_ds_charindex="5043" />
&nbsp;&nbsp;&nbsp; &lt;s:submit/&gt;<br goog_ds_charindex="5059" />
&lt;/s:form&gt;<br goog_ds_charindex="5069" />
&lt;/body&gt;<br goog_ds_charindex="5077" />
&lt;/html&gt;<br goog_ds_charindex="5085" />
<br goog_ds_charindex="5086" />
<br goog_ds_charindex="5087" />
// PointAction配置文件类。<br goog_ds_charindex="5108" />
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br goog_ds_charindex="5148" />
&lt;!DOCTYPE struts PUBLIC<br goog_ds_charindex="5172" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"<br goog_ds_charindex="5246" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;<br goog_ds_charindex="5302" />
<br goog_ds_charindex="5303" />
&lt;struts&gt;<br goog_ds_charindex="5312" />
<br goog_ds_charindex="5313" />
&nbsp;&nbsp;&nbsp; &lt;package name="point" namespace="/point" extends="struts-default"&gt;<br goog_ds_charindex="5384" />
<br goog_ds_charindex="5385" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action name="point" class="com.jpleasure.action.PointAction"&gt;<br goog_ds_charindex="5456" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;/point/Point.jsp&lt;/result&gt;<br goog_ds_charindex="5502" />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &lt;!-- 定义input的result是为了处理转换出错的情况，在输入格式不正确的情况下转移到这个画面 --&gt;<br goog_ds_charindex="5570" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result name="input"&gt;/point/Point.jsp&lt;/result&gt;<br goog_ds_charindex="5629" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/action&gt;<br goog_ds_charindex="5647" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Add actions here --&gt;<br goog_ds_charindex="5681" />
&nbsp;&nbsp;&nbsp; &lt;/package&gt;<br goog_ds_charindex="5696" />
&lt;/struts&gt;<br goog_ds_charindex="5706" />
<br goog_ds_charindex="5707" />
</div>
<div goog_ds_charindex="5709"><strong goog_ds_charindex="5710"><span style="font-size: 10.5pt;" goog_ds_charindex="5711">复杂的类型转换：<br goog_ds_charindex="5720" />
（1）处理Null值<br goog_ds_charindex="5731" />
<span style="font-weight: normal;" goog_ds_charindex="5732">有
些时候我们会被NullPointerException搞的焦头烂额，为什么系统不能为我们定义了但是没有初始化的对象建立一个空的Object的引用
呢？Struts2有这个功能，但是在默认情况下Struts2关闭了这个功能，要想开启这个功能，需要在ParameterInterceptor开始
处理参数之前在ValueStack中将一个值开启，这个值是：</span></span></strong><span goog_ds_charindex="5911">InstantiatingNullHandler.</span>CREATE_NULL_OBJECTS。<br goog_ds_charindex="5958" />
在Java代码中<span goog_ds_charindex="5967">InstantiatingNullHandler.</span>CREATE_NULL_OBJECTS的值是：xwork.NullHandler.createNullObjects<br goog_ds_charindex="6052" />
创建空值对象的规则为：<br goog_ds_charindex="6064" />
</div>
<div goog_ds_charindex="6066">
<ul goog_ds_charindex="6067">
    <li goog_ds_charindex="6068">如果属性声明为Collection或List, 将返回一个ArrayList并赋值给空引用. </li>
    <li goog_ds_charindex="6117">如果属性声明为Map, 将返回一个HashMap并赋值给空引用. </li>
    <li goog_ds_charindex="6152">如果空值属性是一个带有无参构造函数的简单Bean, 将使用ObjectFactory.buildBean(java.lang.Class, java.util.Map)方法创建一个实例.</li>
</ul>
</div>
<p goog_ds_charindex="6249"><strong goog_ds_charindex="6250"><span style="font-size: 10.5pt;" goog_ds_charindex="6251"><span style="font-weight: normal;" goog_ds_charindex="6252"><span style="font-weight: bold;" goog_ds_charindex="6253">（2）Collection和Map</span><br goog_ds_charindex="6272" />
</span></span></strong></p>
<p goog_ds_charindex="6277"><strong goog_ds_charindex="6278">简单List转换</strong><br goog_ds_charindex="6288" />
//JSP代码<br goog_ds_charindex="6296" />
&lt;%--<br goog_ds_charindex="6301" />
&nbsp; Created by IntelliJ IDEA.<br goog_ds_charindex="6329" />
&nbsp; User: mazhao<br goog_ds_charindex="6344" />
&nbsp; Date: 2007/09/04<br goog_ds_charindex="6363" />
&nbsp; Time: 12:47:40<br goog_ds_charindex="6380" />
&nbsp; To change this template use File | Settings | File Templates.<br goog_ds_charindex="6444" />
--%&gt;<br goog_ds_charindex="6449" />
&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;<br goog_ds_charindex="6515" />
&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;<br goog_ds_charindex="6559" />
&lt;html&gt;<br goog_ds_charindex="6566" />
&lt;head&gt;&lt;title&gt;Point Page&lt;/title&gt;&lt;/head&gt;<br goog_ds_charindex="6605" />
&lt;body&gt;<br goog_ds_charindex="6612" />
&lt;s:form action="point" namespace="/point" method="post"&gt;<br goog_ds_charindex="6669" />
&nbsp;&nbsp;&nbsp; &lt;s:textfield label="Point" name="point"/&gt;<br goog_ds_charindex="6715" />
<br goog_ds_charindex="6716" />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;" goog_ds_charindex="6721">&lt;s:textfield label="References" name="references"/&gt;</span><br style="font-weight: bold;" goog_ds_charindex="6774" />
<span style="font-weight: bold;" goog_ds_charindex="6775">&nbsp;&nbsp;&nbsp; &lt;s:textfield label="References" name="references"/&gt;</span><br style="font-weight: bold;" goog_ds_charindex="6832" />
<span style="font-weight: bold;" goog_ds_charindex="6833">&nbsp;&nbsp;&nbsp; &lt;s:textfield label="References" name="references"/&gt;</span><br style="font-weight: bold;" goog_ds_charindex="6890" />
<span style="font-weight: bold;" goog_ds_charindex="6891">&nbsp;&nbsp;&nbsp; &lt;s:textfield label="References" name="references"/&gt;</span><br style="font-weight: bold;" goog_ds_charindex="6948" />
<span style="font-weight: bold;" goog_ds_charindex="6949">&nbsp;&nbsp;&nbsp; &lt;s:textfield label="References" name="references"/&gt;</span><br goog_ds_charindex="7006" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="7027" />
<br goog_ds_charindex="7028" />
&nbsp;&nbsp;&nbsp; &lt;s:property value="point"/&gt;<br goog_ds_charindex="7060" />
&nbsp;&nbsp;&nbsp; &lt;s:submit/&gt;<br goog_ds_charindex="7076" />
&lt;/s:form&gt;<br goog_ds_charindex="7086" />
&lt;/body&gt;<br goog_ds_charindex="7094" />
&lt;/html&gt;<br goog_ds_charindex="7102" />
<br goog_ds_charindex="7103" />
//Action代码<br goog_ds_charindex="7114" />
package com.jpleasure.action;<br goog_ds_charindex="7144" />
<br goog_ds_charindex="7145" />
import com.jpleasure.conversion.Point;<br goog_ds_charindex="7184" />
import com.opensymphony.xwork2.ActionSupport;<br goog_ds_charindex="7230" />
<br goog_ds_charindex="7231" />
import java.util.List;<br goog_ds_charindex="7254" />
<br goog_ds_charindex="7255" />
/**<br goog_ds_charindex="7259" />
&nbsp;* Created by IntelliJ IDEA.<br goog_ds_charindex="7288" />
&nbsp;* User: ma.zhao@dl.cn<br goog_ds_charindex="7311" />
&nbsp;* Date: 2007/09/04<br goog_ds_charindex="7331" />
&nbsp;* Time: 12:45:11<br goog_ds_charindex="7349" />
&nbsp;* To change this template use File | Settings | File Templates.<br goog_ds_charindex="7414" />
&nbsp;*/<br goog_ds_charindex="7418" />
public class PointAction extends ActionSupport {<br goog_ds_charindex="7467" />
&nbsp;&nbsp;&nbsp; private Point point;<br goog_ds_charindex="7492" />
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;" goog_ds_charindex="7497">private List references;</span><br goog_ds_charindex="7523" />
<br goog_ds_charindex="7524" />
&nbsp;&nbsp;&nbsp; public Point getPoint() {<br goog_ds_charindex="7554" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return point;<br goog_ds_charindex="7576" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="7582" />
<br goog_ds_charindex="7583" />
&nbsp;&nbsp;&nbsp; public void setPoint(Point point) {<br goog_ds_charindex="7623" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.point = point;<br goog_ds_charindex="7651" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="7657" />
<br goog_ds_charindex="7658" />
&nbsp;&nbsp;&nbsp; public List getReferences() {<br goog_ds_charindex="7692" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return references;<br goog_ds_charindex="7719" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="7725" />
<br goog_ds_charindex="7726" />
&nbsp;&nbsp;&nbsp; public void setReferences(List references) {<br goog_ds_charindex="7775" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.references = references;<br goog_ds_charindex="7813" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="7819" />
<br goog_ds_charindex="7820" />
&nbsp;&nbsp;&nbsp; public String execute() {<br goog_ds_charindex="7850" />
<br goog_ds_charindex="7851" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(references == null) {<br goog_ds_charindex="7884" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("references is null");<br goog_ds_charindex="7938" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br goog_ds_charindex="7955" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("references length is:" + references.size());<br goog_ds_charindex="8032" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br goog_ds_charindex="8045" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;" goog_ds_charindex="8058">for(Object s: references) {</span><br style="font-weight: bold;" goog_ds_charindex="8087" />
<span style="font-weight: bold;" goog_ds_charindex="8088">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("" + s);</span><br style="font-weight: bold;" goog_ds_charindex="8133" />
<span style="font-weight: bold;" goog_ds_charindex="8134">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br goog_ds_charindex="8149" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="8159" />
<br goog_ds_charindex="8160" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="8184" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="8190" />
}<br goog_ds_charindex="8192" />
</p>
<p goog_ds_charindex="8194"><strong goog_ds_charindex="8195">对象类型List转换（key-value pair 方式）</strong><br goog_ds_charindex="8226" />
// Person 类型</p>
<p goog_ds_charindex="8240">package org.apache.struts2.showcase.conversion;</p>
<p goog_ds_charindex="8289">import java.io.Serializable;</p>
<p goog_ds_charindex="8319">/**<br goog_ds_charindex="8323" />
&nbsp;*<br goog_ds_charindex="8326" />
&nbsp;*/<br goog_ds_charindex="8330" />
public class Person implements Serializable {<br goog_ds_charindex="8376" />
&nbsp;&nbsp;&nbsp; private String name;<br goog_ds_charindex="8401" />
&nbsp;&nbsp;&nbsp; private Integer age;</p>
<p goog_ds_charindex="8427">&nbsp;&nbsp;&nbsp; public void setName(String name) { this.name = name; }<br goog_ds_charindex="8486" />
&nbsp;&nbsp;&nbsp; public String getName() { return this.name; }</p>
<p goog_ds_charindex="8537">&nbsp;&nbsp;&nbsp; public void setAge(Integer age) { this.age = age; }<br goog_ds_charindex="8593" />
&nbsp;&nbsp;&nbsp; public Integer getAge() { return this.age; }<br goog_ds_charindex="8642" />
}<br goog_ds_charindex="8644" />
</p>
<p goog_ds_charindex="8646">// PersionAction 类型</p>
<p goog_ds_charindex="8667">&nbsp;package org.apache.struts2.showcase.conversion;</p>
<p goog_ds_charindex="8717">import java.util.List;</p>
<p goog_ds_charindex="8741">import com.opensymphony.xwork2.ActionSupport;</p>
<p goog_ds_charindex="8788">/**<br goog_ds_charindex="8792" />
&nbsp;*<br goog_ds_charindex="8795" />
&nbsp;*/<br goog_ds_charindex="8799" />
public class PersonAction extends ActionSupport {</p>
<p goog_ds_charindex="8850">&nbsp;&nbsp;&nbsp; private List persons;</p>
<p goog_ds_charindex="8877">&nbsp;&nbsp;&nbsp; public List getPersons() { return persons; }<br goog_ds_charindex="8926" />
&nbsp;&nbsp;&nbsp; public void setPersons(List persons) { this.persons = persons; }</p>
<p goog_ds_charindex="8996">&nbsp;</p>
<p goog_ds_charindex="8999">&nbsp;&nbsp;&nbsp; public String input() throws Exception {<br goog_ds_charindex="9044" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="9068" />
&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="9075">&nbsp;&nbsp;&nbsp; public String submit() throws Exception {<br goog_ds_charindex="9121" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="9145" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="9151" />
}<br goog_ds_charindex="9153" />
// PersonAction转化配置文件PersonAction-conversion.properties</p>
<p goog_ds_charindex="9210">&nbsp;</p>
<p goog_ds_charindex="9213"># PersonAction中persons属性（List类型）中元素的类型</p>
<p goog_ds_charindex="9253">Element_persons=org.apache.struts2.showcase.conversion.Person</p>
<p goog_ds_charindex="9316">&nbsp;</p>
<p goog_ds_charindex="9319">// JSP部分代码</p>
<p goog_ds_charindex="9331">&nbsp;&lt;s:iterator value="new int[3]" status="stat"&gt;<br goog_ds_charindex="9378" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:textfield&nbsp;&nbsp;&nbsp; label="%{'Person '+#stat.index+' Name'}" <br goog_ds_charindex="9444" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="%{'persons['+#stat.index+'].name'}" /&gt;<br goog_ds_charindex="9513" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;s:textfield&nbsp;&nbsp;&nbsp; label="%{'Person '+#stat.index+' Age'}" <br goog_ds_charindex="9578" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="%{'persons['+#stat.index+'].age'}" /&gt;<br goog_ds_charindex="9646" />
&nbsp;&nbsp;&lt;/s:iterator&gt;<br goog_ds_charindex="9662" />
其中stat记录了当前循环的信息，其中stat.index表示当前循环的下标。</p>
<p goog_ds_charindex="9703">所以上述代码会生成如下的代码：</p>
<p goog_ds_charindex="9720">&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 1 Name" <br goog_ds_charindex="9759" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[0].name" /&gt;<br goog_ds_charindex="9801" />
&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 1 Age"<br goog_ds_charindex="9838" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[0].age" /&gt;<br goog_ds_charindex="9879" />
&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 2 Name" <br goog_ds_charindex="9918" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[1].name" /&gt;<br goog_ds_charindex="9960" />
&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 2 Age"<br goog_ds_charindex="9997" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[1].age" /&gt;<br goog_ds_charindex="10038" />
&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 3 Name" <br goog_ds_charindex="10077" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[2].name" /&gt;<br goog_ds_charindex="10119" />
&lt;s:textfield&nbsp;&nbsp;&nbsp; label="Person 3 Age"<br goog_ds_charindex="10156" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="persons[2].age" /&gt;<br goog_ds_charindex="10197" />
</p>
<p goog_ds_charindex="10199">&nbsp;</p>
<p goog_ds_charindex="10202"><strong goog_ds_charindex="10203">对象类型List转换（value 方式）</strong></p>
<p goog_ds_charindex="10226">// Address 类型&nbsp;</p>
<p goog_ds_charindex="10242">package org.apache.struts2.showcase.conversion;</p>
<p goog_ds_charindex="10291"><br goog_ds_charindex="10292" />
/**<br goog_ds_charindex="10296" />
&nbsp;* @version $Date: 2006-11-23 12:31:52 -0500 (Thu, 23 Nov 2006) $ $Id: Address.java 478625 2006-11-23 17:31:52Z wsmoak $<br goog_ds_charindex="10417" />
&nbsp;*/<br goog_ds_charindex="10421" />
public class Address {</p>
<p goog_ds_charindex="10445">&nbsp;&nbsp;&nbsp; private String id;<br goog_ds_charindex="10468" />
&nbsp;&nbsp;&nbsp; private String address;</p>
<p goog_ds_charindex="10497">&nbsp;&nbsp;&nbsp; public String getId() { return id; }<br goog_ds_charindex="10538" />
&nbsp;&nbsp;&nbsp; public void setId(String id) { this.id = id; }</p>
<p goog_ds_charindex="10590">&nbsp;&nbsp;&nbsp; public String getAddress() { return address; }<br goog_ds_charindex="10641" />
&nbsp;&nbsp;&nbsp; public void setAddress(String address) { this.address = address; }</p>
<p goog_ds_charindex="10713">}<br goog_ds_charindex="10715" />
</p>
<p goog_ds_charindex="10717">// AddressAction 类型</p>
<p goog_ds_charindex="10738">&nbsp;package org.apache.struts2.showcase.conversion;</p>
<p goog_ds_charindex="10788">import java.util.LinkedHashSet;<br goog_ds_charindex="10820" />
import java.util.Set;</p>
<p goog_ds_charindex="10843">import com.opensymphony.xwork2.ActionSupport;</p>
<p goog_ds_charindex="10890">/**<br goog_ds_charindex="10894" />
&nbsp;* @version $Date: 2006-11-23 12:31:52 -0500 (Thu, 23 Nov 2006) $ $Id: AddressAction.java 478625 2006-11-23 17:31:52Z wsmoak $<br goog_ds_charindex="11021" />
&nbsp;*/<br goog_ds_charindex="11025" />
public class AddressAction extends ActionSupport {</p>
<p goog_ds_charindex="11077">&nbsp;&nbsp;&nbsp; private Set addresses = new LinkedHashSet();</p>
<p goog_ds_charindex="11127">&nbsp;&nbsp;&nbsp; public Set getAddresses() { return addresses; }<br goog_ds_charindex="11179" />
&nbsp;&nbsp;&nbsp; public void setAddresses(Set addresses) { this.addresses = addresses; }</p>
<p goog_ds_charindex="11256"><br goog_ds_charindex="11257" />
&nbsp;&nbsp;&nbsp; public String input() throws Exception {<br goog_ds_charindex="11302" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="11326" />
&nbsp;&nbsp;&nbsp; }</p>
<p goog_ds_charindex="11333">&nbsp;&nbsp;&nbsp; public String submit() throws Exception {<br goog_ds_charindex="11379" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(addresses);<br goog_ds_charindex="11418" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br goog_ds_charindex="11442" />
&nbsp;&nbsp;&nbsp; }<br goog_ds_charindex="11448" />
}</p>
<p goog_ds_charindex="11451">&nbsp;</p>
<p goog_ds_charindex="11454">//AddressAction转换配置文件AddressAction-conversion.properties</p>
<p goog_ds_charindex="11512"><strong goog_ds_charindex="11513">KeyProperty_addresses=id</strong><br goog_ds_charindex="11539" />
Element_addresses=org.apache.struts2.showcase.conversion.Address<br goog_ds_charindex="11604" />
<strong goog_ds_charindex="11605">CreateIfNull_addresses=true</strong></p>
<p goog_ds_charindex="11635">&nbsp;</p>
<p goog_ds_charindex="11638">// JSP代码&nbsp;</p>
<p goog_ds_charindex="11649">&lt;s:form action="submitAddressesInfo" namespace="/conversion"&gt;<br goog_ds_charindex="11711" />
&nbsp;&nbsp;&lt;s:iterator value="%{new int[3]}" status="stat"&gt;<br goog_ds_charindex="11762" />
&nbsp;&nbsp;&nbsp;&lt;s:textfield label="%{'Address '+#stat.index}"<br goog_ds_charindex="11812" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; name="%{'addresses(<a goog_ds_charindex="11840">\\'id'+#stat.index+'\\').address'</a>}" /&gt;<br goog_ds_charindex="11880" />
&nbsp;&nbsp;&lt;/s:iterator&gt;<br goog_ds_charindex="11896" />
&nbsp;&nbsp;&lt;s:submit /&gt;<br goog_ds_charindex="11911" />
&nbsp;&lt;/s:form&gt;</p>
<p goog_ds_charindex="11923">&nbsp;</p>
<p goog_ds_charindex="11926">&nbsp;上述代码会转换为：</p>
<p goog_ds_charindex="11938">&lt;s:form action="submitAddressInfo" namespace="/conversion"&gt;<br goog_ds_charindex="11998" />
&nbsp;&nbsp;<strong goog_ds_charindex="12001">&lt;s:textfield label="Address 0"<br goog_ds_charindex="12032" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="addresses('id0')" /&gt;<br goog_ds_charindex="12065" />
&nbsp;&nbsp;&lt;s:textfield label="Address 1"<br goog_ds_charindex="12098" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="addresses('id1')" /&gt;<br goog_ds_charindex="12131" />
&nbsp;&nbsp;&lt;s:textfield label="Address 2"<br goog_ds_charindex="12164" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="addresses('id2')" /&gt;<br goog_ds_charindex="12197" />
</strong>&nbsp;&nbsp;&lt;s:submit /&gt;<br goog_ds_charindex="12213" />
&nbsp;&lt;/s:form&gt;</p>
<p goog_ds_charindex="12225">&nbsp;</p>
<p goog_ds_charindex="12228">注意两个地方：</p>
<p goog_ds_charindex="12237">第一，没有向服务器提交Address的id属性，那么Address的id属性是什么呢？<br goog_ds_charindex="12281" />
<strong>KeyProperty_addresses=id</strong>表示向服务器提交的内容的key部分（"id0&#8221;， "id1&#8221;， "id2&#8221;）会被认定为Addredd的id。</p>
<p goog_ds_charindex="12237">第二，<strong>CreateIfNull_addresses=true</strong>表示及时客户端没有向服务器提交任何Address内容，服务器也会为AddressAction的addresses 建立一个长度为0的Set。</p>
<p goog_ds_charindex="12237">&nbsp;</p>
<h2 goog_ds_charindex="12237">相关的一些经验</h2>
<p goog_ds_charindex="12237">开发的过程中不要一味的使用String类型，使用String类型无论在处理的速度还是内
存的使用上都不是最好的方式。一般情况下，Java的模型类（JavaBean，
Action等都可以视为Java模型类，因为其中表示了模型的信息），一般情况下需要和数据库中的类型一致。这样才能保证最好的性能。</p>
<p goog_ds_charindex="12237">那么像java.util.Date，Integer等类型需要表示到JSP页面上的时候还是需要表示为String类型的，但是Struts2都已经帮助实现了，所以请使用具体的类型吧，不要总是使用String类型。</p>
<p goog_ds_charindex="12237">&nbsp;</p><img src ="http://www.blogjava.net/super2/aggbug/237975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:10 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第六章 Localization</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237972.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:09:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237972.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237972.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237972.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237972.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237972.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;"><span style="font-family: 宋体;">
<div><strong>引文</strong></div>
<div><strong>&nbsp;</strong></div>
<div>假如我们开发了一个在中文环境下运行的页面，代码如下：</div>
<div>&lt;html&gt;</div>
<div>&lt;head&gt;</div>
<div>&lt;title&gt;欢迎&lt;/title&gt;</div>
<div>&lt;/head&gt;</div>
<div>&lt;body&gt;</div>
<div>&nbsp;&nbsp;&nbsp; &lt;h1&gt;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 欢迎到来！</div>
<div>&nbsp;&nbsp;&nbsp; &lt;/h1&gt;</div>
<div>&lt;/body&gt;</div>
<div>&lt;/html&gt;</div>
<div>&nbsp;</div>
<div>之后又假如，有一天我们公司的业务扩展到了日本，和美国，那么我们必须要订制另外的两张不同的页面，代码为：</div>
<div>&nbsp;</div>
<div>&lt;html&gt;</div>
<div>&lt;head&gt;</div>
<div>&lt;title&gt;Welcome&lt;/title&gt;</div>
<div>&lt;/head&gt;</div>
<div>&lt;body&gt;</div>
<div>&nbsp;&nbsp;&nbsp; &lt;h1&gt;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Welcome Here！</div>
<div>&nbsp;&nbsp;&nbsp; &lt;/h1&gt;</div>
<div>&lt;/body&gt;</div>
<div>&lt;/html&gt;</div>
<div>和</div>
<div>&lt;html&gt;</div>
<div>&lt;head&gt;</div>
<div>&lt;title&gt;ようこそ&lt;/title&gt;</div>
<div>&lt;/head&gt;</div>
<div>&lt;body&gt;</div>
<div>&nbsp;&nbsp;&nbsp; &lt;h1&gt;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ようこそ！</div>
<div>&nbsp;&nbsp;&nbsp; &lt;/h1&gt;</div>
<div>&lt;/body&gt;</div>
<div>&lt;/html&gt;</div>
<div>&nbsp;</div>
<div>也许你已经看到了，上述代码只有文字内容不相同，除此之外完全相同。也许你已经猜到了，现实的代码绝对不是这样的。那么是怎么处理的呢？</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>基本概念</strong></div>
<div>引用</div>
<div><a href="http://en.wikipedia.org/wiki/Internationalization_and_localization">http://en.wikipedia.org/wiki/Internationalization_and_localization</a></div>
<div>Internationalization and localization are means of adapting
products such as publications, hardware or software for non-native
environments, especially other nations and cultures.</div>
<div>&nbsp;</div>
<div>国际化(internationalization i18n)和本地化(localization l10n)指让产品（出版物，软件，硬件等）能够适应非本地环境，特别是其他的语言和文化。</div>
<div>&nbsp;</div>
<div>针对计算机来说就是让一个既可以在中文环境下运行也可以在英语，甚至是日语的环境下运行。</div>
<div>&nbsp;</div>
<div><strong>Java</strong><strong>中如何实现国际化（仅限语言层面）</strong></div>
<div>Java中国际化通过两步来完成，</div>
<div style="margin-left: 36pt; text-indent: -36pt;">第一，<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp; </span>通过将文字内容以特定的方式存放在特定的文件中，</div>
<div style="margin-left: 36pt;">特定的文件：方便管理，另外可以将文件明和特定的语言管理起来</div>
<div style="margin-left: 36pt;">特定的方式：有些时候有些环境不支持某些语言，例如通常英文环境不支持中文，所以要将中文改变为英文可以识别的形式，在使用的时候在转变回来。</div>
<div style="margin-left: 36pt;">&nbsp;</div>
<div>第二，在运行时根据当前的语言环境决定从哪个文件中读取文字内容。</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </div>
<div>第一步，特定的文件，特定的格式</div>
<div>特殊的文件明通过语言和国家来定义，例如：</div>
<div>中文中国 zh_CN</div>
<div>日文日本 ja_JP</div>
<div>英语美国 en_US</div>
<div>&nbsp;</div>
<div>Java中国际化的概念是将不同国家的语言描述的相同的东西放在各自对应的属性文件中，</div>
<div>如果这个文件的名字叫做Message，那么对应语言的文件分别为：</div>
<div>中文中国 Message_zh_CN.properties</div>
<div>日文日本 Message_ja_JP.properties</div>
<div>英文美国 Message_en_US.properties</div>
<div>&nbsp;</div>
<div>特殊的方式使用替换ascii的方式，java中提供了一个native2ascii.exe的工具（在JAVA_HOME\bin目录下），这个工具专门用来把某种特定的文字内容转变为特殊的格式。</div>
<div>&nbsp;</div>
<div>例如Message_zh_CN.properties中的内容为：</div>
<div>Msg1 = 欢迎</div>
<div>Msg2 = 欢迎到这里！</div>
<div>经过命令native2ascii Message_zh_CN.properties之后输出：</div>
<div>Msg1 = \u6b22\u8fce</div>
<div>Msg2 = \u6b22\u8fce\u5230\u8fd9\u91cc\uff01</div>
<div>这里\u6b22等的数字是对应汉字（或者其他非英语字符）的unicode表示</div>
<div>&nbsp;</div>
<div>第二步，通过当前的运行环境确定使用的文件的名字</div>
<div>例如存在上述的三个文件：</div>
<div>中文中国 Message_zh_CN.properties</div>
<div>日文日本 Message_ja_JP.properties</div>
<div>英文美国 Message_en_US.properties</div>
<div>&nbsp;</div>
<div>可以使用java.util.ResouceBundle 类来取得当前的资源文件，代码为：</div>
<div align="left"><span style="font-size: 10pt; color: black;">ResourceBundle rb = ResourceBundle.<em>getBundle</em>(</span><span style="font-size: 10pt; color: #2a00ff;">"Message"</span><span style="font-size: 10pt; color: black;">);</span></div>
<div>也可以指语言与国家特征来获得想要的文件的内容，例如：</div>
<div><span style="font-size: 10pt; color: black;">ResourceBundle rb = ResourceBundle.<em>getBundle</em>(</span><span style="font-size: 10pt; color: #2a00ff;">"Message"</span><span style="font-size: 10pt; color: black;">, Locale.</span><em><span style="font-size: 10pt; color: #0000c0;">JAPAN</span></em><span style="font-size: 10pt; color: black;">);</span></div>
<div>&nbsp;</div>
<div><strong>Struts2</strong><strong>中如何实现国际化（仅限语言层面）</strong></div>
<div>Struts2中使用国际化的几个方法：</div>
<div style="margin-left: 18pt; text-indent: -18pt;">1）&nbsp;UI标签</div>
<div style="margin-left: 18pt;">例如：</div>
<div style="margin-left: 18pt;">&lt;s:i18n name="struts.action.test.i18n.Shop"&gt;</div>
<div style="margin-left: 18pt;">&nbsp;&nbsp;&nbsp; &lt;s:text name="main.title"/&gt;</div>
<div style="margin-left: 18pt;">&lt;/s:i18n&gt;</div>
<div style="margin-left: 18pt;">从指定资源文件struts.action.test.i18n.Shop中找到main.title对应的消息内容。</div>
<div style="margin-left: 18pt;">&nbsp;</div>
<div style="margin-left: 18pt;">&lt;!-- Second Example --&gt;</div>
<div style="margin-left: 18pt;">&lt;s:text name="main.title" /&gt;</div>
<div style="margin-left: 18pt;">从对应的文件中找到main.title对应的消息内容。</div>
<div>&nbsp;</div>
<div style="margin-left: 18pt;">&lt;!-- Third Examlpe --&gt;</div>
<div style="margin-left: 18pt;">&lt;s:text name="i18n.label.greetings"&gt;</div>
<div style="margin-left: 18pt;">&nbsp;&nbsp; &lt;s:param &gt;Mr Smith&lt;/s:param&gt;</div>
<div style="margin-left: 18pt;">&lt;/s:text&gt;</div>
<div style="margin-left: 18pt;">从对应的文件中找到i18n.label.greetings对应的消息内容，其中的{0}参数将会被Mr Smith替换。</div>
<div>&nbsp;</div>
<div style="margin-left: 18pt; text-indent: -18pt;">2）&nbsp;ActionSupport的getText方法</div>
<div style="margin-left: 18pt;">例如：&lt;s:text name="%{getText("i18n.label.greetings")}"&gt;</div>
<div style="margin-left: 18pt;">或者在Action中直接使用。</div>
<div>&nbsp;</div>
<div>在没有指定资源文件的情况下，资源文件的查找按如下的顺序：</div>
<div>1）ActionClass.properties</div>
<div>2）BaseClass.properties</div>
<div>3）Interface.properties</div>
<div>4）ModelDriven&#8217;s Model</div>
<div>5）package.properties</div>
<div>6）search up the i18n message key hierarchy itself</div>
<div>7）global resource properties</div>
<div>&nbsp;</div>
<div>例如有如下结构：</div>
<div>com/</div>
<div>&nbsp;acme/</div>
<div>&nbsp;&nbsp;&nbsp; package.properties</div>
<div>&nbsp;&nbsp;&nbsp; actions/</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; package.properties</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FooAction.java</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FooAction.properties</div>
<div>如果<span>FooAction.properties文件不存在，将使用com/acme/action
/package.properties，如果com/acme/action/package.properties文件不存在，将使用com
/acme/ package.properties，如果还不存在，将使用com/ package.properties等等。</span></div>
<div>可以通过getText方法，text标签或者i18n标签来访问资源文件。</div>
<div>&nbsp;</div>
<div><strong>可以在struts.properties中通过struts.custom.i18n.resources来指定global的资源绑定。</strong></div>
<div>&nbsp;</div>
<div>相关参考I18n Intercepter</div>
<div>关于类型转换的国际化支持参看【第七章 Type Convertion】部分</div>
</span></span><img src ="http://www.blogjava.net/super2/aggbug/237972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:09 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第五章 Validation</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237968.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237968.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237968.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237968.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237968.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237968.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 5.1节：校验类型和配置方法说明从Struts2 校验框架在验证的场所上可以分为：客户端校验和服务端校验。&nbsp;&nbsp;&nbsp; 客户端校验是指，在HTML画面上自动生成JavaScript校验代码，在用户提交到服务器之前在客户端浏览器中进行校验。默认位客户端校验。&nbsp;&nbsp;&nbsp; 服务端校验是指，在数据提交到服务器上之后，在Action处理之前，对客...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237968.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237968.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:08 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237968.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第四章 Taglib Struts2标签库</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237965.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:06:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237965.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237965.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237965.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237965.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第四章 Tablib Struts标签库Struts2 Taglib抽象了不同表示技术，现在Struts2主要支持三种表示技术：JSP,FreeMarker和Velocity。但部分的Tag在三种表示技术下都可以使用，但是也有部分只能在某一种情况下使用。&nbsp;Tab可以分为两类：通用标签和UI标签。&nbsp;4.1节 通用标签通用标签用来在页面表示的时候控制代码执行...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237965.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:06 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三章 Struts2配置（第三～七节其他配置）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237964.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:04:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237964.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237964.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237964.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237964.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237964.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.3</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节 <span lang="EN-US">Result</span>配置<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Action</span><span style="font-size: 10.5pt; font-family: 宋体;">里提供了五个默认的返回值：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">String SUCCESS = "success";<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">String NONE<span>&nbsp;&nbsp;&nbsp; </span>= "none";<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">String ERROR<span>&nbsp;&nbsp; </span>= "error";<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">String INPUT<span>&nbsp;&nbsp; </span>= "input";<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">String LOGIN<span>&nbsp;&nbsp; </span>= "login";<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">默认的一些配置<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-size: 10pt; font-family: 宋体; color: teal; letter-spacing: 0pt;">在</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">package</span><span style="font-size: 10pt; font-family: 宋体; color: teal; letter-spacing: 0pt;">下有如下配置</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US"><o:p></o:p></span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">&lt;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f7f; letter-spacing: 0pt;" lang="EN-US">result-types</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">&gt;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; letter-spacing: 0pt;" lang="EN-US"><o:p></o:p></span></p>
<p style="text-align: left; text-indent: 10pt;" class="MsoNormal" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">&lt;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f7f; letter-spacing: 0pt;" lang="EN-US">result-type </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f007f; letter-spacing: 0pt;" lang="EN-US">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black; letter-spacing: 0pt;" lang="EN-US">=</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff; letter-spacing: 0pt;" lang="EN-US">"dispatcher"</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; letter-spacing: 0pt;" lang="EN-US"><o:p></o:p></span></p>
<p style="text-align: left; text-indent: 45pt;" class="MsoNormal" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f007f; letter-spacing: 0pt;" lang="EN-US">class</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black; letter-spacing: 0pt;" lang="EN-US">=</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff; letter-spacing: 0pt;" lang="EN-US">"org.apache.struts2.dispatcher.ServletDispatcherResult"</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; letter-spacing: 0pt;" lang="EN-US"><o:p></o:p></span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff; letter-spacing: 0pt;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f007f; letter-spacing: 0pt;" lang="EN-US">default</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black; letter-spacing: 0pt;" lang="EN-US">=</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff; letter-spacing: 0pt;" lang="EN-US">"true" </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">/&gt;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; letter-spacing: 0pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">&lt;/</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f7f; letter-spacing: 0pt;" lang="EN-US">result-types</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: teal; letter-spacing: 0pt;" lang="EN-US">&gt;</span><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">如果一个<span lang="EN-US">Result</span>的<span lang="EN-US">type</span>没有设定的话，默认为<span lang="EN-US">dispthcher</span>。<span lang="EN-US">Dispatcher</span>的意思是转向一个<span lang="EN-US">JSP</span>等的资源。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">另外如果<span lang="EN-US">Result</span>的<span lang="EN-US">name</span>没有设定的话，默认为<span lang="EN-US">SUCCESS</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">一个完整的<span lang="EN-US">Result</span>的声明如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;result name="success" type="dispatcher"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;param name="location"&gt;/ThankYou.jsp&lt;/param&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">考虑到默认值可以写成：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;param name="location"&gt;/ThankYou.jsp&lt;/param&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">另外也可以简写为：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;result&gt;/ThankYou.jsp&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">另外为了方便，可以在<span lang="EN-US">package</span>中设置一些全局的<span lang="EN-US">result</span>，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;global-results&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;result name="error"&gt;/Error.jsp&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;result name="invalid.token"&gt;/Error.jsp&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;result name="login" type="redirect-action"&gt;Logon_input&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/global-results&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">动态结果<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">有些时候，在<span lang="EN-US">Action</span>执行完毕之后才知道<span lang="EN-US">Result</span>的指向，可以使用如下的方法：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Action<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">private String nextAction;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">public String getNextAction() {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>return nextAction;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">public String execute() throws Exception {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>return &#8220;next&#8221;;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;action name="fragment" class="FragmentAction"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;result name="next" type="redirect-action"&gt;${nextAction}&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/action&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.4</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节 <span lang="EN-US">ActionSupport<o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Action</span><span style="font-size: 10.5pt; font-family: 宋体;">类不一定非要实现<span lang="EN-US">Action</span>接口或者集成<span lang="EN-US">ActionSupport</span>类，也就是说<span lang="EN-US">Action</span>可以是一个<span lang="EN-US">POJO</span>对象，只不过提供一个返回<span lang="EN-US">String</span>的方法。如果<span lang="EN-US">Action</span>类不实现<span lang="EN-US">Action</span>接口，也不从<span lang="EN-US">ActionSupport</span>集成，则<span lang="EN-US">Struts</span>框架通过<span lang="EN-US">Java</span>的反射机制（<span lang="EN-US">Reflection</span>）来调用<span lang="EN-US">Action</span>类中的处理方法。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Action</span><span style="font-size: 10.5pt; font-family: 宋体;">类的处理方法需要满足以下要求<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">1 public<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">2 </span><span style="font-size: 10.5pt; font-family: 宋体;">返回<span lang="EN-US">String</span>，框架根据返回值决定迁移的目的<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3 </span><span style="font-size: 10.5pt; font-family: 宋体;">（可选）抛出<span lang="EN-US">Exception</span>，让<span lang="EN-US">Struts</span>框架统一处理异常<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.5</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节 <span lang="EN-US">Exception Handling<o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts</span><span style="font-size: 10.5pt; font-family: 宋体;">可以以声明的方式处理<span lang="EN-US">Action</span>类抛出的异常。以声明的方式处理是指：所有的<span lang="EN-US">Action</span>类的处理方法抛出的<span lang="EN-US">Exception</span>会被框架统一处理，之后定向到预先定义的<span lang="EN-US">Result</span>。处理这些异常的<span lang="EN-US">Action</span>，<span lang="EN-US">Result</span>等可以动态的配置。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2</span><span style="font-size: 10.5pt; font-family: 宋体;">自带一个默认的配置：<span lang="EN-US">struts-default.xml</span>，在这个文件中预先定义了一些基本的操作，其中<span lang="EN-US">Exception Handling</span>也在其中，参看下述代码：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;interceptors&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor name="exception" <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class="com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/interceptors&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;interceptor-stack name="defaultStack"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="exception"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="alias"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="servlet-config"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="prepare"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="i18n"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="chain"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="debugging"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="profiling"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="scoped-model-driven"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="model-driven"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="fileUpload"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="checkbox"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="static-params"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="params"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="conversionError"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="validation"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;param name="excludeMethods"&gt;input,back,cancel,browse&lt;/param&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;/interceptor-ref&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="workflow"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;param name="excludeMethods"&gt;input,back,cancel,browse&lt;/param&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;/interceptor-ref&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/interceptor-stack&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">要使用<span lang="EN-US">Struts2</span>声明式异常处理，只需要将异常映射到<span lang="EN-US">result</span>就可以了，可以用两种方法配置，一种方法是全局配置，针对所有的<span lang="EN-US">Action</span>有效，另一种是针对具体的<span lang="EN-US">Action</span>做配置，只针对具体的<span lang="EN-US">Action</span>有效。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">参看如下<span lang="EN-US">struts.xml </span>配置文件片段：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;package name="default"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;global-results&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span>&lt;result name="login" type="redirect"&gt;/Login.action&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;result name="Exception"&gt;/Exception.jsp&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/global-results&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;global-exception-mappings&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;exception-mapping <o:p></o:p></span></p>
<p style="text-indent: 82.4pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">exception="java.sql.SQLException" result="SQLException"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;exception-mapping <o:p></o:p></span></p>
<p style="text-indent: 82.4pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">exception="java.lang.Exception" result="Exception"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/global-exception-mappings&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;action name="DataAccess" class="com.company.DataAccess"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;exception-mapping <o:p></o:p></span></p>
<p style="text-indent: 77.25pt;" class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">exception="com.company.SecurityException" result="login"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;result name="SQLException" type="chain"&gt;SQLExceptionAction&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;result&gt;/DataAccess.jsp&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/action&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/package&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">上述配置有如下结果<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">1 </span><span style="font-size: 10.5pt; font-family: 宋体;">一个<span lang="EN-US">java.sql.SQLException</span>异常将链接到<span lang="EN-US">SQLExceptionAction </span>（上述文件中没有说明）<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">2 </span><span style="font-size: 10.5pt; font-family: 宋体;">一个<span lang="EN-US">com.company.SecurityException</span>将重新定位到<span lang="EN-US">login.action<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3 </span><span style="font-size: 10.5pt; font-family: 宋体;">其他从<span lang="EN-US">java.lang.Exception</span>继承而来的<span lang="EN-US">Exception</span>将会被定为到<span lang="EN-US">/Exception.jsp</span>页面<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.6</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节<span lang="EN-US"> Intercepter</span>拦截器<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">拦截器的运行时机在<span lang="EN-US">Action</span>类运行之前和之后。拦截器使用<span lang="EN-US">Filter</span>模式，将你需要执行的代码放在<span lang="EN-US">Action</span>类处理方法之前或者之后执行。拦截器在开发程序的时候功能非常强大，通过使用拦截器可以完成校验，属性设置，安全，日志，程序剖析等功能。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">拦截器可以彼此链接构成一个拦截器的栈，每一个拦截器本质上是一个<span lang="EN-US">Java</span>类，都有一个常常的类名，为了方便使用，可以在<span lang="EN-US">Struts2</span>框架中注册这些拦截器，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;interceptor name="security" class="com.jpleasure.security.SecurityInterceptor"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;interceptor-stack name="secureStack"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="security"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="defaultStack"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>&lt;/interceptor-stack&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/interceptors&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">拦截器和拦截器栈可以混合使用来定义新的拦截器栈，在调用过程中，框架按照在拦截器栈中的顺序逐个调用这些拦截器。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">可以在<span lang="EN-US">Package</span>中定义默认的拦截器栈，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;default-interceptor-ref name="secureStack"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">当然每一个<span lang="EN-US">Action</span>类也可以定义自己的拦截器栈，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;action name="VelocityCounter" <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class="org.apache.struts2.example.counter.SimpleCounter"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;result name="success"&gt;...&lt;/result&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;interceptor-ref name="defaultComponentStack"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/action&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.7</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节 分离配置文件<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">可以在<span lang="EN-US">struts.xml</span>中使用<span lang="EN-US">include</span>标记将配置文件分离成不同的部分。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;!DOCTYPE struts PUBLIC<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>"http://struts.apache.org/dtds/struts-2.0.dtd"&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;struts&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;include file="Home.xml"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;include file="Hello.xml"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;include file="Simple.xml"/&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;include file="/util/POJO.xml"/&gt;<o:p></o:p></span></p>
<span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/struts&gt;</span><img src ="http://www.blogjava.net/super2/aggbug/237964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:04 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三章 Struts2配置（第二节 Action配置）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237963.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237963.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237963.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237963.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237963.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 3.2 节 Action配置Package配置使用package可以将逻辑上相关的一组Action，Result，Intercepter等组件分为一组，Package有些想对象，可以继承其他的Package，也可以被其他package继承，甚至可以定义抽象的Package。Package的可以使用的属性：                               ...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237963.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:02 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三章 Struts2配置（第一节 struts.properties配置）</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237961.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:01:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237961.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237961.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237961.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237961.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">3.1</span></strong><strong><span style="font-size: 10.5pt; font-family: 宋体;">节 <span lang="EN-US">struts.properties</span>配置<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.properties</span></strong><span style="font-size: 10.5pt; font-family: 宋体;">文件在<span lang="EN-US">WEB-INF/classes</span>目录下存放。<strong><span lang="EN-US"><o:p></o:p></span></strong></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">这个文件用来配置<span lang="EN-US">Struts2</span>系统的一些基本规约，所有在<span lang="EN-US">struts.properties</span>中配置的内容都可以在<span lang="EN-US">struts.xml</span>中配置，或者<span lang="EN-US">web.xml</span>中在<span lang="EN-US">struts2 filter</span>中配置，例如：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts.properties</span><span style="font-size: 10.5pt; font-family: 宋体;">中的如下配置：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.i18n.encoding=UTF-8<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">相当于<span lang="EN-US">struts.xml</span>中的如下配置：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;constant name=</span><span style="font-size: 10.5pt; font-family: 宋体;">&#8220;<span lang="EN-US">struts.i18n.encoding</span>&#8221;<span lang="EN-US"> value=</span>&#8220;<span lang="EN-US">true</span>&#8221;<span lang="EN-US"> /&gt;<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">相当于<span lang="EN-US">web.xml</span>中的如下配置：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;filter&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp; </span><span>&nbsp;</span>&lt;filter-name&gt;struts&lt;/filter-name&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;filter-class&gt;org.apache.struts2.dispatcher.FilterDispatcher&lt;/filter-class&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;init-param&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;param-name&gt;struts.i18n.encoding&lt;/param-name&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;param-value&gt;true&lt;/param-value&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&lt;/init-param&gt;<o:p></o:p></span></p>
<span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">&lt;/filter&gt;</span><img src ="http://www.blogjava.net/super2/aggbug/237961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:01 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三章 Struts2配置</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237960.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 02:00:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237960.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237960.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237960.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237960.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;">与<span lang="EN-US">Struts 1.X</span>不同，<span lang="EN-US">Struts2</span>引入了<span lang="EN-US">WebWork</span>的配置机制，在很大程度上提高了配置的灵活度。通过使用配置可以配置如下内容：<span lang="EN-US"><o:p></o:p></span></span></p>
<table class="MsoTableGrid" style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 50%; width: 217.55pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="290">
            <p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;">配置类型<span lang="EN-US"><o:p></o:p></span></span></strong></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #e0e0e0 none repeat scroll 0% 50%; width: 217.55pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="290">
            <p class="MsoNormal"><strong><span style="font-size: 10.5pt; font-family: 宋体;">配置文件<span lang="EN-US"><o:p></o:p></span></span></strong></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   </span><span style="font-size: 10.5pt; font-family: 宋体;">参数配置<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.properties<o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   Action </span><span style="font-size: 10.5pt; font-family: 宋体;">配置<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   Result </span><span style="font-size: 10.5pt; font-family: 宋体;">配置<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   Exception Handling </span><span style="font-size: 10.5pt; font-family: 宋体;">配置<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   Intercept </span><span style="font-size: 10.5pt; font-family: 宋体;">配置<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">Struts2   </span><span style="font-size: 10.5pt; font-family: 宋体;">多配置文件<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 217.55pt;" valign="top" width="290">
            <p class="MsoNormal"><span style="font-size: 10.5pt; font-family: 宋体;" lang="EN-US">struts.xml<o:p></o:p></span></p>
            </td>
        </tr>
    </tbody>
</table>
<span style="font-size: 10.5pt; font-family: 宋体;">另外还说明了<span lang="EN-US">Action</span>接口和<span lang="EN-US">ActionSupport</span>类的一些情况。</span><img src ="http://www.blogjava.net/super2/aggbug/237960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 10:00 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第二章 一个简单的Login 应用程序</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237959.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237959.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237959.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237959.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237959.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第一节 需求定义简单的需求如下图                                                1 用户处在Welcome.jsp 页面，点击登录连接到达Login.jsp页面            2 在Login.jsp输入用户名密码，点击登陆按钮，转到LoginAction处理            ...&nbsp;&nbsp;<a href='http://www.blogjava.net/super2/archive/2008/11/01/237959.html'>阅读全文</a><img src ="http://www.blogjava.net/super2/aggbug/237959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 09:59 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一章 Struts2 概览</title><link>http://www.blogjava.net/super2/archive/2008/11/01/237957.html</link><dc:creator>淘声依旧</dc:creator><author>淘声依旧</author><pubDate>Sat, 01 Nov 2008 01:57:00 GMT</pubDate><guid>http://www.blogjava.net/super2/archive/2008/11/01/237957.html</guid><wfw:comment>http://www.blogjava.net/super2/comments/237957.html</wfw:comment><comments>http://www.blogjava.net/super2/archive/2008/11/01/237957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super2/comments/commentRss/237957.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super2/services/trackbacks/237957.html</trackback:ping><description><![CDATA[<font size="3"><span style="font-weight: bold;">Struts 是什么？</span></font><br />
<br />
Struts 2 是一个雅致的，可扩展的，用来建立企业级Java Web应用程序的框架。<br />
Struts 2 不但注重程序的开发过程，更注重部署和后期维护。<br />
Struts 2 来源于WebWork 2。<br />
Struts 2 融合了Struts 和 WebWork的社区力量，是这两个社区努力的结果。<br />
Struts 2 非常容易使用。<br />
Struts 2 最大可能的保留了和Strut 1.x的相似行。<br />
<br />
<font size="3"><span style="font-weight: bold;">Struts2 的特性有那些？</span></font><br />
<br />
上面提到，Struts 2 关注开发，部署和后期维护三个方面。我们就从这三个方面说明Struts 2 的新特性。<br />
<br />
<font size="2"><span style="font-weight: bold;">构建</span></font><br />
&nbsp;&nbsp;&nbsp; 上手非常容易，可以使用起步教程，模板工程或者Maven原型建立Struts 2工程。（起步简单）<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Struts 2 的官方站点上有很多关于Struts 2入门的资料，<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Struts 2 的下载目录中包含空白的模板工程（struts2-blank-2.x.war）和示例工程（struts2-showcase-2.x.war）可以参考。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  Maven 2 中有Struts 2 的项目模板，可以使用Maven 2 直接建立Struts 2 工程<br />
<br />
&nbsp;&nbsp;&nbsp; 更好的设计，Struts 2 中不想要要在在处理和HTTP相关的操作，自需要使用框架的接口即可。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在Strut 2 中不再会涉及到诸如 HttpServletRequest, HttpServletResponse，
HttpSession等Http相关的Servlet接口类，取而代之的是Struts 2
的接口，例如RequestAware，SessionAware等。<br />
<br />
&nbsp;&nbsp;&nbsp; 强大的标签库，Struts 2 的标签基于 CSS，标签可以提供自己需要的HTML支持。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Struts 2 的标签利用了CSS和模板，使用起来会非常方便，在Struts
1.x中我们需要使用Table来组织表单，但是在Struts
2中所有的标签自带了Table内容，可以方便的处理格式。例如&lt;s:textfield&gt; 标签自动添加了 &lt;tr&gt;
&lt;td&gt; 等标签。<br />
<br />
&nbsp;&nbsp;&nbsp; 有状态的Checkbox，可以以一种统一的方式记录checkbox状态的变化。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  在Struts 2中即使没有被选中的checkbox其内容仍然存在于Struts 2 框架中，不必像在Struts 1.x中那样需要做特殊的存在性判断。<br />
<br />
&nbsp;&nbsp;&nbsp; 灵活的取消按钮，在取消按钮点击的时候可以指向一个不同的action。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  @TODO<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 可以在制定Form的action的同时，制定cancel按钮的action，当点击submit和cancel的时候出现完全按不同的功能。<br />
<br />
&nbsp;&nbsp;&nbsp; 第一等级的AJAX的支持，在普通struts 标签的基础上，使用AJAX增加了交互性和灵活性。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  Struts 2 的标签内置了Ajax的支持。Struts 2 的标签使用了Dojotoolkit Ajax框架，不但能够使用Ajax特性，而且能够使用非常丰富和强大的浏览器小控件，例如日期选择控件<br />
<br />
&nbsp;&nbsp;&nbsp; 见到那集成Spring框架，非常简单的使用Spring框架提供的依赖注入功能。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  可以方便的使用Spring管理Struts 2 的action的创建，通过使用Spring可以充分的利用Spring的依赖诸如功能，并且能够很好的集成其他的框架，例如Hibernate，iBatis等。<br />
<br />
&nbsp;&nbsp;&nbsp; 更多的返回形式，除了JSP还支持，JasperReports,JFreeChart, Action链，文件下载等。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  除了支持JSP的表现形式，还支持JasperResports报表， JFreechart图标，Action链，文件下载等。<br />
<br />
&nbsp;&nbsp;&nbsp; POJO表单，不再需要ActionForms，使用Javabean获得客户的收入或者将属性表示出来，<br />
&nbsp;&nbsp;&nbsp;
完全消除了ActionForm组建，可以使用任意合适的类型来接受页面传来的数据或者将数据表现出来。ActionFrom可以使用POJO的
JavaBean来替代，JavaBean中的属性可以使用String，也可以使用具体的类型，例如Date，Int等。 <br />
<br />
&nbsp;&nbsp;&nbsp; POJO Action，使用任意的类作为Action类，甚至可以使用接口。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 任何类都可以作为Action类，只要接口满足一些简单的定义，不需要在使用Action类似的基类，你可以完全自由的发挥。<br />
<br />
部署<br />
&nbsp;&nbsp;&nbsp; 插件结构，使用jar文件扩展框架功能，不需要在做手动的配置，内置了JavaServer Faces， JasperResports, JFreeChart, Tiles等插件。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 扩展一个功能只需要添加一个插件，插件甚至可以热插拔，在你的应用不停止的情况下追加新的功能。<br />
<br />
&nbsp;&nbsp;&nbsp; 集成了分析功能，可以方便的找到程序性能的问题点。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  可以不借助外力发现程序的热点，找到问题的所在，<br />
<br />
&nbsp;&nbsp;&nbsp; 准确的报告错误，可以非常准确的指出程序的问题点。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  准确的报告运行时的错误，方便解决问题。<br />
<br />
维护<br />
&nbsp;&nbsp;&nbsp; Action容易测试，直接测试Struts 2的Action，不需要使用Mock Http对象来测试。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  Action是普通的类，不需要特殊的环境，所以Struts 2 的Action 特别容易测试。<br />
<br />
&nbsp;&nbsp;&nbsp; 聪明的默认值，不需要配置不必要的配置，大部分的框架配置元素的都有非常合适的默认值，基本上你不需要在做任何配置。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  Struts 2 有很多的配置项，但是每一个都有默认值，基本额上不需要更改默认的选项即可保证最佳<br />
<br />
&nbsp;&nbsp;&nbsp; 容易定制的控制器，可以定制每一个Action的处理过程。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  可以使用Intercepter来过滤每一个Action，在Action执行前后追加自定义的操作。<br />
<br />
&nbsp;&nbsp;&nbsp; 集成了Debugging，可以使用内容之的debugging工具找到问题。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  <br />
&nbsp;&nbsp;&nbsp;&nbsp; 灵活的标签库，可以通过修改FreeMarker模板来定制标签的输出，不需要在操作像天书异样的JSP Taglib API，模板语言支持，Freemarker和Velocity &nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  可以自定义模板库，或者修改已有模板的内容来定制页面的显示。<br />
<br />
Struts 2 中使用的模式<br />
Command<br />
Chain of responsibility<br />
<br />
Struts2 处理流程概要<br />
<img src="http://docs.google.com/File?id=dd4s87gd_64g9264nfg" style="width: 640px; height: 750px;" alt="" /><br />
上图来源于Struts2官方站点，是Struts 2 的整体结构。<br />
一个请求在Struts2框架中的处理大概分为以下几个步骤<br />
1 客户端初始化一个指向Servlet容器（例如Tomcat）的请求<br />
2 这个请求经过一系列的过滤器（Filter）（这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器，这个过滤器对于Struts2和其他框架的集成很有帮助，例如：SiteMesh Plugin）<br />
3 接着FilterDispatcher被调用，FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action<br />
4 如果ActionMapper决定需要调用某个Action，FilterDispatcher把请求的处理交给ActionProxy<br />
5 ActionProxy通过Configuration Manager询问框架的配置文件，找到需要调用的Action类<br />
6 ActionProxy创建一个ActionInvocation的实例。<br />
7 ActionInvocation实例使用命名模式来调用，在调用Action的过程前后，涉及到相关拦截器（Intercepter）的调用。<br />
8
一旦Action执行完毕，ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是（但不总是，也可
能是另外的一个Action链）一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2
框架中继承的标签。在这个过程中需要涉及到ActionMapper<br />
&nbsp;<br />
在上述过程中所有的对象（Action，Results，Interceptors，等）都是通过ObjectFactory来创建的。<img src ="http://www.blogjava.net/super2/aggbug/237957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super2/" target="_blank">淘声依旧</a> 2008-11-01 09:57 <a href="http://www.blogjava.net/super2/archive/2008/11/01/237957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>