logo资料库

SSH实现文件上传和下载.doc

第1页 / 共21页
第2页 / 共21页
第3页 / 共21页
第4页 / 共21页
第5页 / 共21页
第6页 / 共21页
第7页 / 共21页
第8页 / 共21页
资料共21页,剩余部分请下载后查看
 引言 文件的上传和下载在 J2EE 编程已经是一个非常古老的话题了,也许您马上就能掰着指头数 出好几个著名的大件:如 SmartUpload、Apache 的 FileUpload。但如果您的项目是构建在 Struts+Spring+Hibernate(以下称 SSH)框架上的,这些大件就显得笨重而沧桑了,SSH 提供了一 个简捷方便的文件上传下载的方案,我们只需要通过一些配置并辅以少量的代码就可以完好解决 这个问题了。 本文将围绕 SSH 文件上传下载的主题,向您详细讲述如何开发基于 SSH 的 Web 程序。SSH 各框架的均为当前最新版本: ·Struts 1.2 ·Spring 1.2.5 ·Hibernate 3.0 本文选用的数据库为 Oracle 9i,当然你可以在不改动代码的情况下,通过配置文件的调整将 其移植到任何具有 Blob 字段类型的数据库上,如 MySQL,SQLServer 等。 总体实现 上传文件保存到 T_FILE 表中,T_FILE 表结构如下: 图 1 T_FILE 表结构 其中: ·FILE_ID:文件 ID,32 个字符,用 Hibernate 的 uuid.hex 算法生成。 ·FILE_NAME:文件名。 ·FILE_CONTENT:文件内容,对应 Oracle 的 Blob 类型。 ·REMARK:文件备注。
文件数据存储在 Blob 类型的 FILE_CONTENT 表字段上,在 Spring 中采用 OracleLobHandler 来处理 Lob 字段(包括 Clob 和 Blob),由于在程序中不需要引用到 oracle 数据驱动程序的具体 类且屏蔽了不同数据库处理 Lob 字段方法上的差别,从而撤除程序在多数据库移植上的樊篱。 1.首先数据表中的 Blob 字段在 Java 领域对象中声明为 byte[]类型,而非 java.sql.Blob 类型。 2.数据表 Blob 字段在 Hibernate 持久化映射文件中的 type 为 org.springframework.orm.hibernate3.support.BlobByteArrayType,即 Spring 所提供的用户自定义的 类型,而非 java.sql.Blob。 3.在 Spring 中使用 org.springframework.jdbc.support.lob.OracleLobHandler 处理 Oracle 数据库 的 Blob 类型字段。 通过这样的设置和配置,我们就可以象持久化表的一般字段类型一样处理 Blob 字段了。 以上是 Spring+Hibernate 将文件二进制数据持久化到数据库的解决方案,而 Struts 通过将表 单中 file 类型的组件映射为 ActionForm 中类型为 org.apache.struts.upload. FormFile 的属性来获取 表单提交的文件数据。 综上所述,我们可以通过图 2,描绘出 SSH 处理文件上传的方案:
图 2 SSH 处理文件上传技术方案 文件上传的页面如图 3 所示: 图 3 文件上传页面
图 4 文件下载页面 该工程的资源结构如图 5 所示: 图 5 工程资源结构
工程的类按SSH 的层次结构划分为数据持久层、业务层和Web 层;WEB-INF 下的 applicationContext.xml 为 Spring 的配置文件,struts-config.xml 为 Struts 的配置文件,file-upload.jsp 为文件上传页面,file-list.jsp 为文件列表页面。 本文后面的章节将从数据持久层->业务层->Web 层的开发顺序,逐层讲解文件上传下载的开发过程。 数据持久层 1、领域对象及映射文件 您可以使用 Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer 等工具或手工的方式,编写 Hibernate 的领域对象和映射文件。其中对应 T_FILE 表的领域对象 Tfile.java 为: 代码 1 领域对象 Tfile 1. package sshfile.model; 2. public class Tfile 3.{ 4. private String fileId; 5. private String fileName; 6. private byte[] fileContent; 7. private String remark; 8. …//getter and setter 9. } 特别需要注意的是:数据库表为 Blob 类型的字段在 Tfile 中的 fileContent 类型为 byte[]。Tfile 的 Hibernate 映射文件 Tfile.hbm.xml 放在 Tfile .java 类文件的相同目录下: 代码 2 领域对象映射文件 1. <?xml version="1.0"?> 2. <!DOCTYPE hibernate-mapping PUBLIC 3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > 5. <hibernate-mapping> 6. <class name="sshfile.model.Tfile" table="T_FILE"> 7. <id name="fileId" type="java.lang.String" column="FILE_ID"> 8. <generator class="uuid.hex"/> 9. </id> 10. <property name="fileContent" 11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType" 12. column="FILE_CONTENT" lazy="true"/> 13. …//其它一般字段的映射 14. </class>
15. </hibernate-mapping> fileContent 字段映射为 Spring 所提供的 BlobByteArrayType 类型,BlobByteArrayType 是用户自定义的 数 据 类 型 , 它 实 现 了 Hibernate 的 org.hibernate.usertype.UserType 接 口 。 BlobByteArrayType 使 用 从 sessionFactory 获取的 Lob 操作句柄 lobHandler 将 byte[]的数据保存到 Blob 数据库字段中。这样,我们就再 没有必要通过硬编码的方式,先 insert 然后再 update 来完成 Blob 类型数据的持久化,这个原来难伺候的老 爷终于被平民化了。关于 lobHandler 的配置请见本文后面的内容。 此外 lazy="true"说明地返回整个 Tfile 对象时,并不返回 fileContent 这个字段的数据,只有在显式调用 tfile.getFileContent()方法时才真正从数据库中获取 fileContent 的数据。这是 Hibernate3 引入的新特性,对于 包含重量级大数据的表字段,这种抽取方式提高了对大字段操作的灵活性,否则加载 Tfile 对象的结果集时 如果总是返回 fileContent,这种批量的数据抽取将可以引起数据库的"洪泛效应"。 2、DAO 编写和配置 Spring 强调面向接口编程,所以我们将所有对 Tfile 的数据操作的方法定义在 TfileDAO 接口中,这些 接口方法分别是: ·findByFildId(String fileId) ·save(Tfile tfile) ·List findAll() TfileDAOHibernate 提供了对 TfileDAO 接口基于 Hibernate 的实现,如代码 3 所示: 代码 3 基于 Hibernate 的 fileDAO 实现类 1. package sshfile.dao; 2. 3. import sshfile.model.*; 4. import org.springframework.orm.hibernate3.support.HibernateDaoSupport; 5. import java.util.List; 6. 7. public class TfileDAOHibernate 8. extends HibernateDaoSupport implements TfileDAO 9. { 10. public Tfile findByFildId(String fileId) 11. { 12. return (Tfile) getHibernateTemplate().get(Tfile.class, fileId); 13. } 14. public void save(Tfile tfile) 15. { 16. getHibernateTemplate().save(tfile); 17. getHibernateTemplate().flush();
18. } 19. public List findAll() 20. { 21. return getHibernateTemplate().loadAll(Tfile.class); 22. } 23. } TfileDAOHibernate 通 过 扩 展 Spring 提 供 的 Hibernate 支 持 类 HibernateDaoSupport 而 建 立 , HibernateDaoSupport 封装了 HibernateTemplate,而 HibernateTemplate 封装了 Hibernate 所提供几乎所有的的 数据操作方法,如 execute(HibernateCallback action),load(Class entityClass, Serializable id),save(final Object entity)等等。 所以我们的 DAO 只需要简单地调用父类的 HibernateTemplate 就可以完成几乎所有的数据库操作了。 由于 Spring 通过代理 Hibernate 完成数据层的操作,所以原 Hibernate 的配置文件 hibernate.cfg.xml 的信 息也转移到 Spring 的配置文件中: 代码 4 Spring 中有关 Hibernate 的配置信息 1. <beans> 2. <!-- 数据源的配置 //--> 3. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 4. destroy-method="close"> 5. <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 6. <property name="url" value="jdbc:oracle:thin:@localhost:1521:ora9i"/> 7. <property name="username" value="test"/> 8. <property name="passWord" value="test"/> 9. </bean> 10. <!-- Hibernate 会话工厂配置 //--> 11. <bean id="sessionFactory" 12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 13. <property name="dataSource" ref="dataSource"/> 14. <property name="mappingDirectoryLocations"> 15. <list> 16. <value>classpath:/sshfile/model</value> 17. </list> 18. </property> 19. <property name="hibernateProperties"> 20. <props> 21. <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> 22. <prop key="hibernate.cglib.use_reflection_optimizer">true</prop> 23. </props> 24. </property> 25. </bean> 26. <!-- Hibernate 模板//-->
27. <bean id="hibernateTemplate" 28. class="org.springframework.orm.hibernate3.HibernateTemplate"> 29. <property name="sessionFactory" ref="sessionFactory"/> 30. </bean> 31. <!--DAO 配置 //--> 32. <bean id="tfileDAO" class="sshfile.dao.TfileDAOHibernate"> 33. <property name="hibernateTemplate" ref="hibernateTemplate" /> 34. </bean> 35. … 36. </beans> 第 3~9 行定义了一个数据源,其实现类是 apache 的 BasicDataSource,第 11~25 行定义了 Hibernate 的 会话工厂,会话工厂类用 Spring 提供的 LocalSessionFactoryBean 维护,它注入了数据源和资源映射文件, 此外还通过一些键值对设置了 Hibernate 所需的属性。 其中第 16 行通过类路径的映射方式,将 sshfile.model 类包目录下的所有领域对象的映射文件装载进来, 在本文的例子里,它将装载进 Tfile.hbm.xml 映射文件。如果有多个映射文件需要声明,使用类路径映射方 式显然比直接单独指定映射文件名的方式要简便。 第 27~30 行定义了 Spring 代理 Hibernate 数据操作的 HibernateTemplate 模板,而第 32~34 行将该模板 注入到 tfileDAO 中。 需要 指定的是 Spring 1.2.5 提供 了两套 Hibernate 的支 持包,其 中 Hibernate 2 相关 的封装类 位于 3.0 的 封 装 类 位 于 org.springframework.orm.hibernate2.* 包 中 , 而 Hibernate org.springframework.orm.hibernate3.*包中,需要根据您所选用 Hibernate 版本进行正确选择。 3、Lob 字段处理的配置 我们前面已经指出 Oracle 的 Lob 字段和一般类型的字段在操作上有一个明显的区别--那就是你必须首 先通过 Oracle 的 empty_blob()/empty_clob()初始化 Lob 字段,然后获取该字段的引用,通过这个引用更改其 值。所以要完成对 Lob 字段的操作,Hibernate 必须执行两步数据库访问操作,先 Insert 再 Update。 使用 BlobByteArrayType 字段类型后,为什么我们就可以象一般的字段类型一样操作 Blob 字段呢?可以确 定的一点是:BlobByteArrayType 不可能逾越 Blob 天生的操作方式,原来是 BlobByteArrayType 数据类型本 身具体数据访问的功能,它通过 LobHandler 将两次数据访问的动作隐藏起来,使 Blob 字段的操作在表现 上和其他一般字段业类型无异,所以 LobHandler 即是那个"苦了我一个,幸福十亿人"的那位幕后英雄。 LobHandler 必须注入到 Hibernate 会话工厂 sessionFactory 中,因为 sessionFactory 负责产生与数据库交 互的 Session。LobHandler 的配置如代码 5 所示: 代码 5 Lob 字段的处理句柄配置 1. <beans> 2. … 3. <bean id="nativeJdbcExtractor"
分享到:
收藏