﻿<?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-　　　　　　　　　　　　　彬 ^_^ -文章分类-SSH</title><link>http://www.blogjava.net/libin2722/category/27232.html</link><description>LuckyStar</description><language>zh-cn</language><lastBuildDate>Fri, 09 Nov 2007 15:15:32 GMT</lastBuildDate><pubDate>Fri, 09 Nov 2007 15:15:32 GMT</pubDate><ttl>60</ttl><item><title>Struts+Spring+Hibernate的完美融合</title><link>http://www.blogjava.net/libin2722/articles/159468.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Fri, 09 Nov 2007 14:36:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/159468.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/159468.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/159468.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/159468.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/159468.html</trackback:ping><description><![CDATA[Struts+Spring+Hibernate的完美融合
<p align="left">&nbsp;</p>
<p align="center"><strong><font size="5">第一篇 struts与spring的融合</font></strong></p>
<p align="center"><strong><font size="5"></font></strong></p>
<p><strong><font size="4">第一步：配置环境与技术支持</font></strong></p>
<p><strong><font size="2">1、环境：tomcat5.0 + eclipse3.2.2 + myEclipse5.5 + jdk1.5</font></strong></p>
<p><strong><font size="2">2、技术：struts1.1+spring2.0</font></strong></p>
<p><font size="2"><strong>分析</strong>：经过多次实验，（初建struts+spring）项目中出现的问题和工具及技术版本没有根本关系，只要在（其他项目运行）已经配置成功的环境下运行就好。这里要注意的是：myEclipse5.0以下的版本不支持spring2.0。小小提示：本人初次在该环境下操作时，多次不成功，最后从新安装配置环境后，struts+spring项目才正常运行，疑与myEclipse有关。</font></p>
<p><strong><font size="4">第二步：新建工程SSHProject</font></strong></p>
<p><strong><font size="2">1、新建工程</font></strong></p>
<p><strong></strong></p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/001.gif" /></p>
<p><font size="2">分析：不同版本的eclipse新建项目对话框不同，3.2.2以下版本没有java EE 5.0。这里我们选择J2EE1.4！</font></p>
<p><strong><font size="2">2、导入struts包</font></strong></p>
<p>&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/002.gif" /></p>
<p><strong><font size="2">3、导入spring包</font></strong></p>
<p><img alt="导入spring 包" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/003.gif" /></p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/004.gif" /></p>
<p><font size="2"><strong>分析：</strong>这里我们使用的是spring2.0，如果你的版本不支持2.0，就使用spring1.2版本。spring1.2与struts1.1同样兼容，但spring1.2只支持hibernate3.0以下的版本。如果你选择spring1.2，就不得不使用hibernate3.0或者2.1。小小提示：对于初学者来说，最好把所有的spring包导入项目。提醒：applicationContext.xml我们放在src下，但我们要知道编译部署后，默认在classes文件夹，所以我们在以后的配置中，一定要注意路径问题。</font></p>
<p><strong><font size="2">3、新建com.ssh.beans.po和com.ssh.beans.dao两个包已做备用。</font></strong></p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/005.gif" /></p>
<p><font size="2">好了，工程框架已经搭好，现在我们就可以往里面放东西了。</font></p>
<p><font size="2"></font></p>
<p><font size="2"></font></p>
<p><font size="2"></font></p>
<p><strong><font size="4">第三步 创建action和bean</font></strong></p>
<p><strong><font size="2">1、在com.ssh.beans.po中创建Customer.java。内容如下：</font></strong></p>
<p align="left">package com.ssh.beans.po;</p>
<p align="left">public class Customer {<br />
&nbsp;<br />
&nbsp;String custId;<br />
&nbsp;String custName;<br />
&nbsp;<br />
&nbsp;public Customer(){<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public Customer(String custId,String custName){<br />
&nbsp;&nbsp;this.custId=custId;<br />
&nbsp;&nbsp;this.custName=custName;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setCustId(String custId){<br />
&nbsp;&nbsp;this.custId=custId;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public String getCustId(){<br />
&nbsp;&nbsp;return this.custId;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setCustName(String custName){<br />
&nbsp;&nbsp;this.custName=custName;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public String getCustName(){<br />
&nbsp;&nbsp;return this.custName;<br />
&nbsp;}<br />
}</p>
<p align="left"><strong><font size="2">2、在com.ssh.beans.dao中创建CustomerDAO.java及其接口ICustomerDAO.java。内容如下：</font></strong></p>
<p align="left">package com.ssh.beans.dao;</p>
<p align="left">import java.util.ArrayList;<br />
import java.util.List;</p>
<p align="left">import com.ssh.beans.po.Customer;</p>
<p align="left">public class CustomerDAO implements ICustomerDAO {<br />
public List getALLCustomer(){<br />
&nbsp;List list=new ArrayList();<br />
&nbsp;Customer c1=new Customer("1","zhang");<br />
&nbsp;Customer c2=new Customer("2","xiaoling");<br />
&nbsp;list.add(c1);<br />
&nbsp;list.add(c2);<br />
&nbsp;return list;<br />
}<br />
}<br />
</p>
<p align="left">&nbsp;</p>
<p align="left">package com.ssh.beans.dao;</p>
<p align="left">import java.util.List;</p>
<p align="left">public interface ICustomerDAO {<br />
&nbsp;public List getALLCustomer();<br />
}<br />
</p>
<p align="left"><strong><font size="2"></font></strong></p>
<p align="left"><strong><font size="2"></font></strong></p>
<p><strong><font size="2">&nbsp;3、创建CustomerAction.java</font></strong></p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/006.gif" /><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/007.gif" /></p>
<p><strong><font size="4"></font></strong></p>
<p><font size="2"><strong>分析</strong>：这里action的创建与我们以前创建action一样，但我们要注意的是，你导入什么版本的struts就要生成什么版本的action，这里是struts1.1。</font></p>
<p><font size="2">接下来我们看看struts-config.xml里面的内容：</font></p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd</a>"&gt;</p>
<p>&lt;struts-config&gt;<br />
&nbsp; &lt;data-sources /&gt;<br />
&nbsp; &lt;form-beans /&gt;<br />
&nbsp; &lt;global-exceptions /&gt;<br />
&nbsp; &lt;global-forwards /&gt;</p>
<p><br />
&nbsp; &lt;action-mappings &gt;<br />
&nbsp;&nbsp;&nbsp; &lt;action path="/customer" type="com.ssh.struts.action.CustomerAction"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="success" path="/index.jsp" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/action&gt;</p>
<p>&lt;/action-mappings&gt;</p>
<p>&nbsp; &lt;message-resources parameter="com.ssh.struts.ApplicationResources" /&gt;<br />
&lt;/struts-config&gt;</p>
<p>没错，内容和我们以前的东东一样。</p>
<p>我们再给CustomerAction.java一些内容：</p>
<p>package com.ssh.struts.action;</p>
<p>import java.util.ArrayList;<br />
import java.util.List;</p>
<p>import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.apache.struts.action.Action;<br />
import org.apache.struts.action.ActionForm;<br />
import org.apache.struts.action.ActionForward;<br />
import org.apache.struts.action.ActionMapping;</p>
<p>import com.ssh.beans.dao.CustomerDAO;<br />
import com.ssh.beans.dao.ICustomerDAO;<br />
import com.ssh.beans.po.Customer;</p>
<p>public class CustomerAction extends Action {<br />
&nbsp;<br />
&nbsp;ICustomerDAO customerDAO=null;<br />
&nbsp;public void setCustomerDAO(ICustomerDAO customerDAO){<br />
&nbsp;&nbsp;this.customerDAO=customerDAO;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public ActionForward execute(ActionMapping mapping, ActionForm form,<br />
&nbsp;&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response) {<br />
&nbsp;&nbsp;List list=new ArrayList();<br />
&nbsp;&nbsp;Customer customer=null;<br />
&nbsp;&nbsp;<strong>setCustomerDAO(new CustomerDAO());</strong><br />
&nbsp;&nbsp;if(customerDAO!=null){<br />
&nbsp;&nbsp;&nbsp;list=customerDAO.getALLCustomer();<br />
&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;list.size();i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;customer=(Customer)list.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("OK:"+customer.getCustName());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;System.out.println("ERROR or NULL");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return mapping.findForward("success");<br />
&nbsp;}<br />
}</p>
<p>&nbsp;</p>
<p>好的，我们现在测试一下！如果访问<a href="http://localhost:8080/SSHProject/customer.do">http://localhost:8080/SSHProject/customer.do</a>能顺利进入index.jsp页面，并输出用户custName值，说明以上我们的工作是正确的！</p>
<p><font size="4"><strong>第四步 配置stuts-config.xml和applicationContext.xml文件</strong></font></p>
<p>看到这里，大家可能会认为，这和以前的web工程的创建没有什么两样，和struts与spring融合没有什么关系，不用着急，奥妙就在sturts-config.xml与applicationContext.xml文件配置中。</p>
<p><strong>1、配置stuts-config.xml文件</strong></p>
<p>在这里，我们要做两个工作：第一，将CustomerAction替换成DelegatingActionProxy代理。第二，添加代理插件ContextLoaderPlugIn。修改后的内容如下：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd</a>"&gt;</p>
<p>&lt;struts-config&gt;<br />
&nbsp; &lt;data-sources /&gt;<br />
&nbsp; &lt;form-beans /&gt;<br />
&nbsp; &lt;global-exceptions /&gt;<br />
&nbsp; &lt;global-forwards /&gt;<br />
&nbsp; <br />
&nbsp; &lt;action-mappings &gt;<br />
&nbsp;&nbsp;&nbsp; &lt;action path="/customer"&nbsp; <strong>type="org.springframework.web.struts.DelegatingActionProxy"&gt;</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="success" path="/index.jsp" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/action&gt;<br />
&nbsp; &lt;/action-mappings&gt;</p>
<p>&nbsp; &lt;message-resources parameter="com.ssh.struts.ApplicationResources" /&gt;<br />
&nbsp; <br />
&nbsp;<strong> &lt;plug-in 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/classes/applicationContext.xml"/&gt;<br />
&nbsp; &lt;/plug-in&gt;<br />
</strong>&nbsp;<br />
&lt;/struts-config&gt;</p>
<p>注：粗体字为修改的内容</p>
<p><strong>分析：</strong>你一定要做到：1、确保spring-struts.jar导入项目。2、保证applicationContext.xml文件路径正确。我们在导入spring包时就提到，applicationContext.xml文件放在src下，编译部署后，文件默认存放在WEB-INF/classes下。所以上面的配置为：<font color="#000000"><strong>value="/WEB-INF/classes/applicationContext.xml"/&gt;</strong>。</font></p>
<p><strong>2、配置applicationContext.xml</strong></p>
<p>在这个文件中，我们的任务是加入我们需要的bean。到目前为止，我们要加入两个bean，即：CustomerDAO与CustomerAction。修改后的内容为：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans<br />
<font color="#000000">&nbsp;xmlns="</font><a href="http://www.springframework.org/schema/beans"><font color="#000000">http://www.springframework.org/schema/beans</font></a><font color="#000000">"<br />
&nbsp;xmlns:xsi="</font><a href="http://www.w3.org/2001/XMLSchema-instance"><font color="#000000">http://www.w3.org/2001/XMLSchema-instance</font></a><font color="#000000">"<br />
&nbsp;xsi:schemaLocation="</font><a href="http://www.springframework.org/schema/beans"><font color="#000000">http://www.springframework.org/schema/beans</font></a><font color="#000000"> </font><a href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"><font color="#000000">http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</font></a><font color="#000000">"&gt;</font><br />
&nbsp;<br />
<strong>&nbsp;&lt;bean name="/customer" class="com.ssh.struts.action.CustomerAction" &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="customerDAO"&gt;&lt;ref bean="customerDAO"/&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&lt;bean name="customerDAO" class="com.ssh.beans.dao.CustomerDAO" /&gt;</strong></p>
<p>&lt;/beans&gt;</p>
<p>注：粗体字为添加的内容</p>
<p><strong>分析：</strong>在这个文件中你要确保：第一，CustomerAction bean中&lt;bean&gt;标签的属性name值(name="/customer")一定与struts-config.xml中属性path的值(path="/customer")一致。第二、&lt;property&gt;标签的属性name值在CustomerAction中一定有对应的属性。第三、&lt;ref&gt;标签的属性bean值一定与CustomerDAO bean的&lt;bean&gt;标签的属性name值一致(注：这就是注入目标对象)。第四、CustomerDAO bean中&lt;bean&gt;标签的属性class值一定是一个实现类(不能为接口)。</p>
<p><strong></strong></p>
<p><strong>3、修改CustomerAction.java</strong></p>
<p>这一步很简单，只要把<strong>setCustomerDAO(new CustomerDAO());</strong>这条语句去掉就好。因为我们已经在applicationContext.xml给customerDAO进行了setter注入。(呵呵，至于什么是setter注入，不了解的朋友先看看spring的IOC)。</p>
<p>好的，到现在为止，我们已经对struts和spring进行了融合。再来测试一下，如果输入同样的内容，就OK！</p>
<p>如果以上操作大家都没有问题，我们就向下看。来吧，一起融合spring与hibernate</p>
<p>&nbsp;</p>
<p align="center"><font size="5"><strong>第二篇 Spring与Hibernate的融合</strong></font><br />
</p>
<p align="left">有的朋友可能只希望知道spring与hibernate的融合。所以在讲struts+spring+hibernate之前，我们跳过使用stuts，先说一下spring+hibernate的融合。如果仍然用SSHProject这个项目，需要把po和dao包下面的类删除，因为我们在生成影射文件和DAO时可能会出现重名文件。还有applicationContext.xml中的bean同样删除。</p>
<p align="left"><strong><font size="4">第一步 配置数据环境</font></strong></p>
<p align="left"><font size="2">既然我们用到hibernate，就要给他配置数据库，这里我们使用的是mysql5.0。eclipse3.2.2一下的版本与3.2.2版本数据库的配置是不同的，这里我们只讲3.2.2的配置。</font></p>
<p align="left"><font size="2"><strong>1、打开DB Brower</strong></font></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/011.gif" /></p>
<p align="left"><font size="2">2、新建数据库连接</font></p>
<p align="left"><font size="2">在DB Brower中右键&gt;新建打开下面对话框，选择输入正确的配置。提示：注意你的数据库名、密码、和驱动器。</font></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/012.gif" /></p>
<p align="left">单击&#8220;完成&#8221;，测试如果连接到数据库，就OK。</p>
<p align="left"><font size="4"><strong>第二步 选择hibernate与包的导入</strong></font></p>
<p align="left"><font size="2"><strong>1、hibernate的选择</strong></font></p>
<p align="left"><font size="2">上面我们已经提到，spring1.2只支持hibernate3.0以下的版本，所以如果你选择的是spring1.2一定要注意这个问题。这里我使用的是hibernate3.1</font></p>
<p align="left"><font size="2"><strong>2、包的导入</strong></font></p>
<p align="left">&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/008.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/009.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/015.gif" /></p>
<p align="left">&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/013.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/014.gif" /></p>
<p align="left">单击&#8220;完成&#8221;OK。</p>
<p align="left"><strong>分析：</strong>在导入包时出现几个问题：1、在找spring建好的applicationContext.xml文件时没有找到路径，被迫把其他项目的数据库连接bean考到该文件内((注：仅仅是我存在的问题)。2、把自动生成的sessionFactory删除。3、最后可能会出现找不到包，所以你要手动添加几个包。</p>
<p align="left">现在我们看看applicationContext.xml文件内容有什么变化，内容如下：</p>
<p align="left">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans<br />
<font color="#000000">&nbsp;xmlns="</font><a href="http://www.springframework.org/schema/beans"><font color="#000000">http://www.springframework.org/schema/beans</font></a><font color="#000000">"<br />
&nbsp;xmlns:xsi="</font><a href="http://www.w3.org/2001/XMLSchema-instance"><font color="#000000">http://www.w3.org/2001/XMLSchema-instance</font></a><font color="#000000">"<br />
&nbsp;xsi:schemaLocation="</font><a href="http://www.springframework.org/schema/beans"><font color="#000000">http://www.springframework.org/schema/beans</font></a><font color="#000000"> </font><a href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"><font color="#000000">http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</font></a><font color="#000000">"&gt;</font><br />
&nbsp;<br />
&nbsp;<strong>&lt;bean id="dataSource"<br />
&nbsp;&nbsp;class="org.apache.commons.dbcp.BasicDataSource"&gt;<br />
&nbsp;&nbsp;&lt;property name="driverClassName"<br />
&nbsp;&nbsp;&nbsp;value="com.mysql.jdbc.Driver"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="url"<br />
&nbsp;&nbsp;&nbsp;value="jdbc:mysql://localhost:3306/pullhand"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="username" value="root"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="password" value="815241"&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;&lt;bean id="sessionFactory"<br />
&nbsp;&nbsp;class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="dataSource" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="hibernateProperties"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.dialect"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.hibernate.dialect.MySQLDialect<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</strong></p>
<p align="left">&lt;/beans&gt;</p>
<p align="left">注：粗体字为自动加入的内容。</p>
<p align="left"><strong><font size="4">第三步 创建影射文件po及dao</font></strong></p>
<p align="left"><strong><font size="2">1、创建影射文件</font></strong></p>
<p align="left"><font size="2">首先你要确定所需要的包都导入classpath路径中，否则在创建影射文件中会出现一些不能操作的对象。如果出现问题，建议大家多重复做几次。</font></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/016.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/017.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/018.gif" /></p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/0019.gif" /></p>
<p align="left">单击"完成"，就OK。</p>
<p align="left">在包资源管理器中我们可以看到，自动生成四个文件，包括CustomerDAO。</p>
<p align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/zhjk_001/020.gif" /></p>
<p align="left">为了方便操作我们包CustomerDAO放在dao包下。如果你没有删除ICustomerDAO接口，那我们就使用它了(因为spring是面对接口的，所以我们的操作都应该经过接口)。</p>
<p align="left">接下来，我们再看看applicationContext.xml有什么变化。内容如下：</p>
<p align="left">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans<br />
&nbsp;xmlns="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>"<br />
&nbsp;xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"<br />
&nbsp;xsi:schemaLocation="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a> <a href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</a>"&gt;<br />
&nbsp;<br />
&nbsp;&lt;bean id="dataSource"<br />
&nbsp;&nbsp;class="org.apache.commons.dbcp.BasicDataSource"&gt;<br />
&nbsp;&nbsp;&lt;property name="driverClassName"<br />
&nbsp;&nbsp;&nbsp;value="com.mysql.jdbc.Driver"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="url"<br />
&nbsp;&nbsp;&nbsp;value="jdbc:mysql://localhost:3306/pullhand"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="username" value="root"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="password" value="815241"&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;&lt;bean id="sessionFactory"<br />
&nbsp;&nbsp;class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="dataSource" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="hibernateProperties"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.dialect"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.hibernate.dialect.MySQLDialect<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<strong>&nbsp;&nbsp;&lt;property name="mappingResources"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;com/ssh/beans/po/Customer.hbm.xml&lt;/value&gt;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
</strong>&nbsp;&nbsp;&lt;/bean&gt;<br />
&nbsp;&nbsp;<br />
<strong>&nbsp;&nbsp;&lt;bean id="CustomerDAO" class="com.ssh.beans.dao.CustomerDAO"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;property name="sessionFactory"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="sessionFactory" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt;</strong><br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&lt;/beans&gt;</p>
<p align="left">注：粗体字为新内容。提醒：如果你没有改CustomerDAO的路径，它应该在po包下。</p>
<p align="left"><strong>2、创建dao。</strong></p>
<p align="left">CustomerDAO.java我们使用hibernate自动生成，ICustomerDAO.java接口使用我们以前建好的。</p>
<p align="left"><strong>3、创建测试类</strong></p>
<p align="left">既然我们不使用action，那么我们就新建一个类Test.java用于测试。内容如下：</p>
<p align="left">package com.ssh.struts.action;</p>
<p align="left">import java.util.List;</p>
<p align="left">import org.springframework.context.ApplicationContext;<br />
import org.springframework.context.support.ClassPathXmlApplicationContext;</p>
<p align="left">import com.ssh.beans.dao.CustomerDAO;</p>
<p align="left">public class Test{<br />
&nbsp;<br />
&nbsp;private ApplicationContext context;<br />
&nbsp;</p>
<p align="left">&nbsp;<br />
&nbsp;private void test(){<br />
&nbsp;&nbsp;CustomerDAO customerDAO=(CustomerDAO)context.getBean("customerDAO");<br />
&nbsp;&nbsp;List list=customerDAO.findAll();<br />
&nbsp;&nbsp;if(list!=null&amp;&amp;list.size()&gt;0){<br />
&nbsp;&nbsp;&nbsp;System.out.println("list.size():"+list.size());<br />
&nbsp;&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;System.out.println("ERROR or NULL");<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;private void run(){<br />
&nbsp;&nbsp;context=new ClassPathXmlApplicationContext("applicationContext.xml");<br />
&nbsp;&nbsp;test();<br />
&nbsp;}<br />
&nbsp;public static void main(String[] args){<br />
&nbsp;&nbsp;new Test().run();<br />
&nbsp;}<br />
}<br />
</p>
<p align="left"><strong>分析：</strong>在测试中可能出现两个异常：</p>
<p align="left">异常一、java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool。如果出现这个异常说明缺少commons-pool-1.2.jar包。</p>
<p align="left">异常二、org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.mysql.jdbc.Driver';;;Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。如果出现这个异常，说明在构建路径中没有驱动包。</p>
<p align="left">好的，我们现在测试一下，如果System.out.println("list.size():"+list.size());执行，说明我们对spring与hibernate的融合成功了。</p>
<p align="left">&nbsp;</p>
<p align="center"><strong><font size="5">第三篇 整合struts+spring+hibernate</font></strong></p>
<p align="left"><font size="2">我们在上两篇的基础只要再对applicationContext.xml文件进行修改，就可以达到我们整合的目地。</font></p>
<p align="left"><font size="4"><strong>第一步 完善applicationContext.xml内容</strong></font></p>
<p align="left"><font size="2"><strong>1、添加事务处理。内容如下：</strong></font></p>
<p align="left"><font size="4"><strong>&nbsp;&nbsp;</strong></font><font size="2">&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="sessionFactory" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp; &lt;bean id="customerDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="transactionManager" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="customerDAO" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="find*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;</font></p>
<p align="left"><font size="2"><strong><em>2</em>、CustomerAction Bean注入事务处理。内容如下：</strong></font></p>
<p align="left"><font size="2">&nbsp;&nbsp;&lt;bean name="/customer" class="com.ssh.struts.action.CustomerAction" &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="customerDAO"&gt;<strong>&lt;ref bean="customerDAOProxy"/&gt;</strong>&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt; </font></p>
<p align="left"><strong>&nbsp;3、最终applicationContext.xml文件，内容如下：</strong></p>
<p align="left">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans<br />
&nbsp;xmlns="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>"<br />
&nbsp;xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"<br />
&nbsp;xsi:schemaLocation="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a> <a href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</a>"&gt;<br />
&nbsp;<br />
&nbsp;&lt;bean id="dataSource"<br />
&nbsp;&nbsp;class="org.apache.commons.dbcp.BasicDataSource"&gt;<br />
&nbsp;&nbsp;&lt;property name="driverClassName"<br />
&nbsp;&nbsp;&nbsp;value="com.mysql.jdbc.Driver"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="url"<br />
&nbsp;&nbsp;&nbsp;value="jdbc:mysql://localhost:3306/pullhand"&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="username" value="root"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="password" value="815241"&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;<br />
&nbsp;&lt;bean id="sessionFactory"<br />
&nbsp;&nbsp;class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="dataSource" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="hibernateProperties"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.dialect"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.hibernate.dialect.MySQLDialect<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="mappingResources"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;com/ssh/beans/po/Customer.hbm.xml&lt;/value&gt;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="sessionFactory" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp; &lt;bean id="customerDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="transactionManager" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="customerDAO" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="find*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&lt;bean id="customerDAO" class="com.ssh.beans.dao.CustomerDAO"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;property name="sessionFactory"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="sessionFactory" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt;<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&lt;bean name="/customer" class="com.ssh.struts.action.CustomerAction" &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="customerDAO"&gt;&lt;ref bean="customerDAOProxy"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&lt;/beans&gt;</p>
<p align="left"><font size="4"><strong>第二步，修改CustomerAction</strong></font></p>
<p align="left">最后内容如下：</p>
<p align="left"><br />
package com.ssh.struts.action;</p>
<p align="left">import java.util.ArrayList;<br />
import java.util.List;</p>
<p align="left">import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.apache.struts.action.Action;<br />
import org.apache.struts.action.ActionForm;<br />
import org.apache.struts.action.ActionForward;<br />
import org.apache.struts.action.ActionMapping;</p>
<p align="left">import com.ssh.beans.dao.ICustomerDAO;<br />
import com.ssh.beans.po.Customer;</p>
<p align="left"><br />
public class CustomerAction extends Action {<br />
&nbsp;ICustomerDAO customerDAO=null;<br />
&nbsp;public void setCustomerDAO(ICustomerDAO customerDAO){<br />
&nbsp;&nbsp;this.customerDAO=customerDAO;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public ActionForward execute(ActionMapping mapping, ActionForm form,<br />
&nbsp;&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response) {<br />
&nbsp;&nbsp;List list=new ArrayList();<br />
&nbsp;&nbsp;Customer customer=null;<br />
&nbsp;&nbsp;if(customerDAO!=null){<br />
&nbsp;&nbsp;&nbsp;list=customerDAO.getALLCustomer();<br />
&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;list.size();i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;customer=(Customer)list.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("OK:"+customer.getCustName());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;System.out.println("ERROR or NULL");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return mapping.findForward("success");<br />
&nbsp;}<br />
}</p>
<p align="left"><font size="4"><strong>第三步 解决找不到Action问题</strong></font></p>
<p align="left"><font size="2">初学者会经常遇到下面这个问题：</font></p>
<h1>HTTP Status 404 - Servlet action is not available</h1>
<hr noShade size="1" />
<p><strong><font style="background-color: #525d76" color="#ffffff">type</font></strong> Status report</p>
<p><strong><font style="background-color: #525d76" color="#ffffff">message</font></strong> <u>Servlet action is not available</u></p>
<p><strong><font style="background-color: #525d76" color="#ffffff">description</font></strong> <u>The requested resource (Servlet action is not available) is not available.</u></p>
<hr noShade size="1" />
<h3>Apache Tomcat/5.0.28</h3>
<p>就是找不到我们的action。</p>
<p>当你努力去解决这个问题时，会发现去掉applicationContext.xml下面这个&lt;property&gt;标签，一切正常：</p>
<p>&nbsp;&nbsp;&lt;property name="mappingResources"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;com/ssh/beans/po/Customer.hbm.xml<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</p>
<p>那是什么原因呢？我想大家都会首先想到下面两个问题：</p>
<p>1、路径是否正确：即com/ssh/beans/po/Customer.hbm.xml的路径正确么？</p>
<p>2、文件是否正确：即Customer.hbm.xml的文件内容对么？</p>
<p>当你费了一身力气发现一切OK，到底什么原因？？？</p>
<p><strong>问题在于构件路径(lib)内的包重叠（提示：前提是你要保证这个问题出现之前都正常），所以你要确定构建路径里的包不能重复！</strong></p>
<p><strong>建议：</strong>大家在导入包时，按照默认导入，不要把所有的包都导进工程，在操作中在把需要的jar包导进去(最好不要把整个liberaries导进去），这样即可以减小工程的大小，又能确保struts\spring\hibernate之间的包不会重叠或者被替换。</p>
<p>&nbsp;</p>
<p>好了，我的任务完成了，大家删包去吧！祝你好运！</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/159468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-11-09 22:36 <a href="http://www.blogjava.net/libin2722/articles/159468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate快速入门</title><link>http://www.blogjava.net/libin2722/articles/159466.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Fri, 09 Nov 2007 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/159466.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/159466.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/159466.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/159466.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/159466.html</trackback:ping><description><![CDATA[本文是开发基于spring的web应用的入门文章，前端采用Struts MVC框架，中间层采用spring，后台采用Hibernate。 <br />
<br />
　　本文包含以下内容：<br />
<br />
　　　&#183;配置Hibernate和事务<br />
<br />
　　　&#183;装载Spring的applicationContext.xml文件<br />
<br />
　　　&#183;建立业务层和DAO之间的依赖关系<br />
<br />
　　　&#183;将Spring应用到Struts中<br />
<br />
　　<strong>简介</strong><br />
<br />
　　这个例子是建立一个简单的web应用，叫MyUsers,完成用户管理操作，包含简单的数据库增，删，查，该即CRUD（新建，访问，更新，删除）操作。这是一个三层的web应用，通过Action（Struts）访问业务层，业务层访问DAO。图一简要说明了该应用的总体结构。图上的数字说明了流程顺序－从web（UserAction）到中间层（UserManager），再到数据访问层（UserDAO），然后将结果返回。<br />
<br />
　　Spring层的真正强大在于它的声明型事务处理，帮定和对持久层支持（例如Hiberate和iBATIS）<br />
<br />
　　以下下是完成这个例子的步骤：<br />
<br />
　　1． 安装Eclipse插件<br />
<br />
　　2． 数据库建表<br />
<br />
　　3． 配置Hibernate和Spring<br />
<br />
　　4． 建立Hibernate DAO接口的实现类<br />
<br />
　　5． 运行测试类，测试DAO的CRUD操作<br />
<br />
　　6． 创建一个处理类，声明事务<br />
<br />
　　7． 创建web层的Action和model<br />
<br />
　　8． 运行Action的测试类测试CRUD操作<br />
<br />
　　9． 创建jsp文件通过浏览器进行CRUD操作<br />
<br />
　　10． 通过浏览器校验jsp<br />
<br />
　　<strong>安装eclipse插件</strong><br />
<br />
　　1． Hibernate插件http://www.binamics.com/hibernatesync<br />
<br />
　　2． Spring插件http://springframework.sourceforge.net/spring-ide/eclipse/updatesite/<br />
<br />
　　3． MyEclipse插件(破解版)<br />
<br />
　　4． Tomcat插件. tanghan<br />
<br />
　　5． 其他插件包括xml，jsp，<br />
<strong><br />
　　数据库建表</strong><br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>create table app_user(id number not null primary,firstname vchar(32),lastname vchar(32));</td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>新建项目</strong><br />
<br />
　　新建一个web project，新建后的目录结构同时包含了新建文件夹page用于放jsp文件，和源文件夹test用于放junit测试文件。同时将用到的包，包括struts，hibernate，spring都导入到lib目录下。<br />
<br />
　　创建持久层O/R mapping<br />
<br />
　　1． 在src/com.jandar.model下用hibernate插件从数据库导出app_user的.hbm.xml文件改名为User.hbm.xml<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>＜?xml version="1.0"?＞<br />
            ＜!DOCTYPE hibernate-mapping PUBLIC<br />
            　　 "-//Hibernate/Hibernate Mapping DTD//EN"<br />
            　　 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" ＞<br />
            ＜hibernate-mapping package="com.jandar.model"＞<br />
            ＜class name="User" table="APP_USER"＞<br />
            　＜id<br />
            　　column="ID"<br />
            　　name="id"<br />
            　　type="integer"<br />
            　＞<br />
            <br />
            　　＜generator class="assigned" /＞<br />
            <br />
            　＜/id＞<br />
            <br />
            　＜property<br />
            　　　column="LASTNAME"<br />
            　　　length="10"<br />
            　　　name="lastname"<br />
            　　　not-null="false"<br />
            　　　type="string"<br />
            　/＞<br />
            <br />
            　＜property<br />
            　　　column="FIRSTNAME"<br />
            　　　length="10"<br />
            　　　name="firstname"<br />
            　　　not-null="true"<br />
            　　　type="string"<br />
            　/＞<br />
            <br />
            ＜/class＞<br />
            ＜/hibernate-mapping＞ </td>
        </tr>
    </tbody>
</table>
<br />
　　2． 通过hibernate synchronizer-＞synchronizer file生成User.<a class="bluekey" href="http://dev.yesky.com/devjava/" target="_blank">java</a>文件,User对象对应于数据库中的app_user表<br />
<br />
　　注：在eclipse下自动生成的对象文件不完全相同，相同的是每个对象文件必须实现Serializable接口，必需又toString和hashCode方法；<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>import java.io.Serializable;<br />
            import org.apache.commons.lang.builder.EqualsBuilder;<br />
            import org.apache.commons.lang.builder.HashCodeBuilder;<br />
            import org.apache.commons.lang.builder.ToStringBuilder;<br />
            import org.apache.commons.lang.builder.ToStringStyle;<br />
            <br />
            public class BaseObject implements Serializable {<br />
            　public String toString() {<br />
            　　return ToStringBuilder.reflectionToString(this,<br />
            　　ToStringStyle.MULTI_LINE_STYLE);<br />
            　} <br />
            <br />
            　public boolean equals(Object o) {<br />
            　　return EqualsBuilder.reflectionEquals(this, o);<br />
            　} <br />
            <br />
            　public int hashCode() {<br />
            　　return HashCodeBuilder.reflectionHashCode(this);<br />
            　}<br />
            }<br />
            <br />
            public class User extends BaseObject {<br />
            　private Long id;<br />
            　private String firstName;<br />
            　private String lastName; <br />
            <br />
            　/**<br />
            　* @return Returns the id.<br />
            　*/<br />
            <br />
            　public Long getId() {<br />
            　　return id;<br />
            　} <br />
            <br />
            　/**<br />
            　　* @param id The id to set.<br />
            　*/<br />
            <br />
            　public void setId(Long id) {<br />
            　　this.id = id;<br />
            　}<br />
            <br />
            　/**<br />
            　* @return Returns the firstName.<br />
            　*/<br />
            <br />
            　public String getFirstName() {<br />
            　　return firstName;<br />
            　} <br />
            <br />
            　/**<br />
            　　* @param firstName The firstName to set.<br />
            　*/<br />
            <br />
            　public void setFirstName(String firstName) {<br />
            　　this.firstName = firstName;<br />
            　} <br />
            <br />
            　/**<br />
            　* @return Returns the lastName.<br />
            　*/<br />
            <br />
            　public String getLastName() {<br />
            　　return lastName;<br />
            　} <br />
            <br />
            　/**<br />
            　* @param lastName The lastName to set.<br />
            　*/<br />
            <br />
            　public void setLastName(String lastName) {<br />
            　　this.lastName = lastName;<br />
            　}<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
<strong>创建DAO访问对象</strong><br />
<br />
　　1． 在src/com.jandar.service.dao新建IDAO.java接口，所有的DAO都继承该接口<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>package com.jandar.services.dao;<br />
            <br />
            public interface IDAO {<br />
            <br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　2． 在src/com.jandar.service.dao下新建IUserDAO.java接口 <br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>public interface IUserDAO extends DAO { <br />
            　List getUsers();<br />
            　User getUser(Integer userid);<br />
            　void saveUser(User user);<br />
            　void removeUser(Integer id); <br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　该接口提供了访问对象的方法，<br />
<br />
　　3． 在src/com.jandar.service.dao.hibernate下新建UserDAOHiberante.java<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>import java.util.List;<br />
            import org.apache.commons.logging.Log;<br />
            import org.apache.commons.logging.LogFactory;<br />
            import org.springframework.orm.hibernate.support.HibernateDaoSupport; <br />
            import com.jandar.model.User;<br />
            import com.jandar.service.dao.IUserDAO;<br />
            <br />
            public class UserDaoHibernate extends HibernateDaoSupport implements IUserDAO { <br />
            <br />
            　private Log log=LogFactory.getLog(UserDaoHibernate.class);<br />
            　/* （非 Javadoc）<br />
            　* @see com.jandar.dao.IUserDAO#getUsers()<br />
            　*/<br />
            <br />
            　public List getUsers() {<br />
            　　return getHibernateTemplate().find("from User"); <br />
            　} <br />
            <br />
            　/* （非 Javadoc）<br />
            　* @see com.jandar.dao.IUserDAO#getUser(java.lang.Long)<br />
            　*/<br />
            <br />
            　public User getUser(Integer id) {<br />
            　　// TODO 自动生成方法存根<br />
            　　return (User) getHibernateTemplate().get(User.class,id);<br />
            　} <br />
            <br />
            　/* （非 Javadoc）<br />
            　* @see com.jandar.dao.IUserDAO#saveUser(com.jandar.model.User)<br />
            　*/<br />
            <br />
            　public void saveUser(User user) {<br />
            　　log.debug("xxxxxxx");<br />
            　　System.out.println("yyyy");<br />
            　　getHibernateTemplate().saveOrUpdate(user);<br />
            　　if(log.isDebugEnabled())<br />
            　　{<br />
            　　　log.debug("userId set to "+user.getId());<br />
            　　} <br />
            　} <br />
            <br />
            　/* （非 Javadoc）<br />
            　* @see com.jandar.dao.IUserDAO#removeUser(java.lang.Long)<br />
            　*/<br />
            <br />
            　public void removeUser(Integer id) {<br />
            　　Object user=getHibernateTemplate().load(User.class,id);<br />
            　　getHibernateTemplate().delete(user);<br />
            　　if(log.isDebugEnabled()){<br />
            　　　log.debug("del user "+id);<br />
            　　} <br />
            　} <br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　在这个类中实现了IUserDAO接口的方法，并且继承了HibernateDAOSupport类。这个类的作用是通过hibernate访问、操作对象，进而实现对数据库的操作。
<img src ="http://www.blogjava.net/libin2722/aggbug/159466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-11-09 22:35 <a href="http://www.blogjava.net/libin2722/articles/159466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate实现上传下载</title><link>http://www.blogjava.net/libin2722/articles/159465.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Fri, 09 Nov 2007 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/159465.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/159465.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/159465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/159465.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/159465.html</trackback:ping><description><![CDATA[<strong>引言</strong><br />
<br />
　　文件的上传和下载在J2EE编程已经是一个非常古老的话题了，也许您马上就能掰着指头数出好几个著名的大件：如SmartUpload、Apache的FileUpload。但如果您的项目是构建在Struts+Spring+Hibernate（以下称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 />
　　本文选用的数据库为Oracle 9i，当然你可以在不改动代码的情况下，通过配置文件的调整将其移植到任何具有Blob字段类型的数据库上，如MySQL，SQLServer等。<br />
<br />
　　<strong>总体实现</strong><br />
<br />
　　上传文件保存到T_FILE表中，T_FILE表结构如下：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/661b4k5512t8.gif" border="0"  alt="" /><br />
            图 1 T_FILE表结构</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　其中：<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 />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/9g24f0968d37.jpg" border="0"  alt="" /><br />
            图 2 SSH处理文件上传技术方案</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　文件上传的页面如图 3所示：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/8984n19kf77o.jpg" border="0"  alt="" /><br />
            图 3 文件上传页面</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　文件下载的页面如图 4所示：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/v9hx8m4556my.jpg" border="0"  alt="" /><br />
            图 4 文件下载页面</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　该工程的资源结构如图 5所示：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/s652irpixa30.gif" border="0"  alt="" /><br />
            图 5 工程资源结构</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　工程的类按SSH的层次结构划分为数据持久层、业务层和Web层；WEB-INF下的applicationContext.xml为Spring的配置文件，struts-config.xml为Struts的配置文件，file-upload.jsp为文件上传页面，file-list.jsp为文件列表页面。<br />
<br />
　　本文后面的章节将从数据持久层-＞业务层-＞Web层的开发顺序，逐层讲解文件上传下载的开发过程。<br />
<strong>数据持久层</strong><br />
<br />
　　1、领域对象及映射文件<br />
<br />
　　您可以使用Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer等工具或手工的方式，编写Hibernate的领域对象和映射文件。其中对应T_FILE表的领域对象Tfile.java为：<br />
<br />
　　代码 1 领域对象Tfile<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　特别需要注意的是：数据库表为Blob类型的字段在Tfile中的fileContent类型为byte[]。Tfile的Hibernate映射文件Tfile.hbm.xml放在Tfile .java类文件的相同目录下：<br />
<br />
　　代码 2 领域对象映射文件<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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="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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　第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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　首先，必须定义一个能够从连接池中抽取出本地数据库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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　如第7所示，通过sessionFactory的lobHandler属性进行注入。<br />
<strong>业务层</strong><br />
<br />
　　1、业务层接口<br />
<br />
　　"面向接口而非面向类编程"是Spring不遗余力所推荐的编程原则，这条原则也已经为大部开发者所接受；此外，JDK的动态代理只对接口有效，否则必须使用CGLIB生成目标类的子类。我们依从于Spring的倡导为业务类定义一个接口：<br />
<br />
　　代码 7 业务层操作接口<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　其中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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　在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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　write(OutputStream os,String fileId)也简单地分为两个操作步骤，首先，根据fileId加载表记录，然后将fileContent写入到输出流中。<br />
<br />
　　3、Spring事务配置<br />
<br />
　　下面，我们来看如何在Spring配置文件中为FileService配置声明性的事务<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　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注入。<br />
<strong>Web层实现</strong><br />
<br />
　　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 />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/f7r1dsl4iy25.jpg" border="0"  alt="" /><br />
            图 6 Web层Struts流程图</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　其中，在执行文件上传的请求时，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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　第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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　由于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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　file-list.jsp页面使用Struts标签展示出保存在Request域中的记录：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　展现页面的每条记录挂接着一个链接地址，形如：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 />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img src="http://soft.yesky.com/imagelist/05/12/86u0y1fafg9o.jpg" border="0"  alt="" /><br />
            图 7 FileActionForm</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　当然这样会造成属性的冗余，比如在文件上传的请求中，只会用到fileContent和remark属性，而在文件下载的请求时，只会使用到fileId属性。但这种冗余是会带来好处的--它使得一个Action可以处理多个请求。<br />
<br />
　　2.3 下载文件<br />
<br />
　　在列表页面中点击一个文件下载，其请求由FileAction的download方法来响应，download方法调用业务层的FileService方法，获取文件数据并写出到response的响应流中。通过合理设置HTTP响应头参数，将响应流在客户端表现为一个下载文件对话框，其代码如下所示：<br />
<br />
　　代码 10 业务接口实现类之download<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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. }</td>
        </tr>
    </tbody>
</table>
<br />
　　第15~18行，设置HTTP响应头，将响应类型设置为application/x-msdownload MIME类型，则响应流在IE中将弹出一个文件下载的对话框，如图 4所示。IE所支持的MIME类型多达26种，您可以通过这个网址查看其他的MIME类型：<br />
<br />
http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.asp。<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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　启动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 />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
    <tbody>
        <tr>
            <td>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＞</td>
        </tr>
    </tbody>
</table>
<br />
　　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所提供的方便类，相信这些知识对您的开发都有所裨益
<img src ="http://www.blogjava.net/libin2722/aggbug/159465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-11-09 22:34 <a href="http://www.blogjava.net/libin2722/articles/159465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>