专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »数据库 » ssh上传:SSH实现上传下载(1) »正文

ssh上传:SSH实现上传下载(1)

来源: 发布时间:星期二, 2008年12月16日 浏览:48次 评论:0
Joseph
引言
  文件上传和下载在J2EE编程已经是个非常古老话题了也许您马上就能掰着指头数出好几个著名大件:如SmartUpload、ApacheFileUpload但如果您项目是构建在Struts+Spring+Hibernate(以下称SSH)框架上这些大件就显得笨重而沧桑了SSH提供了个简捷方便文件上传下载方案我们只需要通过些配置并辅以少量代码就可以完好解决这个问题了
  本文将围绕SSH文件上传下载主题向您详细讲述如何开发基于SSHWebSSH各框架均为当前最新版本:
  ·Struts 1.2
  ·Spring 1.2.5
  ·Hibernate 3.0
  本文选用数据库为Oracle 9i当然你可以在不改动代码情况下通过配置文件调整将其移植到任何具有Blob字段类型数据库上如MySQLSQLServer等
  总体实现
  上传文件保存到T_FILE表中T_FILE表结构如下:
图 1 T_FILE表结构
  其中:
  ·FILE_ID:文件ID32个用Hibernateuuid.hex算法生成
  ·FILE_NAME:文件名
  ·FILE_CONTENT:文件内容对应OracleBlob类型
  ·REMARK:文件备注
  文件数据存储在Blob类型FILE_CONTENT表字段上在Spring中采用OracleLobHandler来处理Lob字段(包括Clob和Blob)由于在中不需要引用到oracle数据驱动具体类且屏蔽了区别数据库处理Lob字段思路方法上差别从而撤除在多数据库移植上樊篱
  1.首先数据表中Blob字段在Java领域对象中声明为类型而非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将文件 2进制数据持久化到数据库解决方案而Struts通过将表单中file类型组件映射为ActionForm中类型为org.apache.struts.upload. FormFile属性来获取表单提交文件数据
  综上所述我们可以通过图 2描绘出SSH处理文件上传方案:
图 2 SSH处理文件上传技术方案
  文件上传页面如图 3所示:

图 3 文件上传页面
  文件下载页面如图 4所示:

图 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 Tfile
3.{
4. private String fileId;
5. private String fileName;
6. private fileContent;
7. private String remark;
8. …//getter and ter
9. }
  特别需要注意是:数据库表为Blob类型字段在Tfile中fileContent类型为TfileHibernate映射文件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. < table="T_FILE">
7. <id type="java.lang.String" column="FILE_ID">
8. <generator />
9. </id>
10. <property
11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType"
12. column="FILE_CONTENT" lazy="true"/>
13. …//其它般字段映射
14. </
15. </hibernate-mapping>
  fileContent字段映射为Spring所提供BlobByteArrayType类型BlobByteArrayType是用户自定义数据类型它实现了Hibernate org.hibernate.usertype.UserType接口BlobByteArrayType使用从sessionFactory获取Lob操作句柄lobHandler将数据保存到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 TfileDAOHibernate
8. extends HibernateDaoSupport implements TfileDAO
9. {
10. public Tfile findByFildId(String fileId)
11. {
12. (Tfile) getHibernateTemplate.get(Tfile., fileId);
13. }
14. public void save(Tfile tfile)
15. {
16. getHibernateTemplate.save(tfile);
17. getHibernateTemplate.flush;
18. }
19. public List findAll
20. {
21. getHibernateTemplate.loadAll(Tfile.);
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
4. destroy-method="close">
5. <property value="oracle.jdbc.driver.OracleDriver"/>
6. <property value="jdbc:oracle:thin:@localhost:1521:ora9i"/>
7. <property value="test"/>
8. <property value="test"/>
9. </bean>
10. <!-- Hibernate会话工厂配置 //-->
11. <bean
12. >
13. <property ref="dataSource"/>
14. <property >
15. <list>
16. <value>path:/sshfile/model</value>
17. </list>
18. </property>
19. <property >
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
28. >
29. <property ref="sessionFactory"/>
30. </bean>
31. <!--DAO配置 //-->
32. <bean >
33. <property ref="hibernateTemplate" />
34. </bean>
35. …
36. </beans>
  第3~9行定义了个数据源其实现类是apacheBasicDataSource第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相关封装类位于org.springframework.orm.hibernate2.*包中而Hibernate3.0封装类位于org.springframework.orm.hibernate3.*包中需要根据您所选用Hibernate版本进行正确选择

  3、Lob字段处理配置

  我们前面已经指出OracleLob字段和般类型字段在操作上有个明显区别--那就是你必须首先通过Oracleempty_blob/empty_clob化Lob字段然后获取该字段引用通过这个引用更改其值所以要完成对Lob字段操作Hibernate必须执行两步数据库访问操作先Insert再Update

  使用BlobByteArrayType字段类型后为什么我们就可以象字段类型样操作Blob字段呢?可以确定点是:BlobByteArrayType不可能逾越Blob天生操作方式原来是BlobByteArrayType数据类型本身具体数据访问功能它通过LobHandler将两次数据访问动作隐藏起来使Blob字段操作在表现上和其他般字段业类型无异所以LobHandler即是那个"苦了我幸福十亿人"那位幕后英雄

  LobHandler必须注入到Hibernate会话工厂sessionFactory中sessionFactory负责产生和数据库交互SessionLobHandler配置如代码 5所示:

  代码 5 Lob字段处理句柄配置

1. <beans>
2. …
3. <bean
4.
5. lazy-init="true"/>
6. <bean
7. lazy-init="true">
8. <property >
9. <ref local="nativeJdbcExtractor"/>
10. </property>
11. </bean>
12. …
13. </beans>
  首先必须定义个能够从连接池中抽取出本地数据库JDBC对象(如OracleConnectionOracleResultSet等)抽取器:nativeJdbcExtractor这样才可以执行些特定数据库操作对于那些仅封装了Connection而未包括Statement简单数据连接池SimpleNativeJdbcExtractor是效率最高抽取器实现类但具体到apacheBasicDataSource连接池它封装了所有JDBC对象这时就需要使用CommonsDbcpNativeJdbcExtractor了Spring针对几个著名Web服务器数据源提供了相应JDBC抽取器:

  ·WebLogic:WebLogicNativeJdbcExtractor

  ·WebSphere:WebSphereNativeJdbcExtractor

  ·JBoss:JBossNativeJdbcExtractor

  在定义了JDBC抽取器后再定义lobHandlerSpring 1.2.5提供了两个lobHandler:

  ·DefaultLobHandler:适用于大部分数据库如SqlServerMySQL对Oracle 10g也适用但不适用于Oracle 9i(看来Oracle 9i确实是个怪胎谁叫Oracle 公司自己都说Oracle 9i是个过渡性产品呢)

  ·OracleLobHandler:适用于Oracle 9i和Oracle 10g

  由于我们数据库是Oracle9i所以使用OracleLobHandler
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: