﻿<?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-                                  &lt;center&gt;&lt;font size=5&gt;心的方向&lt;/center&gt;-随笔分类-框架整合</title><link>http://www.blogjava.net/zilong/category/30712.html</link><description>                           &lt;center&gt;   新的征途...... &lt;/center&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 10 Apr 2008 14:46:29 GMT</lastBuildDate><pubDate>Thu, 10 Apr 2008 14:46:29 GMT</pubDate><ttl>60</ttl><item><title>Spring与Struts如何整合</title><link>http://www.blogjava.net/zilong/archive/2008/04/10/191909.html</link><dc:creator>阿伟</dc:creator><author>阿伟</author><pubDate>Thu, 10 Apr 2008 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/zilong/archive/2008/04/10/191909.html</guid><wfw:comment>http://www.blogjava.net/zilong/comments/191909.html</wfw:comment><comments>http://www.blogjava.net/zilong/archive/2008/04/10/191909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zilong/comments/commentRss/191909.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zilong/services/trackbacks/191909.html</trackback:ping><description><![CDATA[<h3><a href="http://lihaiyan.javaeye.com/blog/127812"><span style="font-size: 10pt">Spring与Struts如何整合</span></a></h3>
<span style="font-size: 10pt">转自：http://lihaiyan.javaeye.com/blog/127812<br />
</span>
<div class="blog_content">
<div class="postText"><span style="font-size: 10pt">为了在Struts中加载Spring context，需要在struts-config.xml文件中加入如下部分：<br />
</span><span style="color: #0000cc"><span style="font-size: 10pt">&lt;struts-config&gt;<br />
&nbsp; &lt;plug-in<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;set-property property="contextConfigLocation"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value="/WEB-INF/applicationContext.xml" /&gt;<br />
&nbsp; &lt;/plug-in&gt;<br />
&lt;/struts-config&gt;</span></span></div>
<div class="postText"><span style="font-size: 10pt"><span style="color: #0000cc">第一种方法：</span><br />
&nbsp;&nbsp;&nbsp; 通过Struts的plug-in在Struts和Spring之间提供了良好的结合点。通过plug-in我们实现了Spring context的加载，不过仅仅加载Spring context并没有什么实际的意义，还应该经过配置将Struts的Action交给Spring容器进行管理。<br />
</span><span style="font-size: 10pt"><span style="color: #0000ff">&lt;action-mappings&gt;<br />
&nbsp; &lt;action path="/login"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="org.springframework.web.struts.DelegatingActionProxy"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="loginForm"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="success" path="/main.jsp" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="failure" path="/login.jsp" /&gt;<br />
&lt;/action&gt;<br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp; 在form bean这个节点上与传统的Struts配置没有什么区别，而在Action上面则发生了变化。在传统的action节点上type属性写入action类的完整类名，而和Spring结合后在这点上是使用了Spring提供的</span><span style="color: #0000ff">DelegatingActionProxy</span></span><span style="color: #000000"><span style="font-size: 10pt">作为action的type属性，<span style="color: #0000ff">DelegatingActionProxy</span>同样是org.apache.struts.action.Action的一个子类，它将把调用请求转交给真正的Action实现。通过这样的方式，Spring获得了Action实例的管理权，它将对Action进行调度，并为Struts提供所需的Action实例。这样，就可以将Action看作是Spring的一个bean，它就可以享受Spring的所有服务，如依赖注入、实例管理、事务管理等。<br />
&nbsp;&nbsp;&nbsp; 在applicationContext.xml中相应的配置如下的节点：<br />
</span><span style="font-size: 10pt"><span style="color: #0000cc">&lt;beans&gt;<br />
.......<br />
&nbsp;&nbsp;&nbsp; &lt;bean name="/login" class="net.xiaxin.action.LoginAction"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;singleton="false"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="userDAO"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="userDAOProxy" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&lt;/beans&gt;<br />
</span>&nbsp;&nbsp;&nbsp; 最后这个bean的配置是关键，这个名为&#8220;/login&#8221;的bean与Struts中的<br />
</span><span style="font-size: 10pt"><span style="color: #0000cc">&lt;action path="/login" &#8230;&#8230;&gt;<br />
&#8230;&#8230;<br />
&lt;/action&gt;</span>节点相对应，这样，Spring Bean Name与Struts Action Path相关联，当Struts加载对应的Action时，DelegatingActionProxy就根据传入的path属性，在Spring Context寻找对应bean，并将其实例返回给Struts。与此同时，还可以看到，"/login" bean 中包含了一个userDAO 引用，Spring 在运行期将根据配置为其提供userDAO 实例，以及围绕userDAO 的事务管理服务。这样一来，对于Struts 开发而言，我们既可以延续Struts 的开发流程，也可以享受Spring 提供的事务管<br />
理服务。而bean 的另外一个属性singleton="false"，指明了Action 的实例获取方式为每次重新创建。这也解决了Struts中令人诟病的线程安全问题。</span></span></div>
<div class="postText"><span style="color: #000000"><span style="font-size: 10pt">第二种方法：</span></span></div>
<div class="postText"><span style="color: #000000">
<p><span style="font-size: 10pt">为了在 <span class="emphasis"><em>struts-config.xml</em></span> 文件中配置 </span><a href="http://www.springframework.org/docs/api/org/springframework/web/struts/DelegatingRequestProcessor.html" target="_top"><tt class="literal"><span style="font-family: 新宋体"><span style="font-size: 10pt">DelegatingRequestProcessor</span></span></tt></a><span style="font-size: 10pt">，你需要重载 &lt;controller&gt; 元素的 &#8220;processorClass&#8221; 属性。 下面的几行应该放在 &lt;action-mapping&gt; 元素的后面。 </span></p>
<pre class="programlisting"><span style="font-size: 10pt">&lt;controller&gt;
&lt;set-property property="processorClass"
value="http://www.zhmy.com/org.springframework.web.struts.DelegatingRequestProcessor"/&gt;
&lt;/controller&gt;</span></pre>
<p><span style="font-size: 10pt">增加这些设置之后，不管你查询任何类型的 Action，Sping都自动在它的context配置文件中寻找。 实际上，你甚至不需要指定类型。下面两个代码片断都可以工作： </span></p>
<pre class="programlisting"><span style="font-size: 10pt">&lt;action path="/user" type="com.whatever.struts.UserAction"/&gt;
&lt;action path="/user"/&gt;</span></pre>
<p><span style="font-size: 10pt">如果你使用 Struts 的 <span class="emphasis"><em>modules</em></span> 特性，你的 bean 命名必须含有 module 的前缀。 举个例子，如果一个 Action 的定义为 <tt class="literal"><span style="font-family: 新宋体">&lt;action path="/user"/&gt;</span></tt>，而且它的 module 前缀为&#8220;admin&#8221;， 那么它应该对应名为 <tt class="literal"><span style="font-family: 新宋体">&lt;bean name="/admin/user"/&gt;</span></tt> 的 bean</span></p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in">
<table summary="Note" border="0">
    <tbody>
        <tr>
            <td valign="top" align="center" width="25" rowspan="2"><span style="font-size: 10pt">&nbsp;</span></td>
            <th align="left"><span style="font-size: 10pt">&nbsp;</span></th>
        </tr>
        <tr>
            <td valign="top" align="left" colspan="2">
            <div><span style="font-size: 10pt">如果你在 Struts 应用中使用了 Tiles，你需要配置 &lt;controller&gt; 为 </span><a href="http://www.springframework.org/docs/api/org/springframework/web/struts/DelegatingTilesRequestProcessor.html" target="_top"><tt class="classname"><span style="font-family: 新宋体"><span style="font-size: 10pt">DelegatingTilesRequestProcessor</span></span></tt></a><span style="font-size: 10pt">。 </span></div>
            </td>
        </tr>
    </tbody>
</table>
</div>
</span></div>
<div class="postText"><br />
<span style="font-size: 10pt">如果第二种方法不行，再用第一种方法。&nbsp;&nbsp;&nbsp;</span></div>
<div class="postText"><span style="font-size: 10pt">&nbsp;至此，SS组合已经将Struts MVC以及Spring中的Bean管理、事务管理融为一体。如<br />
果算上userDAO 中的Hibernate 部分，我们就获得了一个全面、成熟、高效、自顶而下的<br />
Web 开发框架。</span></div>
<p class="postText"><span style="font-size: 10pt">来源:http://deathmask1980.spaces.live.com/blog/cns!8633c46371110374!118.entry</span></p>
</div>
<br />
<img src ="http://www.blogjava.net/zilong/aggbug/191909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zilong/" target="_blank">阿伟</a> 2008-04-10 16:46 <a href="http://www.blogjava.net/zilong/archive/2008/04/10/191909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate实现上传下载(四)</title><link>http://www.blogjava.net/zilong/archive/2008/04/10/191865.html</link><dc:creator>阿伟</dc:creator><author>阿伟</author><pubDate>Thu, 10 Apr 2008 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/zilong/archive/2008/04/10/191865.html</guid><wfw:comment>http://www.blogjava.net/zilong/comments/191865.html</wfw:comment><comments>http://www.blogjava.net/zilong/archive/2008/04/10/191865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zilong/comments/commentRss/191865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zilong/services/trackbacks/191865.html</trackback:ping><description><![CDATA[<h3><a href="http://lihaiyan.javaeye.com/blog/127797"><span style="font-size: 10pt">Struts+Spring+Hibernate实现上传下载(四)</span></a></h3>
<span style="font-size: 10pt">转自：http://lihaiyan.javaeye.com/blog/127797<br />
</span>
<div class="blog_content">
<p><span class="span"><span style="font-size: 10pt"><strong>Web层实现<br />
<br />
</strong>　　1、Web层的构件和交互流程<br />
<br />
　　Web层包括主要3个功能：<br />
<br />
　　&#183;上传文件。<br />
<br />
　　&#183;列出所有已经上传的文件列表，以供点击下载。<br />
<br />
　　&#183;下载文件。<br />
<br />
　　Web层实现构件包括与2个JSP页面，1个ActionForm及一个Action：<br />
<br />
　　&#183;file-upload.jsp：上传文件的页面。<br />
<br />
　　&#183;file-list.jsp：已经上传文件的列表页面。<br />
<br />
　　&#183;FileActionForm：file-upload.jsp页面表单对应的ActionForm。<br />
<br />
　　&#183;FileAction：继承org.apache.struts.actions.DispatchAction的Action，这样这个Action就可以通过一个URL参数区分中响应不同的请求。<br />
<br />
　　Web层的这些构件的交互流程如图 6所示：<br />
<br />
</span></span></p>
<p>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" height="167" alt="" src="http://soft.yesky.com/imagelist/05/12/f7r1dsl4iy25.jpg" width="420" onload="rsimg(this,420)" _counted="undefined" resized="true" />420){this.resized=true;this.style.width=420;}" border=0 resized="true"&gt;<br />
            图 6 Web层Struts流程图</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　其中，在执行文件上传的请求时，FileAction在执行文件上传后，forward到loadAllFile出口中，loadAllFile加载数据库中所有已经上传的记录，然后forward到名为fileListPage的出口中，调用file-list.jsp页面显示已经上传的记录。<br />
<br />
　　2、FileAction功能<br />
<br />
　　Struts 1.0的Action有一个弱项：一个Action只能处理一种请求，Struts 1.1中引入了一个DispatchAction，允许通过URL参数指定调用Action中的某个方法，如http://yourwebsite/fileAction.do?method=upload即调用FileAction中的upload方法。通过这种方式，我们就可以将一些相关的请求集中到一个Action当中编写，而没有必要为某个请求操作编写一个Action类。但是参数名是要在struts-config.xml中配置的：<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. ＜struts-config＞<br />
            2. ＜form-beans＞<br />
            3. ＜form-bean name="fileActionForm" type="sshfile.web.FileActionForm" /＞<br />
            4. ＜/form-beans＞<br />
            5. ＜action-mappings＞<br />
            6. ＜action name="fileActionForm" parameter="method" path="/fileAction"<br />
            7. type="sshfile.web.FileAction"＞<br />
            8. ＜forward name="fileListPage" path="/file-list.jsp" /＞<br />
            9. ＜forward name="loadAllFile" path="/fileAction.do?method=listAllFile" /＞<br />
            10. ＜/action＞<br />
            11. ＜/action-mappings＞<br />
            12. ＜/struts-config＞</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　第6行的parameter="method"指定了承载方法名的参数，第9行中，我们还配置了一个调用FileAction不同方法的Action出口。<br />
<br />
　　FileAction共有3个请求响应的方法，它们分别是：<br />
<br />
　　&#183;upload(&#8230;)：处理上传文件的请求。<br />
<br />
　　&#183;listAllFile(&#8230;)：处理加载数据库表中所有记录的请求。<br />
<br />
　　&#183;download（&#8230;）：处理下载文件的请求。<br />
<br />
　　下面我们分别对这3个请求处理方法进行讲解。<br />
<br />
　　2.1 上传文件<br />
<br />
　　上传文件的请求处理方法非常简单，简之言之，就是从Spring容器中获取业务层处理类FileService，调用其save(FileActionForm form)方法上传文件，如下所示：<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. public class FileAction<br />
            2. extends DispatchAction<br />
            3. {<br />
            4. //将上传文件保存到数据库中<br />
            5. public ActionForward upload(ActionMapping mapping, ActionForm form,<br />
            6. HttpServletRequest request,<br />
            7. HttpServletResponse response)<br />
            8. {<br />
            9. FileActionForm fileForm = (FileActionForm) form;<br />
            10. FileService fileService = getFileService();<br />
            11. fileService.save(fileForm);<br />
            12. return mapping.findForward("loadAllFile");<br />
            13. }<br />
            14. //从Spring容器中获取FileService对象<br />
            15. private FileService getFileService()<br />
            16. {<br />
            17. ApplicationContext appContext = WebApplicationContextUtils.<br />
            18. getWebApplicationContext(this.getServlet().getServletContext());<br />
            19. return (FileService) appContext.getBean("fileService");<br />
            20. }<br />
            21. &#8230;<br />
            22. }</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　由于FileAction其它两个请求处理方法也需要从Spring容器中获取FileService实例，所以我们特别提供了一个getFileService()方法（第15~21行）。重构的一条原则就是："发现代码中有重复的表达式，将其提取为一个变量；发现类中有重复的代码段，将其提取为一个方法；发现不同类中有相同的方法，将其提取为一个类"。在真实的系统中，往往拥有多个Action和多个Service类，这时一个比较好的设置思路是，提供一个获取所有Service实现对象的工具类，这样就可以将Spring 的Service配置信息屏蔽在一个类中，否则Service的配置名字散落在程序各处，维护性是很差的。<br />
<br />
　　2.2 列出所有已经上传的文件<br />
<br />
　　listAllFile方法调用Servie层方法加载T_FILE表中所有记录，并将其保存在Request域中，然后forward到列表页面中：<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. public class FileAction<br />
            2. extends DispatchAction<br />
            3. {<br />
            4. &#8230;<br />
            5. public ActionForward listAllFile(ActionMapping mapping, ActionForm form,<br />
            6. HttpServletRequest request,<br />
            7. HttpServletResponse response)<br />
            8. throws ModuleException<br />
            9. {<br />
            10. FileService fileService = getFileService();<br />
            11. List fileList = fileService.getAllFile();<br />
            12. request.setAttribute("fileList",fileList);<br />
            13. return mapping.findForward("fileListPage");<br />
            14. }<br />
            15. }</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　file-list.jsp页面使用Struts标签展示出保存在Request域中的记录：<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. ＜%@page contentType="text/html; charset=GBK"%＞<br />
            2. ＜%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%＞<br />
            3. ＜%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%＞<br />
            4. ＜html＞<br />
            5. ＜head＞<br />
            6. ＜title＞file-download＜/title＞<br />
            7. ＜/head＞<br />
            8. ＜body bgcolor="#ffffff"＞<br />
            9. ＜ol＞<br />
            10. ＜logic:iterate id="item" name="fileList" scope="request"＞<br />
            11. ＜li＞<br />
            12. ＜a href='fileAction.do?method=download&amp;fileId=<br />
            13. ＜bean:write name="item"property="fileId"/＞'＞<br />
            14. ＜bean:write name="item" property="fileName"/＞<br />
            15. ＜/a＞<br />
            16. ＜/li＞<br />
            17. ＜/logic:iterate＞<br />
            18. ＜/ol＞<br />
            19. ＜/body＞<br />
            20. ＜/html＞</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　展现页面的每条记录挂接着一个链接地址，形如：fileAction.do?method=download&amp;fileId=xxx，method参数指定了这个请求由FileAction的download方法来响应，fileId指定了记录的主键。<br />
<br />
　　由于在FileActionForm中，我们定义了fileId的属性，所以在download响应方法中，我们将可以从FileActionForm中取得fileId的值。这里涉及到一个处理多个请求Action所对应的ActionForm的设计问题，由于原来的Action只能对应一个请求，那么原来的ActionForm非常简单，它仅需要将这个请求的参数项作为其属性就可以了，但现在一个Action对应多个请求，每个请求所对应的参数项是不一样的，此时的ActionForm的属性就必须是多请求参数项的并集了。所以，除了文件上传请求所对应的fileContent和remark属性外还包括文件下载的fileId属性：<br />
<br />
</span></p>
<p>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://soft.yesky.com/imagelist/05/12/86u0y1fafg9o.jpg" onload="rsimg(this,420)" _counted="undefined" />420){this.resized=true;this.style.width=420;}" border=0&gt;<br />
            图 7 FileActionForm</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　当然这样会造成属性的冗余，比如在文件上传的请求中，只会用到fileContent和remark属性，而在文件下载的请求时，只会使用到fileId属性。但这种冗余是会带来好处的--它使得一个Action可以处理多个请求。<br />
<br />
　　2.3 下载文件<br />
<br />
　　在列表页面中点击一个文件下载，其请求由FileAction的download方法来响应，download方法调用业务层的FileService方法，获取文件数据并写出到response的响应流中。通过合理设置HTTP响应头参数，将响应流在客户端表现为一个下载文件对话框，其代码如下所示：<br />
<br />
　　代码 10 业务接口实现类之download<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. public class FileAction<br />
            2. extends DispatchAction<br />
            3. {<br />
            4. &#8230;<br />
            5. public ActionForward download(ActionMapping mapping, ActionForm form,<br />
            6. HttpServletRequest request,<br />
            7. HttpServletResponse response)<br />
            8. throws ModuleException<br />
            9. {<br />
            10. FileActionForm fileForm = (FileActionForm) form;<br />
            11. FileService fileService = getFileService();<br />
            12. String fileName = fileService.getFileName(fileForm.getFileId());<br />
            13. try<br />
            14. {<br />
            15. response.setContentType("application/x-msdownload");<br />
            16. response.setHeader("Content-Disposition",<br />
            17. "attachment;" + " filename="+<br />
            18. new String(fileName.getBytes(), "ISO-8859-1"));<br />
            19. fileService.write(response.getOutputStream(), fileForm.getFileId());<br />
            20. }<br />
            21. catch (Exception e)<br />
            22. {<br />
            23. throw new ModuleException(e.getMessage());<br />
            24. }<br />
            25. return null;<br />
            26. }<br />
            27. }</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　第15~18行，设置HTTP响应头，将响应类型设置为application/x-msdownload MIME类型，则响应流在IE中将弹出一个文件下载的对话框，如图 4所示。IE所支持的MIME类型多达26种，您可以通过这个网址查看其他的MIME类型：<br />
<br />
</span><a href="http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.asp" target="_blank"><span style="font-size: 10pt">http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.asp</span></a><span style="font-size: 10pt">。<br />
<br />
　　如果下载文件的文件名含有中文字符，如果不对其进行硬编码，如第18行所示，客户文件下载对话框中出现的文件名将会发生乱码。<br />
第19行代码获得response的输出流，作为FileServie write(OutputStream os,String fileId)的入参，这样文件的内容将写到response的输出流中。<br />
<br />
　　3、web.xml文件的配置<br />
<br />
　　Spring容器在何时启动呢？我可以在Web容器初始化来执行启动Spring容器的操作，Spring提供了两种方式启动的方法：<br />
<br />
　　&#183;通过org.springframework.web.context .ContextLoaderListener容器监听器，在Web容器初始化时触发初始化Spring容器，在web.xml中通过＜listener＞＜/listener＞对其进行配置。<br />
<br />
　　&#183;通过Servlet org.springframework.web.context.ContextLoaderServlet，将其配置为自动启动的Servlet，在Web容器初始化时，通过这个Servlet启动Spring容器。<br />
<br />
　　在初始化Spring容器之前，必须先初始化log4J的引擎，Spring也提供了容器监听器和自动启动Servlet两种方式对log4J引擎进行初始化：<br />
<br />
　　&#183;org.springframework.web.util .Log4jConfigListener<br />
<br />
　　&#183;org.springframework.web.util.Log4jConfigServlet<br />
<br />
　　下面我们来说明如何配置web.xml启动Spring容器：<br />
<br />
　　代码 11 web.xml中对应Spring的配置内容<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. ＜web-app＞<br />
            2. ＜context-param＞<br />
            3. ＜param-name＞contextConfigLocation＜/param-name＞<br />
            4. ＜param-value＞/WEB-INF/applicationContext.xml＜/param-value＞<br />
            5. ＜/context-param＞<br />
            6. ＜context-param＞<br />
            7. ＜param-name＞log4jConfigLocation＜/param-name＞<br />
            8. ＜param-value＞/WEB-INF/log4j.properties＜/param-value＞<br />
            9. ＜/context-param＞<br />
            10. ＜servlet＞<br />
            11. ＜servlet-name＞log4jInitServlet＜/servlet-name＞<br />
            12. ＜servlet-class＞org.springframework.web.util.Log4jConfigServlet＜/servlet-class＞<br />
            13. ＜load-on-startup＞1＜/load-on-startup＞<br />
            14. ＜/servlet＞<br />
            15. ＜servlet＞<br />
            16. ＜servlet-name＞springInitServlet＜/servlet-name＞<br />
            17. ＜servlet-class＞org.springframework.web.context.ContextLoaderServlet＜/servlet-class＞<br />
            18. ＜load-on-startup＞2＜/load-on-startup＞<br />
            19. ＜/servlet＞<br />
            20. &#8230;<br />
            21. ＜/web-app＞</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　启动Spring容器时，需要得到两个信息：Spring配置文件的地址和Log4J属性文件，这两上信息分别通过contextConfigLocationWeb和log4jConfigLocation容器参数指定，如果有多个Spring配置文件，则用逗号隔开，如：<br />
<br />
/WEB-INF/applicationContext_1.xml, /WEB-INF/applicationContext_1.xm2<br />
<br />
　　由于在启动ContextLoaderServlet之前，必须事先初始化Log4J的引擎，所以Log4jConfigServlet必须在ContextLoaderServlet之前启动，这通过＜load-on-startup＞来指定它们启动的先后顺序。<br />
<br />
　　乱码是开发Web应用程序一个比较老套又常见问题，由于不同Web应用服务器的默认编码是不一样的，为了方便Web应用在不同的Web应用服务器上移植，最好的做法是Web程序自身来处理编码转换的工作。经典的作法是在web.xml中配置一个编码转换过滤器，Spring就提供了一个编码过滤器类CharacterEncodingFilter，下面，我们为应用配置上这个过滤器：<br />
<br />
</span></p>
<p>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. ＜web-app＞<br />
            2. &#8230;<br />
            3. ＜filter＞<br />
            4. ＜filter-name＞encodingFilter＜/filter-name＞<br />
            5. ＜filter-class＞org.springframework.web.filter.CharacterEncodingFilter＜/filter-class＞<br />
            6. ＜init-param＞<br />
            7. ＜param-name＞encoding＜/param-name＞<br />
            8. ＜param-value＞GBK＜/param-value＞<br />
            9. ＜/init-param＞<br />
            10. ＜/filter＞<br />
            11. ＜filter-mapping＞<br />
            12. ＜filter-name＞encodingFilter＜/filter-name＞<br />
            13. ＜url-pattern＞/*＜/url-pattern＞<br />
            14. ＜/filter-mapping＞<br />
            15. &#8230;<br />
            16. ＜/web-app＞</span></td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<span style="font-size: 10pt">　　Spring的过滤器类是org.springframework.web.filter.CharacterEncodingFilter，通过encoding参数指定编码转换类型为GBK，＜filter-mapping＞的配置使该过滤器截获所有的请示。<br />
<br />
　　Struts的框架也需要在web.xml中配置，想必读者朋友对Struts的配置都很熟悉，故在此不再提及，请参见本文所提供的源码。<br />
<br />
　　<strong>总结</strong><br />
<br />
　　本文通过一个文件上传下载的Web应用，讲解了如何构建基于SSH的Web应用，通过Struts和FormFile，Spring的LobHandler以及Spring为HibernateBlob处理所提供的用户类BlobByteArrayType ，实现上传和下载文件的功能仅需要廖廖数行的代码即告完成。读者只需对程序作稍许的调整，即可处理Clob字段：<br />
<br />
　　&#183;领域对象对应Clob字段的属性声明为String类型；<br />
<br />
　　&#183;映射文件对应Clob字段的属性声明为org.springframework.orm.hibernate3.support.ClobStringType类型。<br />
<br />
　　本文通过SSH对文件上传下载简捷完美的实现得以管中窥豹了解SSH强强联合构建Web应用的强大优势。在行文中，还穿插了一些分层的设计经验，配置技巧和Spring所提供的方便类，相信这些知识对您的开发都有所裨益。</span></p>
<p><span style="font-size: 10pt"><span class="span">作者：陈雄华</span><span class="span">出处：天极开发</span></span></p>
</div>
<br />
<img src ="http://www.blogjava.net/zilong/aggbug/191865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zilong/" target="_blank">阿伟</a> 2008-04-10 15:03 <a href="http://www.blogjava.net/zilong/archive/2008/04/10/191865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate实现上传下载(三)</title><link>http://www.blogjava.net/zilong/archive/2008/04/10/191864.html</link><dc:creator>阿伟</dc:creator><author>阿伟</author><pubDate>Thu, 10 Apr 2008 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/zilong/archive/2008/04/10/191864.html</guid><wfw:comment>http://www.blogjava.net/zilong/comments/191864.html</wfw:comment><comments>http://www.blogjava.net/zilong/archive/2008/04/10/191864.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zilong/comments/commentRss/191864.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zilong/services/trackbacks/191864.html</trackback:ping><description><![CDATA[<h3><a href="http://lihaiyan.javaeye.com/blog/127796"><span style="font-size: 10pt">Struts+Spring+Hibernate实现上传下载(三)</span></a></h3>
<span style="font-size: 10pt">转自：http://lihaiyan.javaeye.com/blog/127796<br />
</span>
<p><span class="span"><span style="font-size: 10pt"><strong>业务层<br />
<br />
</strong>　　1、业务层接口<br />
<br />
　　"面向接口而非面向类编程"是Spring不遗余力所推荐的编程原则，这条原则也已经为大部开发者所接受；此外，JDK的动态代理只对接口有效，否则必须使用CGLIB生成目标类的子类。我们依从于Spring的倡导为业务类定义一个接口：<br />
<br />
　　代码 7 业务层操作接口<br />
<br />
</span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. public interface FileService<br />
            2. {<br />
            3. void save(FileActionForm fileForm);//将提交的上传文件保存到数据表中<br />
            4. List getAllFile();//得到T_FILE所示记录<br />
            5. void write(OutputStream os,String fileId);//将某个文件的文件数据写出到输出流中<br />
            6. String getFileName(String fileId);//获取文件名<br />
            7. }</span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　其中save(FileActionForm fileForm)方法，将封装在fileForm中的上传文件保存到数据库中，这里我们使用FileActionForm作为方法入参，FileActionForm是Web层的表单数据对象，它封装了提交表单的数据。将FileActionForm直接作为业务层的接口入参，相当于将Web层传播到业务层中去，即将业务层绑定在特定的Web层实现技术中，按照分层模型学院派的观点，这是一种反模块化的设计，但在"一般"的业务系统并无需提供多种UI界面，系统Web层将来切换到另一种实现技术的可能性也微乎其微，所以笔者觉得没有必要为了这个业务层完全独立于调用层的过高目标而去搞一个额外的隔离层，浪费了原材料不说，还将系统搞得过于复杂，相比于其它原则，"简单"始终是最大的一条原则。<br />
<br />
　　getAllFile()负责获取T_FILE表所有记录，以便在网页上显示出来。<br />
<br />
　　而getFileName(String fileId)和write(OutputStream os,String fileId)则用于下载某个特定的文件。具体的调用是将Web层将response.getOutputStream()传给write(OutputStream os,String fileId)接口，业务层直接将文件数据输出到这个响应流中。具体实现请参见错误！未找到引用源。节下载文件部分。<br />
<br />
　　2、业务层接口实现类<br />
<br />
　　FileService的实现类为FileServiceImpl，其中save(FileActionForm fileForm)的实现如下所示：<br />
<br />
　　代码 8 业务接口实现类之save()<br />
<br />
</span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. &#8230;<br />
            2. public class FileServiceImpl<br />
            3. implements FileService<br />
            4. {<br />
            5. private TfileDAO tfileDAO;<br />
            6. public void save(FileActionForm fileForm)<br />
            7. {<br />
            8. Tfile tfile = new Tfile();<br />
            9. try<br />
            10. {<br />
            11. tfile.setFileContent(fileForm.getFileContent().getFileData());<br />
            12. }<br />
            13. catch (FileNotFoundException ex)<br />
            14. {<br />
            15. throw new RuntimeException(ex);<br />
            16. }<br />
            17. catch (IOException ex)<br />
            18. {<br />
            19. throw new RuntimeException(ex);<br />
            20. }<br />
            21. tfile.setFileName(fileForm.getFileContent().getFileName());<br />
            22. tfile.setRemark(fileForm.getRemark());<br />
            23. tfileDAO.save(tfile);<br />
            24. }<br />
            25. &#8230;<br />
            26. }</span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　在save(FileActionForm fileForm)方法里，完成两个步骤：<br />
<br />
　　其一，象在水桶间倒水一样，将FileActionForm对象中的数据倒入到Tfile对象中；<br />
<br />
　　其二，调用TfileDAO保存数据。<br />
<br />
　　需要特别注意的是代码的第11行，FileActionForm的fileContent属性为org.apache.struts.upload.FormFile类型，FormFile提供了一个方便的方法getFileData()，即可获取文件的二进制数据。通过解读FormFile接口实现类DiskFile的原码，我们可能知道FormFile本身并不缓存文件的数据，只有实际调用getFileData()时，才从磁盘文件输入流中获取数据。由于FormFile使用流读取方式获取数据，本身没有缓存文件的所有数据，所以对于上传超大体积的文件，也是没有问题的；但是，由于数据持久层的Tfile使用byte[]来缓存文件的数据，所以并不适合处理超大体积的文件（如100M），对于超大体积的文件，依然需要使用java.sql.Blob类型以常规流操作的方式来处理。<br />
<br />
　　此外，通过FileForm的getFileName()方法就可以获得上传文件的文件名，如第21行代码所示。<br />
<br />
　　write(OutputStream os,String fileId)方法的实现，如代码 9所示：<br />
<br />
　　代码 9 业务接口实现类之write()<br />
<br />
</span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. &#8230;<br />
            2. public class FileServiceImpl<br />
            3. implements FileService<br />
            4. {<br />
            5.<br />
            6. public void write(OutputStream os, String fileId)<br />
            7. {<br />
            8. Tfile tfile = tfileDAO.findByFildId(fileId);<br />
            9. try<br />
            10. {<br />
            11. os.write(tfile.getFileContent());<br />
            12. os.flush();<br />
            13. }<br />
            14. catch (IOException ex)<br />
            15. {<br />
            16. throw new RuntimeException(ex);<br />
            17. }<br />
            18. }<br />
            19. &#8230;<br />
            20. }</span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　write(OutputStream os,String fileId)也简单地分为两个操作步骤，首先，根据fileId加载表记录，然后将fileContent写入到输出流中。<br />
<br />
　　3、Spring事务配置<br />
<br />
　　下面，我们来看如何在Spring配置文件中为FileService配置声明性的事务<br />
<br />
</span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 10pt">1. ＜beans＞<br />
            2. &#8230; <br />
            3. ＜bean id="transactionManager"<br />
            4. class="org.springframework.orm.hibernate3.HibernateTransactionManager"＞<br />
            5. ＜property name="sessionFactory" ref="sessionFactory"/＞<br />
            6. ＜/bean＞<br />
            7. ＜!-- 事务处理的AOP配置 //--＞<br />
            8. ＜bean id="txProxyTemplate" abstract="true"<br />
            9. class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"＞<br />
            10. ＜property name="transactionManager" ref="transactionManager"/＞<br />
            11. ＜property name="transactionAttributes"＞<br />
            12. ＜props＞<br />
            13. ＜prop key="get*"＞PROPAGATION_REQUIRED,readOnly＜/prop＞<br />
            14. ＜prop key="find*"＞PROPAGATION_REQUIRED,readOnly＜/prop＞<br />
            15. ＜prop key="save"＞PROPAGATION_REQUIRED＜/prop＞<br />
            16. ＜prop key="write"＞PROPAGATION_REQUIRED,readOnly＜/prop＞<br />
            17. ＜/props＞<br />
            18. ＜/property＞<br />
            19. ＜/bean＞<br />
            20. ＜bean id="fileService" parent="txProxyTemplate"＞<br />
            21. ＜property name="target"＞<br />
            22. ＜bean class="sshfile.service.FileServiceImpl"＞<br />
            23. ＜property name="tfileDAO" ref="tfileDAO"/＞<br />
            24. ＜/bean＞<br />
            25. ＜/property＞<br />
            26. ＜/bean＞<br />
            27. ＜/beans＞</span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　Spring的事务配置包括两个部分：<br />
<br />
　　其一，定义事务管理器transactionManager，使用HibernateTransactionManager实现事务管理；<br />
<br />
　　其二，对各个业务接口进行定义，其实txProxyTemplate和fileService是父子节点的关系，本来可以将txProxyTemplate定义的内容合并到fileService中一起定义，由于我们的系统仅有一个业务接口需要定义，所以将其定义的一部分抽象到父节点txProxyTemplate中意义确实不大，但是对于真实的系统，往往拥有为数众多的业务接口需要定义，将这些业务接口定义内容的共同部分抽取到一个父节点中，然后在子节点中通过parent进行关联，就可以大大简化业务接口的配置了。<br />
<br />
　　父节点txProxyTemplate注入了事务管理器，此外还定义了业务接口事务管理的方法（允许通过通配符的方式进行匹配声明，如前两个接口方法），有些接口方法仅对数据进行读操作，而另一些接口方法需要涉及到数据的更改。对于前者，可以通过readOnly标识出来，这样有利于操作性能的提高，需要注意的是由于父类节点定义的Bean仅是子节点配置信息的抽象，并不能具体实现化一个Bean对象，所以需要特别标注为abstract="true"，如第8行所示。<br />
<br />
　　fileService作为一个目标类被注入到事务代理器中，而fileService实现类所需要的tfileDAO实例，通过引用3.2节中定义的tfileDAO Bean注入。</span></span></p>
<br />
<img src ="http://www.blogjava.net/zilong/aggbug/191864.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zilong/" target="_blank">阿伟</a> 2008-04-10 15:01 <a href="http://www.blogjava.net/zilong/archive/2008/04/10/191864.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate实现上传下载(二)</title><link>http://www.blogjava.net/zilong/archive/2008/04/10/191863.html</link><dc:creator>阿伟</dc:creator><author>阿伟</author><pubDate>Thu, 10 Apr 2008 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/zilong/archive/2008/04/10/191863.html</guid><wfw:comment>http://www.blogjava.net/zilong/comments/191863.html</wfw:comment><comments>http://www.blogjava.net/zilong/archive/2008/04/10/191863.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zilong/comments/commentRss/191863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zilong/services/trackbacks/191863.html</trackback:ping><description><![CDATA[<h3><a href="http://lihaiyan.javaeye.com/blog/127795"><span style="font-size: 12pt"><span style="font-size: 10pt">Struts+Spring+Hibernate实现上传下载(二)</span></span></a></h3>
<span style="font-size: 12pt"><span style="font-size: 10pt">转自：http://lihaiyan.javaeye.com/blog/127795<br />
</span></span>
<p><span class="span"><span style="font-size: 12pt"><span style="font-size: 10pt"><strong style="font-size: 10pt">数据持久层<br />
<br />
</strong>　　1、领域对象及映射文件<br />
<br />
　　您可以使用Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer等工具或手工的方式，编写Hibernate的领域对象和映射文件。其中对应T_FILE表的领域对象Tfile.java为：<br />
<br />
　　代码 1 领域对象Tfile<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. package sshfile.model;<br />
            2. public class Tfile<br />
            3.{<br />
            4. private String fileId;<br />
            5. private String fileName;<br />
            6. private byte[] fileContent;<br />
            7. private String remark;<br />
            8. &#8230;//getter and setter<br />
            9. }</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　特别需要注意的是：数据库表为Blob类型的字段在Tfile中的fileContent类型为byte[]。Tfile的Hibernate映射文件Tfile.hbm.xml放在Tfile .java类文件的相同目录下：<br />
<br />
　　代码 2 领域对象映射文件<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. ＜?xml version="1.0"?＞<br />
            2. ＜!DOCTYPE hibernate-mapping PUBLIC<br />
            3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
            4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ＞<br />
            5. ＜hibernate-mapping＞<br />
            6. ＜class name="sshfile.model.Tfile" table="T_FILE"＞<br />
            7. ＜id name="fileId" type="java.lang.String" column="FILE_ID"＞<br />
            8. ＜generator class="uuid.hex"/＞<br />
            9. ＜/id＞<br />
            10. ＜property name="fileContent"<br />
            11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType"<br />
            12. column="FILE_CONTENT" lazy="true"/＞<br />
            13. &#8230;//其它一般字段的映射<br />
            14. ＜/class＞<br />
            15. ＜/hibernate-mapping＞</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　fileContent字段映射为Spring所提供的BlobByteArrayType类型，BlobByteArrayType是用户自定义的数据类型，它实现了Hibernate 的org.hibernate.usertype.UserType接口。BlobByteArrayType使用从sessionFactory获取的Lob操作句柄lobHandler将byte[]的数据保存到Blob数据库字段中。这样，我们就再没有必要通过硬编码的方式，先insert然后再update来完成Blob类型数据的持久化，这个原来难伺候的老爷终于被平民化了。关于lobHandler的配置请见本文后面的内容。<br />
<br />
　　此外lazy="true"说明地返回整个Tfile对象时，并不返回fileContent这个字段的数据，只有在显式调用tfile.getFileContent()方法时才真正从数据库中获取fileContent的数据。这是Hibernate3引入的新特性，对于包含重量级大数据的表字段，这种抽取方式提高了对大字段操作的灵活性，否则加载Tfile对象的结果集时如果总是返回fileContent，这种批量的数据抽取将可以引起数据库的"洪泛效应"。<br />
<br />
　　2、DAO编写和配置<br />
<br />
　　Spring强调面向接口编程，所以我们将所有对Tfile的数据操作的方法定义在TfileDAO接口中，这些接口方法分别是：<br />
<br />
　　&#183;findByFildId(String fileId)<br />
<br />
　　&#183;save(Tfile tfile)<br />
<br />
　　&#183;List findAll()<br />
<br />
　　TfileDAOHibernate提供了对TfileDAO接口基于Hibernate的实现，如代码 3所示：<br />
<br />
　　代码 3 基于Hibernate 的fileDAO实现类<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. package sshfile.dao;<br />
            2.<br />
            3. import sshfile.model.*;<br />
            4. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;<br />
            5. import java.util.List;<br />
            6.<br />
            7. public class TfileDAOHibernate<br />
            8. extends HibernateDaoSupport implements TfileDAO<br />
            9. {<br />
            10. public Tfile findByFildId(String fileId)<br />
            11. {<br />
            12. return (Tfile) getHibernateTemplate().get(Tfile.class, fileId);<br />
            13. }<br />
            14. public void save(Tfile tfile)<br />
            15. {<br />
            16. getHibernateTemplate().save(tfile);<br />
            17. getHibernateTemplate().flush();<br />
            18. }<br />
            19. public List findAll()<br />
            20. {<br />
            21. return getHibernateTemplate().loadAll(Tfile.class);<br />
            22. }<br />
            23. }</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　TfileDAOHibernate通过扩展Spring提供的Hibernate支持类HibernateDaoSupport而建立，HibernateDaoSupport封装了HibernateTemplate，而HibernateTemplate封装了Hibernate所提供几乎所有的的数据操作方法，如execute(HibernateCallback action)，load(Class entityClass, Serializable id)，save(final Object entity)等等。<br />
<br />
　　所以我们的DAO只需要简单地调用父类的HibernateTemplate就可以完成几乎所有的数据库操作了。<br />
<br />
　　由于Spring通过代理Hibernate完成数据层的操作，所以原Hibernate的配置文件hibernate.cfg.xml的信息也转移到Spring的配置文件中：<br />
<br />
　　代码 4 Spring中有关Hibernate的配置信息<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. ＜beans＞<br />
            2. ＜!-- 数据源的配置 //--＞<br />
            3. ＜bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"<br />
            4. destroy-method="close"＞<br />
            5. ＜property name="driverClassName" value="http://www.zhmy.com/oracle.jdbc.driver.OracleDriver"/＞<br />
            6. ＜property name="url" value="jdbc:oracle:thin:@localhost:1521:ora9i"/＞<br />
            7. ＜property name="username" value="test"/＞<br />
            8. ＜property name="password" value="test"/＞<br />
            9. ＜/bean＞<br />
            10. ＜!-- Hibernate会话工厂配置 //--＞<br />
            11. ＜bean id="sessionFactory"<br />
            12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"＞<br />
            13. ＜property name="dataSource" ref="dataSource"/＞<br />
            14. ＜property name="mappingDirectoryLocations"＞<br />
            15. ＜list＞<br />
            16. ＜value＞classpath:/sshfile/model＜/value＞<br />
            17. ＜/list＞<br />
            18. ＜/property＞<br />
            19. ＜property name="hibernateProperties"＞<br />
            20. ＜props＞<br />
            21. ＜prop key="hibernate.dialect"＞org.hibernate.dialect.OracleDialect＜/prop＞<br />
            22. ＜prop key="hibernate.cglib.use_reflection_optimizer"＞true＜/prop＞<br />
            23. ＜/props＞<br />
            24. ＜/property＞<br />
            25. ＜/bean＞<br />
            26. ＜!-- Hibernate 模板//--＞<br />
            27. ＜bean id="hibernateTemplate"<br />
            28. class="org.springframework.orm.hibernate3.HibernateTemplate"＞<br />
            29. ＜property name="sessionFactory" ref="sessionFactory"/＞<br />
            30. ＜/bean＞<br />
            31. ＜!--DAO配置 //--＞<br />
            32. ＜bean id="tfileDAO" class="sshfile.dao.TfileDAOHibernate"＞<br />
            33. ＜property name="hibernateTemplate" ref="hibernateTemplate" /＞<br />
            34. ＜/bean＞<br />
            35. &#8230;<br />
            36. ＜/beans＞</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　第3~9行定义了一个数据源，其实现类是apache的BasicDataSource，第11~25行定义了Hibernate的会话工厂，会话工厂类用Spring提供的LocalSessionFactoryBean维护，它注入了数据源和资源映射文件，此外还通过一些键值对设置了Hibernate所需的属性。<br />
<br />
　　其中第16行通过类路径的映射方式，将sshfile.model类包目录下的所有领域对象的映射文件装载进来，在本文的例子里，它将装载进Tfile.hbm.xml映射文件。如果有多个映射文件需要声明，使用类路径映射方式显然比直接单独指定映射文件名的方式要简便。 <br />
<br />
　　第27~30行定义了Spring代理Hibernate数据操作的HibernateTemplate模板，而第32~34行将该模板注入到tfileDAO中。<br />
<br />
　　需要指定的是Spring 1.2.5提供了两套Hibernate的支持包，其中Hibernate 2相关的封装类位于org.springframework.orm.hibernate2.*包中，而Hibernate 3.0的封装类位于org.springframework.orm.hibernate3.*包中，需要根据您所选用Hibernate版本进行正确选择。<br />
<br />
　　3、Lob字段处理的配置<br />
<br />
　　我们前面已经指出Oracle的Lob字段和一般类型的字段在操作上有一个明显的区别--那就是你必须首先通过Oracle的empty_blob()/empty_clob()初始化Lob字段，然后获取该字段的引用，通过这个引用更改其值。所以要完成对Lob字段的操作，Hibernate必须执行两步数据库访问操作，先Insert再Update。<br />
<br />
　　使用BlobByteArrayType字段类型后，为什么我们就可以象一般的字段类型一样操作Blob字段呢？可以确定的一点是：BlobByteArrayType不可能逾越Blob天生的操作方式，原来是BlobByteArrayType数据类型本身具体数据访问的功能，它通过LobHandler将两次数据访问的动作隐藏起来，使Blob字段的操作在表现上和其他一般字段业类型无异，所以LobHandler即是那个"苦了我一个，幸福十亿人"的那位幕后英雄。<br />
<br />
　　LobHandler必须注入到Hibernate会话工厂sessionFactory中，因为sessionFactory负责产生与数据库交互的Session。LobHandler的配置如代码 5所示：<br />
<br />
　　代码 5 Lob字段的处理句柄配置<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. ＜beans＞<br />
            2. &#8230;<br />
            3. ＜bean id="nativeJdbcExtractor"<br />
            4. class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"<br />
            5. lazy-init="true"/＞<br />
            6. ＜bean id="lobHandler"<br />
            7. class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true"＞<br />
            8. ＜property name="nativeJdbcExtractor"＞<br />
            9. ＜ref local="nativeJdbcExtractor"/＞<br />
            10. ＜/property＞<br />
            11. ＜/bean＞<br />
            12. &#8230;<br />
            13. ＜/beans＞</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　首先，必须定义一个能够从连接池中抽取出本地数据库JDBC对象（如OracleConnection，OracleResultSet等）的抽取器：nativeJdbcExtractor，这样才可以执行一些特定数据库的操作。对于那些仅封装了Connection而未包括Statement的简单数据连接池，SimpleNativeJdbcExtractor是效率最高的抽取器实现类，但具体到apache的BasicDataSource连接池，它封装了所有JDBC的对象，这时就需要使用CommonsDbcpNativeJdbcExtractor了。Spring针对几个著名的Web服务器的数据源提供了相应的JDBC抽取器：<br />
<br />
　　&#183;WebLogic：WebLogicNativeJdbcExtractor<br />
<br />
　　&#183;WebSphere：WebSphereNativeJdbcExtractor<br />
<br />
　　&#183;JBoss：JBossNativeJdbcExtractor<br />
<br />
　　在定义了JDBC抽取器后，再定义lobHandler。Spring 1.2.5提供了两个lobHandler：<br />
<br />
　　&#183;DefaultLobHandler：适用于大部分的数据库，如SqlServer，MySQL，对Oracle 10g也适用，但不适用于Oracle 9i（看来Oracle 9i确实是个怪胎，谁叫Oracle 公司自己都说Oracle 9i是一个过渡性的产品呢）。<br />
<br />
　　&#183;OracleLobHandler：适用于Oracle 9i和Oracle 10g。<br />
<br />
　　由于我们的数据库是Oracle9i，所以使用OracleLobHandler。<br />
<br />
　　在配置完LobHandler后， 还需要将其注入到sessionFactory的Bean中，下面是调用后的sessionFactory Bean的配置：<br />
<br />
　　代码 6 将lobHandler注入到sessionFactory中的配置<br />
<br />
</span></span>
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: 12pt"><span style="font-size: 10pt">1. ＜beans＞<br />
            2. &#8230;<br />
            3. ＜bean id="sessionFactory"<br />
            4. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"＞<br />
            5. ＜property name="dataSource" ref="dataSource"/＞<br />
            6. ＜!-- 为处理Blob类型字段的句柄声明 //--＞<br />
            7. ＜property name="lobHandler" ref="lobHandler"/＞<br />
            8. &#8230;<br />
            9. ＜/bean＞<br />
            10. &#8230;<br />
            11. ＜/beans＞</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt">　　如第7所示，通过sessionFactory的lobHandler属性进行注入。</span></span></span></p>
<br />
<img src ="http://www.blogjava.net/zilong/aggbug/191863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zilong/" target="_blank">阿伟</a> 2008-04-10 14:55 <a href="http://www.blogjava.net/zilong/archive/2008/04/10/191863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate实现上传下载(一)</title><link>http://www.blogjava.net/zilong/archive/2008/04/10/191862.html</link><dc:creator>阿伟</dc:creator><author>阿伟</author><pubDate>Thu, 10 Apr 2008 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/zilong/archive/2008/04/10/191862.html</guid><wfw:comment>http://www.blogjava.net/zilong/comments/191862.html</wfw:comment><comments>http://www.blogjava.net/zilong/archive/2008/04/10/191862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zilong/comments/commentRss/191862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zilong/services/trackbacks/191862.html</trackback:ping><description><![CDATA[<a href="http://lihaiyan.javaeye.com/blog/127794"><span style="font-size: 10pt">转自：http://lihaiyan.javaeye.com/blog/127794</span></a><br />
<span style="font-size: 10pt"><strong>引言</strong><br />
<br />
　　文件的上传和下载在</span><a class="bluekey" href="http://www.yesky.com/key/3547/3547.html" target="_blank"><span style="font-size: 10pt">J2EE</span></a><span style="font-size: 10pt">编程已经是一个非常古老的话题了，也许您马上就能掰着指头数出好几个著名的大件：如SmartUpload、</span><a class="bluekey" href="http://www.yesky.com/key/927/5927.html" target="_blank"><span style="font-size: 10pt">Apache</span></a><span style="font-size: 10pt">的FileUpload。但如果您的项目是构建在Struts+Spring+</span><a class="bluekey" href="http://www.yesky.com/key/845/5845.html" target="_blank"><span style="font-size: 10pt">Hibernate</span></a><span style="font-size: 10pt">（以下称SSH）框架上的，这些大件就显得笨重而沧桑了，SSH提供了一个简捷方便的文件上传下载的方案，我们只需要通过一些配置并辅以少量的代码就可以完好解决这个问题了。<br />
<br />
　　本文将围绕SSH文件上传下载的主题，向您详细讲述如何开发基于SSH的Web程序。SSH各框架的均为当前最新版本：<br />
<br />
　　&#183;Struts 1.2<br />
<br />
　　&#183;Spring 1.2.5<br />
<br />
　　&#183;Hibernate 3.0<br />
<br />
　　本文选用的数据库为</span><a class="bluekey" href="http://www.yesky.com/key/777/5777.html" target="_blank"><span style="font-size: 10pt">Oracle</span></a><span style="font-size: 10pt"> 9i，当然你可以在不改动代码的情况下，通过配置文件的调整将其移植到任何具有Blob字段类型的数据库上，如</span><a class="bluekey" href="http://www.yesky.com/key/1784/6784.html" target="_blank"><span style="font-size: 10pt">MySQL</span></a><span style="font-size: 10pt">，SQLServer等。<br />
<br />
　　<strong>总体实现</strong><br />
<br />
　　上传文件保存到T_FILE表中，T_FILE表结构如下：<br />
<br />
</span>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://soft.yesky.com/imagelist/05/12/661b4k5512t8.gif" onload="rsimg(this,420)" _counted="undefined" />420){this.resized=true;this.style.width=420;}" border=0&gt;<br />
            图 1 T_FILE表结构</span></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　其中：<br />
<br />
　　&#183;FILE_ID：文件ID，32个字符，用Hibernate的uuid.hex算法生成。<br />
<br />
　　&#183;FILE_NAME：文件名。<br />
<br />
　　&#183;FILE_CONTENT：文件内容，对应Oracle的Blob类型。<br />
<br />
　　&#183;REMARK：文件备注。<br />
<br />
　　文件数据存储在Blob类型的FILE_CONTENT表字段上，在Spring中采用OracleLobHandler来处理Lob字段（包括Clob和Blob），由于在程序中不需要引用到oracle数据驱动程序的具体类且屏蔽了不同数据库处理Lob字段方法上的差别，从而撤除程序在多数据库移植上的樊篱。 <br />
<br />
　　1．首先数据表中的Blob字段在Java领域对象中声明为byte[]类型，而非java.sql.Blob类型。<br />
<br />
　　2．数据表Blob字段在Hibernate持久化映射文件中的type为org.springframework.orm.hibernate3.support.BlobByteArrayType，即Spring所提供的用户自定义的类型，而非java.sql.Blob。 <br />
<br />
　　3．在Spring中使用org.springframework.jdbc.support.lob.OracleLobHandler处理Oracle数据库的Blob类型字段。<br />
<br />
　　通过这样的设置和配置，我们就可以象持久化表的一般字段类型一样处理Blob字段了。<br />
<br />
　　以上是Spring＋Hibernate将文件二进制数据持久化到数据库的解决方案，而Struts通过将表单中file类型的组件映射为ActionForm中类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。<br />
<br />
　　综上所述，我们可以通过图 2，描绘出SSH处理文件上传的方案：<br />
<br />
</span>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://soft.yesky.com/imagelist/05/12/9g24f0968d37.jpg" onload="rsimg(this,420)" _counted="undefined" />420){this.resized=true;this.style.width=420;}" border=0&gt;<br />
            图 2 SSH处理文件上传技术方案</span></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　文件上传的页面如图 3所示：<br />
<br />
</span>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" height="165" alt="" src="http://soft.yesky.com/imagelist/05/12/8984n19kf77o.jpg" width="420" onload="rsimg(this,420)" _counted="undefined" resized="true" />420){this.resized=true;this.style.width=420;}" border=0 resized="true"&gt;<br />
            图 3 文件上传页面</span></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　文件下载的页面如图 4所示：<br />
<br />
</span>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" height="248" alt="" src="http://soft.yesky.com/imagelist/05/12/v9hx8m4556my.jpg" width="420" onload="rsimg(this,420)" _counted="undefined" resized="true" />420){this.resized=true;this.style.width=420;}" border=0 resized="true"&gt;<br />
            图 4 文件下载页面</span></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　该工程的资源结构如图 5所示：<br />
<br />
</span>
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><span style="font-size: 10pt"><img style="cursor: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://soft.yesky.com/imagelist/05/12/s652irpixa30.gif" onload="rsimg(this,420)" _counted="undefined" />420){this.resized=true;this.style.width=420;}" border=0&gt;<br />
            图 5 工程资源结构</span></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span style="font-size: 10pt">　　工程的类按SSH的层次结构划分为数据持久层、业务层和Web层；WEB-INF下的applicationContext.xml为Spring的配置文件，struts-config.xml为Struts的配置文件，file-upload.jsp为文件上传页面，file-list.jsp为文件列表页面。<br />
<br />
　　本文后面的章节将从数据持久层-＞业务层-＞Web层的开发顺序，逐层讲解文件上传下载的开发过程。<br />
</span>
<img src ="http://www.blogjava.net/zilong/aggbug/191862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zilong/" target="_blank">阿伟</a> 2008-04-10 14:48 <a href="http://www.blogjava.net/zilong/archive/2008/04/10/191862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>