基于Hadoop的企业级网盘系统的研究与开发

基于Hadoop的企业级网盘系统的研究与开发

    

Research and Development of Enterprise-class Online Storage System based on Hadoop


 演示网站:http://haodisk.duapp.com

 

  

项目地址:http://haodisk.duapp.com

博客:http://www.toocruel.net

本文地址:http://www.toocruel.net/post/haodisk.html

 

2014 5


 

摘要

 

企业网盘是基于云计算理念推出的企业数据网络存储和管理解决方案,利用互联网后台数据中心的海量计算和存储能力为企业提供数据汇总分发、存储备份和管理等服务。 企业网盘是一个企事业单位私有的专用网盘系统,具有强大和简单易用的文件管理、协同办公、部门或虚拟团队级文件共享等丰富功能。 与免费的个人网盘相比,具有更强的团队协同功能,在组织架构、共享权限上能适应企业的需求。在多人共享、协作日常办公文档时能有效的提高工作效率。

    基于Hadoop企业级网盘系统的研究与开发主要就是开发这样一个系统,主要包括系统前台、系统后台、Android手机客户端三个部分。本文主要描述了系统后台的开发流程。通过该流程将对采用JavaEE技术和云存储技术对系统进行设计以及具体实现。系统后台的开发是采用Java语言,使用SpringHibernateStruts2JavaEE开发框架,使用Hadoop的分布式文件系统存储文件。数据库采用关系型数据库Mysql,同时对采用Hadoop的非关系型数据库HBase对该网盘系统进行数据库设计也进行了研究。

 

关键词:企业网盘;文件共享;云存储;非关系型数据库

 

 

Abstract

Enterprise online storage system is introduced the concept of cloud-based enterprise network storage and data management solutions,using massive computing and storage capacity of the Internet background data centers to provide enterprises with distributed data collection, storage, backup and management services. Enterprise-class online storage system is a private network of private enterprises, with a strong and easy to use document management, collaborative office, department or team level virtual file-sharing and other rich features. Compared with the free personal network disk, a stronger team collaboration capabilities, in the organizational structure, the share permissions can adapt to the needs of enterprises. In multiplayer sharing, can effectively improve work efficiency when collaborating everyday office documents.

Research and development of enterprise-class online storage system based on Hadoop is mainly to develop such a system, including system foreground, the system background, Android mobile client in three parts. This paper describes the background of the system development process. The process will be adopted by JavaEE technologies and cloud storage technology for system design and implementation. The Development of system background using the Java language, JavaEE development framework such as Spring, Hibernate, Struts2 and so on, and using Hadoop distributed file system to store files. The systrem using relational databases Mysql, while design using Hadoop HBase non-relational database as system database were also studied.

Key words: Enterprise-class online storage; Cloud storage; File-sharing

 

  

摘要

Abstract

  

1 引言

1.1课题来源及意义

1.2技术发展概况

2 可行性分析

2.1 技术可行性

2.1.1 JavaEE技术简介

2.1.2 B/S结构

2.1.3 Struts2框架技术简介

2.1.4 Hibernate框架技术简介

2.1.5 Spring框架技术简介

2.1.6 Hadoop云计算技术简介

2.1.7 Json轻量级数据交换格式

2.1.8 HBase非关系数据库技术简介

2.2 经济可行性

2.3 操作可行性

3 需求分析

3.1 系统需求

3.1.1 功能需求

3.1.2 性能需求

4 总体设计

4.1 系统简介

4.1.1 系统架构

4.1.2 系统功能框架

4.1.3 文件管理

4.1.4 权限管理

4.1.5 用户管理

4.1.6 部门管理

4.1.7 群组管理

4.1.8 系统管理

4.2 数据库设计

4.2.1 数据库

4.2.2 物理模型

4.2.3 数据库结构

4.3 Hbase数据库设计

4.3.1 使用Hbase的优势

4.3.2 Hbase存储结构

4.3.3 Hbase与关系型数据库的对比

4.3.4 Hbase中表结构设计

5 详细设计和实现

5.1 系统的开发环境

5.2 类设计

5.3 系统模块实现

5.3.1 文件管理模块实现

5.3.2 权限管理模块实现

5.3.3 文件共享模块实现

6 系统测试

6.1 软件测试定义

6.2 软件测试目的

6.3 软件测试方法

6.4 功能模块测试

6.4.1 文件上传功能测试

6.4.2 文件下载功能测试

6.4.3 文件其他操作测试

6.4.4 文件共享功能测试

7 总结

参考文献

致谢

 .............................................................................................................. 

附录A: 主要源程序...............................................................................  

附录B: 软件使用说明书....................................................................... 

 

      


1 引言

1.1课题来源及意义

随着信息技术地不断发展和高校办学规模越来越大,高校的行政办公和教学活动中时刻进行着海量数据资源的产生和流通,信息共享交流更加频繁,如各类文档文件、教学课件、多媒体素材等都需要频繁使用。移动存储设备由于使用不便和共享困难等一般适用于存储个人数据;E-Mail使用较方便,但不适用于存储传输较大的文件;网上邻居等局域网共享方式受到校园网结构的制约无法很好的满足用户需求;FTP功能相对强大,但是服务界面简陋,有些用户使用起来有一定困难。因此,如何在安全、便捷、可接受代价的前提下向用户提供大容量、高可靠性的网络存储业务,成为了信息化建设的一大课题。于是网络硬盘应运而生,摒弃了以上不足。但随着存储技术的不断发展,传统的网盘技术已经显得力不从心,存在传输速度慢、容灾备份及恢复能力低、安全性差、营运成本高等诸多瓶颈。而近年流行的云存储技术推动了网盘行业的浪潮,如百度云、腾讯微云等。云计算架构的分布式存储技术能充分利用其技术,结合超大规模、高可扩展性、廉价性、高可靠性等特点来满足当前PB级的海量数据存储管理要求。云存储是构建在高速分布式存储网络上的数据中心,它将网络中大量不同类型的存储设备通过应用软件集合起来协同工作,形成一个安全的数据存储和访问系统,适用于各大中小型企业与个人用户的数据资料存储、备份、归档等一系列需求。尽管业内已经提供了大量云存储服务相关的产品,由于目前的云存储服务大多是商业化产品,对企业网和校园网的信息化建设来说,在数据安全和价格上都是问题。所以,采用Hadoop的分布式存储技术开发这样一个能满足海量数据存储、高效可靠、安全稳定、低成本等网盘系统有着十分积极的意义。

1.2技术发展概况

随着移动互联网大潮的到来,随时随地办公、学习、娱乐等成了可能。人们无时无刻在产生文档、视频、照片等文件,同时又迫切的需要随时随地去调阅、编辑、保存这些信息数据,此时,帮助用户方便、快捷的储存、调用这些文件的网盘应运而生。

网盘最初是解决发送大文件问题,以及满足网民对于一些好的资料的收藏而推出。网盘需要投入相应的硬件设施,同样需要有一定的带宽,这样也就增加了相应的成本。目前国内的网盘主要分为2种类型,一种是为娱乐资源类型,一种是专注于网络存储的应用型。从互联网的发展角度来说,很多的网盘都是打着免费的旗号在运营着,但是随着用户数的增加,以及原本网速这道坎,导致很多运营商的发展有点难堪。

近年来,由于新兴起的云计算与云储存技术研究浪潮,网盘行业经历了一次革命。互联网行业巨头百度、金山、腾讯、360等都纷纷涉足网盘行业。甚至打击起暴力营销战,突然都为网盘“掐”起来。先是金山快盘推出100G容量;360随后跟进,宣称只要完成几个简单任务,就可获得360G的容量;而后百度网盘继续跟进,花1块钱就可以获得1T永久容量的网盘;向来凶猛强悍的360,干脆送给用户1T的容量,还是永久免费连传统的IT企业也不甘落后,华为网盘推出惊人的无限空间终结了这场无底线的混战。

各大互联网巨头都在极力打造一个属于自己的网盘整合平台,通过平台提供各种用户常用的服务,例如下载、分享、支付、社交等来建立起庞大的帝国。在国外无论是Google、苹果还是微软,都将网盘纳入自己的账号生态系统;在国内,迅雷依托下载、金山依托办公、腾讯依托QQ和微信、360依托安全软件和安全浏览器,都在不断扩展自己的领域,形成属于自己的平台,掌握了流量的入口。这些巨头公司都想搭生态、做循环、留住用户、圈住开发者,那么网盘就是其中很重要的一个基础建设项目,自然成兵家必争之地。

网盘的发展在后期,随着国内网速的提升,以及对于网盘的便利性在网民中的普及,再进一步提升速度和安全,打造品牌个性云服务,应该会有很好的发展。

 

 

 

 

 

 

 

2 可行性分析

2.1 技术可行性

基于Hadoop的企业级网盘系统后台的开发的技术架构是:JAVA +Struts2+Hibernate+Spring+Jsp+JQuery/Ajax+Hadoop,采用MVC分层的开发模式。将项目分为一下几层:

表现层(V) Jsp+JQuery/Ajax

控制层(C) Struts2

业务层(C)  具体模块的业务方法

数据访问层(M) Hibernate+Hadoop Hibernate处理的是网盘系统产生的用户数据,Hadoop用来存储用户真实的文件。

2.1.1 JavaEE技术简介

JavaEEJava Platform Enterprise Edition)是一个开发分布式企业级应用的规范和标准。JavaEE应用程序是由组件构成的。J2EE组件是具有独立功能的单元,他们通过相关的类和文件组装成JavaEE应用程序,并与其他组件交互。JavaEE包括的技术有:Web ServiceStrutsHibernateSpringJSPServletJSFEJBJavaBeanJDBCJNDIXMLJavaSE

框架即Framework,我们可以把框架理解为某种应用的半成品,就是一组组件,供用户选用,完成用户自己的系统。简单地说就是使用别人准备好的组件,来实施自己的项目。框架技术是在JavaEE的基础上形成的,而应用程序是在框架的基础上创建的。

应用程序的三层结构是表示层,由用户界面和用户生成界面的代码组成;中间层,包含系统的业务和功能代码;数据层,负责完成存取数据库的数据和对数据进行封装。

三层体系结构的优点:一个组件的更改不会影响其他两个组件。例如:如果用户需要更换数据库,那么只有数据层组件需要修改代码。同样,如果更改了用户界面设计,那么只有表示层组件需要修改。由于表示层和数据层相互独立,因而可以方便地扩充表示层,使系统具有良好的可扩展性。

JavaEE技术体系结构可分为:表示层技术、中间层技术、数据层技术。JavaEE还涉及到系统集成的一些技术。

2.1.2 B/S结构

B/S结构(Browser/Server浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。客户机上只要安装一个浏览器Browser),如Netscape NavigatorInternet Explorer服务器安装OracleSybaseInformix SQL Server等数据库。浏览器通过Web Server 同数据库进行数据交互。

2.1.3 Struts2框架技术简介

         Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。Struts2 是MVC框架组件之一,主要充当MVC中的Controllor(控制器)角色。它做的工作就是对于用户的每一个URL资源请求都会引导到对应的Java程序(Servlet)处理,这就是控制器。接着,这个Java程序就会调用业务层和数据访问层的代码。在本网盘系统中就是这样,Struts中的Action接受用户请求,调用业务层的方法处理,业务层一般会调用数据访问层,如果是上传文件或下载文件的话业务层会调用Hadoop文件存储层,最后程序处理结果是以Json返回的,由表示层接收处理。


2.1.4 Hibernate框架技术简介

Hibernate是非常优秀、成熟的 ORM 框架。提供强大的对象和关系数据库映射以及查询功能。Hibernate是面向对象的程序设计语言和关系型数据库之间的桥梁,允许开发者采用面向对象的方式来操作关系数据库。Hibernate是一个基于jdbc的开源的持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。HibernateJDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑。

2.1.5 Spring框架技术简介

       简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。pring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。Spring常用来整合项目,管理整个系统中的Java对象,它有一个容器专门放这些对象。由它管理项目对象(MVC各层的实例对象)后,所有层统一都从这个容器中取对象使用。Spring提供了很方便的依赖注入方式,或是基于注解或是手工配置XML都能取出Spring管理的对象。

2.1.6 Hadoop云计算技术简介

Hadoop 是一个分布式系统基础架构,由 Apache 基金会开发。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力高速运算和存储。 Hadoop 实现了一个分布式文件系统(Hadoop Distributed File System),简称 HDFS HDFS 有着高容错性的特点,并且设计用来部署在低廉的硬件上。而且它提供高传输率来访问应用程序的数据,适合那些有着超大数据集的应用程序。HDFS 放宽了POSIX 的要求这样可以流的形式访问文件系统中的数据。Hadoop带有用Java语言编写的框架,因此运行在Linux生产平台上是非常理想的。Hadoop 上的应用程序也可以使用其他语言编写,比如C++

2.1.7 Json轻量级数据交换格式

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScriptStandard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。简单地说[2]JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪,但是JavaScript很容易解释它,而且 JSON 可以表示比"名称 / 值对"更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。

2.1.8 HBase非关系数据库技术简介

       HBase是一个分布式的、非关系型开源数据库。 HBase有如下几个特点: HBaseNo-SQL的一个典型实现,提升了系统的可扩展性; HBase支持线性水平扩展,极大提升了系统的可伸 缩性和运算能力; HBaseGoogleBigTable有异曲同工之妙,底层也是建立在HDFS(Hadoop分布式文件系统)之上,可以搭建 在廉价的PC机集群上。

       NoSQL(NoSQL = Not Only SQL),意思是不仅仅是SQL的扩展,一般指的是非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显 得力不从心,传统的电信行业动辍就千万甚至上亿的数据,甚至有客户提出需要存储相关的日志数据50年以上,暴露了很多难以克服的问题,而非关系型的数据库 则由于其本身的特点得到了非常迅速的发展。

关系型数据库难以克服的问题:

l        不能很好处理对数据库高并发读写的需求;

l        不能很好处理对海量数据的高效率存储和访问的需求;

l        不能很好处理对数据库的高可扩展性和高可用性的需求。

SQL语言和关系型数据库(MySQLPostgreSQLOracle等)是通用的数据解决方案,占有绝大多数的市场。但是就像上面提到的,它有很多难以解决的问题。不过在最近兴起的NoSQL运动中,涌现出一批具备高可用性、支持线性扩展、支持MapReduce操作等特性的数据产品比如MongoDBCouchDBHbase,它们具有如下特性:

l        频繁的写入操作、相对较少的读取统计信息的操作;

l        海量数据(如数据仓库中需要分析的数据)适合存储在一个结构松散、分布式的文件存储系统中;

l        存储二进制文件(如mp3或者pdf文档)并且能够直接为用户的浏览器提供下载功能。

使用这些非关系数据库并不是要取代原有的关系数据库,而是为不同的应用场景提供更多的选择。也就是说,在一些特定的情况下如果是关系型的数据库解决不了的问题,那么就可以考虑使用nosql,而不是说完全将应用移植到nosql上,毕竟适合才是最好的

2.2 经济可行性

基于Hadoop的企业级网盘使用的技术或框架(SSH框架、Mysql数据库、Hadoop)都是免费开源的,不涉及版权和价格问题。Hadoop集群对集群的机器要求也不高,普通机器集群就可以发挥Hadoop处理海量数据的优势。该系统采用的是Java开发的,因此可跨平台运行,windowLinux均可,但Hadoop集群是Linux机器集群是必须的。因此,该系统在经济上是完全可行的。

2.3 操作可行性

本系统对于服务器端和客户端所要求的软硬件的最低配置在大多数的用户计算机都能达到,现有的开发工具(MyEclipseMysql)完全能够实现,而且本系统对管理员和网盘用户没有任何的特殊要求,实际操作基本上以鼠标操作并辅以少量的键盘操作,操作方式很方便。因此本系统具有良好的易用性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3 需求分析

3.1 系统需求

对于系统的开发而言,系统的需求工作非常重要,它规定了系统设计统一的最基本的要求,需求分析的结果是系统设计实现测试验收和维护的依据。

对高校校园网用户或企业级用户来说,对外网的网络硬盘服务的使用积极性有限,首先是因为这些服务都处在校园网或企业网出口之外,使用这些服务会占用宝贵的出口带宽;其次,校园网或企业网出口带宽有限,并不适合传输较大的文件;第三,外网的网络硬盘服务所提供的空间极其有限,不能满足高校和企业这一用户群体的需求。因此,需要在校园内或企业内部开展网络硬盘服务。

本系统基于现状,开发语言为Java,采用Struts2HibernateSpringJavaEE框架技术搭建后台和HtmlCssJavascript以及AjaxJquery等前端技术开发,实现企业网盘的功能。

3.1.1 功能需求

因为是企业级的网盘,面向企业开发的,所以用户可操作空间类型被设计为三类:个人、部门、群组,用户可在自己的个人空间、所属部门(一个用户一个门户)、所属群组(一个用户可以属于多个群组)的空间进行文件操作(上传、下载、重命名、创建目录、移动、复制、删除等以下简称文件操作)。同一个部门或同一个群组内的用户能对该部门或群组空间的文件进行操作,这同时也实现部门和群组共享。此外,分享功能还需要外链分享、指定用户分享、邮件分享等。用户能查看并操作自己的分享、查看和操作收到的别人的分享。整个系统需要一个用户--角色--权限的权限机制,保证系统安全,维持系统正常运行。

1. 个人文件管理

1)文件操作:上传、下载、重命名、创建目录、移动、复制、删除等。对与自己的个人空间,用户拥有全部文件操作权限。

2)设置共享:对于每个文件和目录用户可以设置(包括编辑和删除)共享,有外链分享、邮件分享、指定用户分享、群组分享和部门分享等。

2. 部门文件管理

1)文件操作:部门成员才能进行文件操作,非部门成员无法访问部门文件,而且普通部门成员只能查看和下载,部门管理员才拥有修改、删除等操作。(企业里部门的文件当然不能被员工随意修改和删除)

2)共享相关:部门成员可将部门文件复制到自己的个人空间。

3. 群组文件管理

1)文件操作:群组成员才能进行文件操作,非群组成员无法访问该群组文件,和部门不通,群组的普通成员不只能查看和下载,同时才拥有修改、删除等操作。因为群组的设计目地就是为一个项目组、团队提供共享空间,如果只有管理员能编辑和删除,这也就没什么意义了。

2)共享相关:群组成员可将群组文件复制到自己的个人空间。

4. 文件共享管理

1)外链分享:用户将文件以外链形式分享,生成一个公开的链接,任何人都能访问这个链接下载分享的文件。

2)邮件分享:将文件的外链分享链接发到指定邮箱

3)指定分享:将文件分享给指定用户,只有指定的用户能查看和下载

4)部门共享:用户可将个人空间的文件分享(复制)到所在部门的空间

5)群组共享:用户可将个人空间的文件分享到任意一个所属群组的空间

6)我的分享:用户查看、编辑、删除所有的分享

7)我收到的分享:查看、删除其他用户通过指定分享方式分享的文件

5. 系统管理

管理员对系统的管理和维护,普通用户无法访问

1)用户管理:对用户的管理,包括用户的添加、删除、修改(设置部门、设置群组、修改空间大小信息)。

2)角色管理:添加系统角色、删除和修改角色,和用户是多对多关系

3)部门管理:部门的增、删、改、查,及设置部门管理员

4)群组管理:群组的增、删、改、查,及设置群组管理员

5)权限管理:用户属于多个角色,每个角色有多个权限,用户拥有的所有角色权限的集合就是用户的权限。采用的是以URL来定义权限,根据用户访问的URL来对用户的请求进行拦截

6)配置管理:系统的基本配置,如Hadoop  HDFSIP和端口

6. 其他小模块

回收站、通知、意见反馈、在线用户统计、访问统计等

3.1.2 性能需求

1. 设计需求

本系统是按照软件工程的要求设计的。采用以设计为中心的软件工程策略,实施严格的文档控制,以保证目标软件的可控性。利用Java的优点,构建出可扩展、更加安全、更加稳定的应用程序。

2. 软件维护性

由于采用MVC分层的设计思想,层与层之间都是通过按照接口定义来编写代码,各层的实例对象由Spring容器来创建和管理,层与层之间是低耦合的。

由于采用了Hibernate ORM框架,它处理对象与数据库表、对象的关系和表之间的关联关系的映射。操作对象就是操作表,不用关心表的创建和操作外键,不用写复杂的SQL语句,采用了Hibernate能通过简单的HQL语句实现复杂的查询。而且Hibernate支持几乎所有关系型数据库,MysqlSqlServerOracle等。

由于系统是Java开发的,因为Java是一门跨平台语言,所以可以在任意运行JVM的操作系统上部署服务器,不过最好要和HadoopLinux机器集群处在同一个网段,以提升系统性能。

3. 存储空间

企业级网盘后台管理系统使用Mysql数据库来存储数据信息,当然可随意切换使用其他数据库并不修改程序代码。

4. 可扩展性

随着系统的升级,新的功能会越来越多,数据的展现方式也会越来越丰富,因此要求系统必须有较高的可扩展性。系统采用了流行的SSH JavaWeb开发框架,能快速的进行新功能的开发,可满足高扩展性要求。

5. 易用性

系统前端采用Html+Css+Javascript+Jquery+Ajax等页面展现和异步交互技术,有良好的UI设计,根据用户的操作习惯进行设计。比如,在文件列表显示页面,对每一个文件条目右键,会弹出文件的操作,选择一个或多个文件后在文件列表的顶部也会显示对这些选中的文件的批量操作。

6. 可用性

1)界面统一,操作简单。

2)错误提示友好并能准确定位错误来源,方便纠正。

3)基于B/S架构开发,只要有浏览器就可访问

4)本系统还有对应的手机客户端,手机访问也很方便

5)系统在前端界面设计上非常友好,无刷新页面实现几乎全部功能,以Json格式数据交互,降低服务器出口带宽,占用用户较少的网速,给用户提供个性的服务,完美的体验。

7. 系统性能

1)系统是采用Java语言开发,应用了SpringHibernateStruts2等服务器端框架,在服务器端性能方面处于中上等。

2)相比传统的Servlet/JSP+JDBC的开发方式在性能上并比一定会弱,即使框架让系统变得笨重。因为各个框架都在发展进步,性能超越传统的技术架构很正常。

3Web应用服务器,即Tomcat运行服务器,在Tomcatjava虚拟机JVM配置上,最好把内存稍调大点,建议设置256M JVM运行内存。

4)数据库服务器,因为Hibernate支持多种数据库,所以常用的MysqlSqlServerOracle均可,最好和Web应用服务器在一个网段中,访问数据库通道畅通能提高Web服务器端的响应速度。

5Hadoop集群,应该和Web应用服务器最好在一个网段中,确保文件上传下载的速度。

 

 

4 总体设计

4.1 系统简介

企业级网盘后台是基于Web的应用程序,采用B/S系统架构。前后台以Json数据来交互。前台页面在用户的操作下产生数据用Ajax异步交互技术发送Json数据到后台,后台Java程序访问数据库或Hadoop文件系统,处理完后再返回结果Json给前台Javascript处理,处理后更新界面。在这种模式下,用户再使用时不需刷新整个界面而是由Javascript局部刷新页面,能用户良好的体验。现在用户计算机的性能逐渐提升,把一部分逻辑交给前台JS处理,服务器只返回较简单的Json数据。这样既可以减轻服务器的压力,又可以减少网络传输的数据量,利用了用户计算机的空闲的处理能力,在给用户良好体验的同时也大大提升了系统性能。。

4.1.1 系统架构

基于Hadoop的企业级网盘系统主要有个人文件管理、部门文件管理、群组文件管理、文件、权限管理、用户管理、角色管理、部门管理和群组管理。

4.1.2 系统功能框架

根据需求分析,基于Hadoop的企业级网盘系统后台的整体功能框架,如图4.1

4.1 系统框架层次图

4.1.3 文件管理

后台的文件管理模块是整个系统的重中之重,是所有模块的基础。

它接收由前台页面通过Ajax等技术POST过来的文件操作相关的Json数据,并进行处理,可能需要更新数据库或访问Hadoop文件系统,最后返回结果Json数据给前台页面,前台页面Javascript回调函数收到响应,解析并更新界面。

文件管理的用户是所有注册用户,通过此模块可以实现用户对文件的各种文件操作,上传、下载、移动、复制等。分为个人文件管理、部门文件管理、群组文件管理。

1. 文件操作

主要有文件的上传、下载、目录的创建、删除、重命名、移动、复制等。

列出目录Json数据

文本框: {"errorCode":"0","errorMessage":null,"result":[{"createTime":"2014-05-19 01:07:47","deletePath":"null","diskPath":"\/\/唯美.jpg","fileOwner":"annoy","fileOwnerId":"52","fileType":0,"folder":false,"id":195  ,"modifyTime":"2014-05-19 01:07:47","name":"唯美.jpg" ,"sharedId":"4cfe8c94-4ec7-48ee-bee8-e68d21a3fa32","size":359897 },……输入:目录路径,参数名path,如: {"path": "/"}

输出:当前登录用户的该Path对应目录下的所有目录和文件的Json数据。

文件上传

先将文件保存到Hadoop集群中,再更新数据库中用户的相应记录。

创建目录

输入:目录名,目录路径

             {"mkDirName":"mkDirName","path":"/" }

输出:操作结果

             {"errMsg":null,"errorCode":null,"ok":true}

重命名目录或文件

输入:目录或文件ID,新目录或文件名

输出:结果JSON

移动多个目录和文件

输入:以逗号拼接目录ID,文件ID,目标目录ID

输入:结果JSON

删除多个目录和文件

输入:以逗号拼接的目录ID,文件ID

输出:结果JSON

复制多个目录和文件、回收多个目录和文件、彻底删除多个目录和文件、还原多个目录和文件等。移动、复制、回收等操作都只是对数据库操作而言,改变了目录或文件的父目录ID

2. 个人、部门、群组文件管理

上述文件操作是个人文件管理、部门文件管理、群组文件管理的基础。系统设计为对每一个用户、每一个部门、每一个群组都有逻辑上的空间(总空间大小、已用空间大小、剩余空间大小),而每一个空间在DeptFolderGroupFolder表里都对应一个主目录记录。

用户对个人空间的操作即是对主目录的操作,可通过用户的主目录找到用户所有的目录和文件。

个人文件管理、部门文件管理、群组文件管理均有文件操作部分,其中部门和群组文件管理是以个人文件管理为模版,进行模式的复制来开发的。可以把一个部门或群组等效成一个用户,有很多代码能复用。

4.1.4 权限管理

1. 权限模型说明

       系统以URL来标识和定义权限,采用的权限模型为:用户->角色->权限。三个实体用户、角色、和权限。用户和角色属于多对多关系,角色和权限也是多对多关系,权限和权限本身是一对多的自关联。也就是说一个用户能有很多角色,一个角色也能有很多权限,权限有子权限和父权限。用户的权限就是用户拥有的角色的权限集合。拥有某权限则拥有该权限的子权限。

应用场景:权限模块的应用是在用户每次请求URL时对请求URL进行拦截,判断该URL是否在用户的权限中,如果不在则不能继续操作,在则通过权限的检查。

l      权限就是控制功能的使用(功能对应着URL)。

l      对功能的控制就是对URL的访问控制。

l      一个功能对应一个或两个URL

1. 例如列表或删除功能,只对应一个URL.

2. 例如添加或修改功能,对应两个URL..add, ..addUI

2. 权限操作

(1)    添加权限:将URL列入权限管理,默认不在权限表中的URL用户都拥有该权限。

(2)    修改、删除权限:取消对某URL的权限控制

(3)    设置权限:为角色设置权限,拥有莫权限则同时拥有它的子权限 

4.1.5 用户管理

用户管理模块的用户是管理员,通过此模块可以实现管理员添加新用户、修改用户所属角色、部门、群组,删除和初始化密码等。

1. 用户列表

管理员用,分页显示所有用户,由JSP页面输出

2. 添加用户

在该模块中管理员可以手动添加网盘用户。同时设置用户的角色和部门、群组,以及空间大小、上传类型、单文件上传大小限制等。

2. 修改用户

管理员对系统用户个人信息,姓名、邮箱、性别、手机号等基本信息和角色信息、所属部门、所属群组进行编辑修改。

3. 删除用户

管理员删除不用的账户,释放对应的系统空间

4. 用户注册

新用户注册,为其分配空间,设置默认角色,设置默认部门,设置默认群组等。

5. 用户登录

用户登录后将User对象放进Session中,设置用户在线状态为1,便于统计在线用户。

6. 注销用户

用户退出时更新用户在线状态,设置为0,表示不在线。

7. 在线用户

首先需要在用户的一个online属性,为0为离线1为在线。当Tomcat启动时初始化所有用户的在线状态,都设置为0,这是在ServletContextListener监听器来实现的。当用户登录后设置在线状态1,注销或session关闭,都会触发检查当前在线用户的方法

4.1.6 部门管理

企业中的部门经常共享文件,部门有部门的存储空间,部门的成员可以在该空间进行下文件操作。对于系统管理员,则能添加、修改、删除部门,也可设置部门管理员。部门的普通用户不能修改和删除部门空间里的文件,而部门管理员则拥有这些操作的权限。为部门设置管理员,方便部门间的文件共享,确保共享文件的安全,不能被随意删除修改。

1. 添加部门

接收前台传过来的部门名称,上级部门等参数,在数据库里添加一个部门记录,并初始化部门的空间,初始化部门的主目录,回收站目录等,添加的同时也能设置部门管理员,部门空间大小,空间使用情况。

2. 修改部门

对部门的基本信息和空间信息进行修改,设置管理员,设置空间大小,设置空间使用情况。

3. 删除部门

删除停止使用的部门,释放系统空间。如果该部门下有用户则不能删除该部门。

4.1.7 群组管理

群组的设计是为小型团队、项目组等提供文件共享功能,方便文件的交流,必须开发项目时的一些代码有时候需要共享,拷来拷去比较麻烦,能有一个公共的空间,大家都去使用这个空间就方便多了。

由此可见群组和部门不同,部门的空间文件只有管理员才可以进行修改和删除,而群组的是每一个用户权限相同,都拥有对群组空间操作的全部权限。这是实际生活中的需要。

1. 添加群组

普通用户和管理员均能添加群组,不过普通用户创建的群组有上线限制目前最大为3个,而管理员可随意创建群组。创建时,和部门、用户一样可附带设置空大小,空间使用情况,设置管理员等。

2. 修改群组

管理员对群组进行修改,包括空间大小的设置,已用空间大小、剩余空间大小的设置。

3. 删除部门

删除停止使用的群组,释放系统空间。群组下有用户则不能删除该群组。

4.1.8 系统管理

系统管理是设置系统基本配置信息,如Hadoop NameNodeIP和端口,站点名称,域名或IP设置等。

4.2 数据库设计

对于数据库设计,首先要整理系统中的数据,分析数据的来源和流向,通过分析,最终确定在计算机中要存储哪些信息,如何组织这些信息,需要几张怎么样的表,确定表内包含哪些字段,如何确定数据库的模式。

4.2.1 数据库

在此次设计中,因为使用了HibernateORM框架所以能使用各种关系型数据库,系统开发使用的是Mysql数据库,当然可轻松切换到其他数据库。

系统是基于Hadoop的,采用HadoopHbase非关系数据库来作为系统的数据库也是可以的。本文主要研究关系型数据库的设计,后面会单独介绍Hbase非关系型数据库的设计。

4.2.2 物理模型

       基于Hadoop的企业级网盘系统的主要数据库表物理模型如图4.2

 

4.2 数据库物理模型

4.2.3 数据库结构

1.关系模型

数据库的关系模型是从数据库表设计的逻辑层面上对系统E-R图进行的变换,在变换过程中根据E-R图向关系模型的转变规则,其中描述了表的主键和外键等数据库表设计关键性的属性,得到的结果如下。

用户(用户ID,密码,登录名,昵称,性别,部门ID,真实姓名,邮箱,电话,在线状态,描述,空间大小,已用空间大小,剩余空间大小)

角色(角色ID,角色名称,描述,空间大小,上传类型,上传大小限制)

用户-角色(用户ID,角色ID

权限(权限ID,路径,权限名称)

角色-权限(权限ID,角色ID

文件(文件ID,文件名,文件真实名称,文件路径,文件大小,存储位置,父目录ID,修改时间)

目录(目录ID,目录名称,目录节点,父目录ID,路径)

部门(部门ID,部门名称,父部门ID,空间大小,已用大小,剩余大小,部门描述)

群组(群组ID,群组名称,空间大小,已用大小,剩余大小,群组描述)

2.数据库关系表

基于Hadoop的企业级网盘系统的数据库关系表如下所示。

l         权限(hd_privilege)表如表4.1所示。

4.1 权限(hd_privilege)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

 

 

权限ID

2

name

varchar

255

       

权限名

3

url

varchar

255

       

权限路径

4

parentId

bigint

20

         

父权限ID

l         角色(hd_role)表如表4.2所示。

4.2 角色(hd_role)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

     

角色ID

2

name

varchar

20

       

角色名

3

description

varchar

255

       

角色描述

4

spaceSize

bigint

20

       

空间大小

5

uploadType

varchar

255

       

上传类型

6

uploadSizeLimit

bigint

20

       

上传限制

 

l         文件(hd_file)表如表4.3 所示。

4.3 文件(hd_file)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

 

文件编号

2

filename

varchar

255

0

     

文件名称

3

realName

varchar

255

0

     

真实名称

4

ext

varchar

255

0

     

后缀名

5

modiTime

datetime

         

修改时间

6

fileSize

bigint

20

0

     

文件大小

7

folderId

bigint

20

         

所在目录ID

8

fileContentType

varchar

255

         

文件类型

9

path

varchar

255

         

文件路径

l         目录(hd_folder)表如表4.4所示。

4.4 目录(hd_folder)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

 

目录编号

2

folderName

varchar

255

0

     

目录名称

3

node

int

11

0

     

节点

4

modiTime

datetime

         

修改时间

5

userId

bigint

20

0

     

用户ID

6

parentFolderId

bigint

20

0

     

父目录ID

7

path

varchar

255

         

目录路径

l         群组(hd_group)表如表4.5

4.5 群组(hd_group)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

 

群组编号

2

name

varchar

20

0

     

群组名称

3

description

varchar

255

0

     

群组描述

4

spaceSize

bigint

20

0

     

空间大小

5

usedSize

bigint

20

0

     

已用大小

6

remainingSize

bigint

20

         

剩余大小

7

createUserId

bigint

20

         

创建者ID

l         用户(hd_user)表如表4.6

4.6 用户(hd_user)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

 

用户编号

2

loginName

varchar

20

0

     

登录名

3

password

varchar

255

0

     

密码

4

email

varchar

20

0

     

邮箱

5

mobile

varchar

11

0

     

电话

6

nickName

varchar

20

         

昵称

7

status

varchar

255

         

状态

8

validateCode

varchar

255

         

验证码

9

description

varchar

255

         

用户描述

10

departmentId

bigint

20

         

所在部门号

11

name

varchar

255

         

真实姓名

12

gender

varchar

255

         

性别

13

online

int

11

         

在线状态

14

spaceSize

bigint

20

         

空间大小

15

usedSize

bigint

20

         

已用大小

16

remainingSize

bigint

20

         

剩余大小

17

uploadType

varchar

255

         

上传类型

18

UploadSizeLimit

bigint

20

         

上传限制

 

l         部门(hd_dept)表如表4.7所示。

4.7 部门(hd_dept)表

序号

列名

数据类型

长度

小数位

标识

主键

外键

允许空

说明

1

id

bigint

20

0

     

部门编号

2

name

varchar

255

0

     

部门名称

3

description

varchar

255

0

     

部门描述

4

parentId

bigint

20

0

     

父部门ID

5

spaceSize

bigint

20

0

     

空间大小

6

usedSize

bigint

20

0

     

已用大小

7

remaining

bigint

20

0

       

剩余大小

 

4.3 Hbase数据库设计

4.3.1 使用Hbase的优势

HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库.所谓非结构化数据存储就是说HBase是基于列的而不是基于行的模式,这样方便读写你的大数据内容。

HBase是介于Map Entry(key & value)DB Row之间的一种数据存储方式。就点有点类似于现在流行的Memcache,但不仅仅是简单的一个key对应一个 value,你很可能需要存储多个属性的数据结构,但没有传统数据库表中那么多的关联关系,这就是所谓的松散数据。

简单来说,你在HBase中的表创建的可以看做是一张很大的表,而这个表的属性可以根据需求去动态增加,在HBase中没有表与表之间关联查询。你只需要 告诉你的数据存储到Hbase的那个column families 就可以了,不需要指定它的具体类型:char,varchar,int,tinyint,text等等。但是你需要注意HBase中不包含事务此类的功能。

Apache HBase Google Bigtable 有非常相似的地方,一个数据行拥有一个可选择的键和任意数量的列。表是疏松的存储的,因此用户可以给行定义各种不同的列,对于这样的功能在大项目中非常实用,可以简化设计和升级的成本。

4.3.2 Hbase存储结构

HBase 是基于列的数据库,下面是关系型数据库和hbase数据库存储的对比。

行式存储,如图4.3,其特点如下:

1.        数据是按行存储的

2.        没有索引的查询使用大量I/O

3.        建立索引和物化视图需要花费大量时间和资源                                                                              

4.        面对查询的需求,数据库必须被大量膨胀才能满足性能要求

4.3 传统行式数据

列式存储,如图4.4,其特点如下:

1.        数据按列存储——每一列单独存放

2.        数据即是索引

3.        只访问查涉及的列——大量降低系统IO

4.         每一列由一个线索来处理——查询的并发处理

5.        数据类型一致,数据特征相似——高效压缩

4.4 列式数据库

 

4.3.3 Hbase与关系型数据库的对比

       Hbase是基于列的,传统关系型数据库是基于表格结构和行存储。下面是Hbase与关系型数据库RDBMS的对应关系,如表4.8

4.8 HbaseRDbms比较

 

HBase

RDBMS

数据类型

只有字符串

丰富的数据类型

数据操作

简单的增删改查

各种各种的函数,表连接

存储模式

基于列存储

基于表格结构行存储

数据保护

更新后旧版本仍会保留

替换

可伸缩性

轻易的进行增加节点,兼容性高

需要中间层,牺牲功能

                           

4.3.4 Hbase中表结构设计

       以传统关系数据库表的设计模式,设计Hbase中的表。需要对传统关系型数据库表的一对多,多对多关联关系做转换。

1)本系统中的FileFolder实体对应关系数据库中的两张表hd_filehd_folder,如图4.5

 

                            4.5 文件和目录的关系型数据库表物理模型

(2)Hbase中设计表,实现目录和文件的存储,即将上述FileFolder实体的关系型数据库表hd_filehd_folder转换为Hbase的非关系型基于列的表结构存储,一张表即可实现,表名使用File,表的每一行表示一个文件或目录,如表4.10

4.10 Hbase中目录和文件表设计

File

行键row

列族Column families

 

Info

Parent

child

<file_id>

Info:fileName

Info:modiTime

Info:path

Info:node

Info:fileTypr

Parent:<file_id>

Child:<file_id>

1

Info:fileName=根目录

Info:modiTime=2014/5/22

Info:path=/

Info:node=0

Info:fileTypr=folder

 

Child:2=folder

Child:3=folder

Child:4=file

2

Info:fileName=文档

Info:modiTime=2014/5/22

Info:path=/文档

Info:node=1

Info:fileTypr=folder

Parent:1=folder

Child:3=file

3

Info:fileName=软件

Info:modiTime=2014/5/22

Info:path=/软件

Info:node=1

Info:fileTypr=folder

Parent:1=folder

 

4

Info:fileName=QQ.exe

Info:modiTime=2014/5/22

Info:path= /QQ.exe

Info:node=2

Info:fileTypr=file

Parent:1=folder

 

5

Info:fileName=毕业设计论文.doc

Info:modiTime=2014/5/22

Info:path=/文档/毕业设计论文.doc

Info:node=2

Info:fileTypr=file

Parent:2=folder

 


      

 

5 详细设计和实现

5.1 系统的开发环境

1)开发工具:Myecplise8.5以上

2)开发语言:Java

3)框架技术:SpringStruts2HibernateHadoop

4)数据库:Mysql

5)应用服务器:Tomcat6以上

6)数据存储服务器:Hadoop分布式Linux集群

5.2 类设计

在系统详细设计中类设计是最重要的模型图设计,类是相似对象的共同属性和行为的抽象。通过类设计将会具体实现总体设计中的领域模型,同时也对时序图中系统的行为进行了封装,还封装了数据库支持类,该类用来与数据库数据进行沟通。这样通过详细设计过程对总体设计的模型进行了具体实现。在系统总体设计中详细分析了企业级网盘系统采用的架构等,用结构设计详细描述了系统。在类的设计中,利用这些结构的特点,结合该系统类的设计,形成的MVC架构的项目三层类设计如下(此处只将重要的类描述):

1. 实体层

该层中实现的类有:FileFloderRolePrivilegeUserShareDepartmentGroup等。其构造如图5.1所示:

5.1 实体层

2. 数据访问层(DAO

该层采用Java泛型,定义了公共的Dao的接口DaoSupport<T>,如图5.2,并实现了该接口DaoSupportImpl<T>,如图5.3

              5.2 DaoSupport                    5.3 DaoSupportImpl

 

DaoSupportImpl实现了对整个系统中对象的CRUD操作,并抽取了接口DaoSupport供业务逻辑Service层实现,Service层在实现接口的同时要继承DaoSuportImpl,并提供泛型的实例,即要操作的实体对象,即可复用DaoSupportImplCRUD方法。

2.业务逻辑层(Service

该层是包含整个系统核心业务逻辑,接口如图5.4,接口的实现如图5.5

 

 

 

 

 

 

 

 

 

 

          5.4 Service层接口                                    5.5 Service层实现类

3. 控制层(Action

该层中实现的包有:admindeptgrouploginshare

该层用来处理前端的数据请求,经由上述Service处理完成后,返回Json数据。该层定义了一个BaseAction<T>,它是Struts所有Action的基类。BaseAction实现 StrutsmodelDriven接口,所谓ModelDriven,意思是直接把实体类当成页面数据的收集对象。该类通过泛型的方式传入实体,然后再通过反射机制获取该类型的实例:

通过反射获取model的真实类型:

ParameterizedType pt = (ParameterizedType)  this.getClass().getGenericSuperclass();

Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0];

通过反射创建model的实例:

model = clazz.newInstance();

比如,用户操作UserAction的类定义为:

Public class UserAction extends BaseAction<User>{......}

这样前端在传参数时可直接使用User实体中的属性名,不用在Action中再定义很多属性接收POST过来的数据,也省去了再定义一个实体User通过user.loginName的形式传值的麻烦。

5.3 系统模块实现

5.3.1 文件管理模块实现

         用户、目录、文件的UML模型图如图5.6

      

                                          5.6 用户.目录–文件 UML模型图

1. 相关实体设计

(1)    表示目录的实体Folder,对应数据库表hd_folder

       其中:id对应数据库表中的主键字段,目录的Id在所有用户的目录中是唯一的。

       folderName:目录名

       node:目录的层次深度,根目录为0,根目录下的目录为1,以此类推

       modiTime:目录的创建或修改时间

       path:目录相对个人空间的路径,如根目录为“/”,根目录下的目录为“/图片”

       oldFolderId:被删除后记录原始父目录,以便从回收站还原

       oldPath:被删除后的记录原始目录路径,用于从回收站还原时的目录path的还原

       user:与实体User的多对以关联关系

       parentFolder:父目录,自关联,多对以关系

       childFolders:目录的子目录,自关联,一对多关系

       files:与实体File的一多多关联关系,

       2)表示文件的实体File,对应数据库表hd_file

其中:Id对应数据库表记录中的主键字段,在所有用户的文件中Id是唯一的。

       fileName:文件名

       path:文件的真实路径

       modiTime:文件的上传时间

       fileSize:文件的大小

       oldFolderId:文件的旧父目录,被删除后还原使用

       foler:文件的所属目录,与实体Folder的多对一关联关系

2. Hibernate中实体与数据库表的关联关系映射配置

1)目录实体Folder与数据库表hd_folder的映射配置

              user属性:与User的多对一

文本框: <many-to-one name="user" class="User" column="userId" lazy="false"> </many-to-one>              files属性:与文件的一对多

文本框: <set name="files" cascade="all" order-by="id ASC" >     <key column="folderId"></key><one-to-many class="File"/></set>              parentFolder属性:多对一自关联

文本框:  <many-to-one name="parentFolder" class="Folder"  lazy="false"     column="parentFolderId">     </many-to-one>

              childFolders属性:一对多自关联

文本框:  <set name="childFolders" cascade="all" order-by="id ASC" >     <key column="parentFolderId"></key><one-to-many class="Folder"/></set>

2)文件实体File与数据库表hd_file的映射配置

folder属性:文件所属目录,与Folder的多对一

文本框: <many-to-one name="folder" class="Folder" column="folderId" lazy="false" ></many-to-one>

3. 获取用户指定目录Json数据

用户登录后,默认进入的是个人文件管理,前台html页面加载完成后由Javascript Ajax异步向后台请求根目录的数据。首次打开网站首页会获取用户根目录的Json数据,当用户点击目录名则又向后台请求所点击的目录的Json数据。所以需要一个业务方法,用来产生指定用户指定目录的Json

1)用一个JavaBean来描述一个目录或文件,这个bean定义为:

文本框: Public class FileVo{ private Date createTime = new Date(); private String fileOwner; private boolean folder; private Date modifyTime = new Date(); private String name; private Long size; private Long  id; private String  deletePath; }

2)用一个FileVoList集合来定义一个目录下的文件和子目录信息:

3)用一个JsonBean 包装List<FileVo>,这个JsonBean需要有errorCodeerrorMessage属性,因为前台Javascript再收到这个JsonBean后会根据这errorCode值给判断用户的操作是否成功,若失败则根据errorMessage给用户提示,这个JsonBean定义如下:

文本框: public class FileVOJson { private String errorCode; private String errorMessage; private List<FileVO> result;  //getters setters }

 

 

 

 

 

 

返回目录Json数据如下:

 

 

 

文本框: {"errorCode":"0","errorMessage":null,"result":[{"createTime":"2014-05-19 01:07:47","deletePath":"null","diskPath":"\/\/唯美.jpg","fileOwner":"annoy","fileOwnerId":"52","fileType":0,"folder":false,"id":195  ,"modifyTime":"2014-05-19 01:07:47","name":"唯美.jpg" ,"sharedId":"4cfe8c94-4ec7-48ee-bee8-e68d21a3fa32","size":359897 },……]}

4. Struts2文件上传

使用Struts实现文件上传是非常简单的而且方便。

 首先,需要导入包commons-fileupload-1.2.1.jarcommons-io-1.3.2.jar,然在Action类中,这里需要接收文件(File类型),文件名,文件类型,文件名必须和表单里面的name属性名一致,然后文件名的写法是 文件名+FileName,然后文件类型名称的写法是文件名+ContentType,分别把他们设置成属性,就是分别为他们提供setget方法。接着需要把接受到的File文件转存到服务器的目录里,否则它就存放在Struts的临时目录里面,在Action执行完毕后会被删除。

5. 将文件转存到Hadoop

Struts2的文件上传是通过拦截器实现的,当文件通过Http上传完毕后会执行Action中的方法,此时需要将这个临时的文件通过IO流的操作,使用HadoopApi存储到HDFS分布式文件系统中。

fileInputStreamstruts2接受到的文件的输入流

Path:文件存储到Hadoop文件系统的路径,相对与HDFS根目录

文本框: public String createGroupFile(FileInputStream fileInputStream) throws Exception { String path = "/group/"+UUID.randomUUID(); Path hdfsPath =new Path( path); FSDataOutputStream out = getFs().create(hdfsPath); IOUtils.copyBytes(fileInputStream,out,HdfsUtils.getConfiguration()); return path; } 通过HadoopFileSyatem类的create方法创建一个文件,同时拿到这个文件的输出流,再通过UIUtils流工具类的copyBytes方法将从strutsAction中获取到的用户上传文件的输入流和这个输出流对接,即可将文件转存到Hadoop集群的分布式文件系统HDFS中。

6. 用户上传的文件索引信息更新到数据库

然后,就需要更新数据库,为用户上传的文件添加一个记录,并更新用户的空间使用情况

文本框: File file = new File(); file.setExt(uploadFileFileName.substring(uploadFileFileName.lastIndexOf('.') + 1, uploadFileFileName.length())); file.setFileContentType(uploadFileContentType); file.setFileName(uploadFileFileName); file.setFileSize(uploadFile.length()); file.setPath(path); file.setFolder(folder); fileService.save(file); user.setUsedSize(user.getUsedSize()+uploadFile.length()); user.setRemainingSize(user.getSpaceSize()-user.getUsedSize()); userService.update(user);

其中,fileServiceuserService分别是实体文件File和实体用户User的业务逻辑的实现类的实例对象。

7. 目录或文件的移动

目录在实体设计上关联的有自己的父目录,文件也有自己的父目录。因此,文件和目录的移动只是把文件或目录的父目录设置成移动到的目录就实现了目录和文件的移动。

文本框:  public void moveFiles(Long[] fileIds, Long descFolderId) { File file =  null; Folder descFolder = (Folder) getSession().createQuery("FROM Folder f where f.id=?").setParameter(0, descFolderId).uniqueResult(); for(int i =0;i<fileIds.length;i++){ file =  getById(fileIds[i]); file.setFolder(descFolder); } } 这样做只更新了数据库中的目录和文件父目录的外键引用,并没有涉及到Hadoop文件系统中的文件移动操作。这样做确实是可行的,因为文件的实体File里定义的有文件在Hadoop中的真实文件路径,只要凭这个路径就能找到这个文件,而在文件移动的时候并不会改变这个路径。这样也是合情合理的,只改变数据库中的外键引用而不改变文件在Hadoop中的存储位置,在减轻Hadoop集群服务器压力的同时也能给用户较快的响应速度。文件的移动Service方法如下:

该方法实现了将多个指定idfileIds)的文件移动到指定iddescFolderId)的目录中,目录的移动与之类似。

8. 递归实现目录或文件的复制

和移动类似,相似的是复制到目标目录跟移动一样做为要复制的目录和文件的父目录,不通的是,要把要复制的目录和文件在数据库中生成一份新的目录和文件记录,然后把新生成的目录和文件的父目录设置成要复制到的目录。

在复制目录的时候,考虑到目录都可能有子目录,在复制一个目录的同时它的子目录也应该被复制过去,我采用的是递归实现的。

而对于目录下的子文件的复制就简单多了,在递归调用前进行目录子文件的复制操作。下面以目录的复制为例说明:

文本框: private void copyFolder(Folder f, Folder folder) { Folder nf = new Folder(); nf.set….. //复制当前的目录 save(nf); if(f.getFiles().size()>0){ Iterator<File>it = f.getFiles().iterator(); while(it.hasNext()){ File f2 = it.next(); File f1 = new File(); f1.set…. //递归调用前复制当前目录的子文件 fileService.save(f1); //更新用户空间使用情况 } } if(f.getChildFolders().size()>0){ Iterator<Folder>it = f.getChildFolders().iterator(); while(it.hasNext()){ copyFolder(it.next(),nf); //对当前目录的每一个子目录递归调用复制 } } }

 

9. Hadoop HDFS分布式文件系统中下载文件

1)编写Struts2的文件下载Action

2)在Struts.xml中配置文件下载Result

文本框:  <result name="success" type="stream">    <param name="contentType">application/octet-stream;charsetUTF-8</param><param name="inputName">inputStream</param><param name="contentDisposition">attachment;filename="${downFileName}"</param><param name="bufferSize">4096</param><param name="contentLength">${fileLength}</param></result>

此处的下载不通与下面介绍的文件共享的下载,通过这个Action用户只能下载自己的文件,不允许下载其他用户的文件,这在Action里都要检查用户是不是这个文件的主人。

文本框: if(getCurrentUser().getId().intValue()!=file.getFolder().getUser().getId().intValue()){ //throw new RuntimeException("非法操作,只能操作自己的文件"); } 3)从Hadoop中获取文件输入流

文本框:  public InputStream downloadFile(String path) throws Exception { FSDataInputStream out = null; Path hdfsPath =new Path( path); try { out = getFs().open(hdfsPath); } catch (IOException e) { e.printStackTrace(); throw new HDFSException("HDFS异常", e); } return out; }

 

通过设置HTTP内容类型contentTypeapplication/octet-stream,将该输入流和经由文件下载Action返回,浏览器就会知道要下载文件,文件是一点一点从Hadoop HDFS文件系统中通过HTTP协议流向用户的浏览器。

5.3.2权限管理模块实现

系统以URL来标识和定义权限,采用的权限模型为:用户->角色->权限。三个实体用户、角色、和权限。用户和角色属于多对多关系,角色和权限也是多对多关系,权限和权限本身是一对多的自关联。也就是说一个用户能有很多角色,一个角色也能有很多权限,权限有子权限和父权限。用户的权限就是用户拥有的角色的权限集合。拥有某权限则拥有该权限的子权限。

应用场景:权限模块的应用是在用户每次请求URL时对请求URL进行拦截,判断该URL是否在用户的权限中,如果不在则不能继续操作,在则通过权限的检查。权限模块的UML类图如图5.7

5.7 权限管理UML模型图

1.      相关实体的说明

1)实体权限Privilege,对应数据库表hd_privilege

Id:主键

Name:权限的名字

url:权限的访问地址,相对于应用访问的根目录,代表一个权限

roles:拥有这个权限的角色,与实体角色Role的多对多关联关系           

parent:自关联属性,表示权限的父级权限,role拥有一个权限就同时拥有它的所有下级权限

chrildren:与自身的一对多自关联,包含所有子权限的集合,与parent对应

实体角色的说明

Id:主键

Name:角色名

Descroiption;角色描述

Users:属于该角色的所有用户集合,与User的多对多关联关系

Privileges:该角色拥有的所有权限集合,与实体权限Privilege的多对多

2.      Hibernate 多对多的关联关系映射

用户User和角色RoleRole和权限Privilege均是多对多的关系。

先从数据库表的方面来考虑,多对多关系要使用中间表。对于UserRole,中间表名为hd_user_role,对于RolePrivilege,中间表为hd_role_privilege。用户和角色中间表hd_user_role中字段为两个外键userIdroleId,分别指向用户和角色的id。角色和权限中间表hd_role_privilege中字段为两个外键roleIdprivilegeId,分享指向角色和权限的id

从对象关系映射的方面来考虑,在Hibernate中是需要在两个多对多关联关系的实体中分别定义元素为对方的集合。Privilege映射文件部分定义如下:

文本框:  <set name="roles" table="hd_role_privilege"  > <key column="privilegeId"></key><many-to-many class="Role" column="roldId"></many-to-many></set><many-to-one name="parent" class="Privilege" column="parentId" ></many-to-one ><set name="children" lazy="false" order-by="order_ ASC" cascade="all" ><key column="parentId"></key><one-to-many class="Privilege" ></one-to-many></set>

3. 权限分类说明

系统中权限分为三类:

1)登陆功能,未登录可以使用

2)要控制的功能,需要登陆用户,并且有相应权限才可以使用。例如:上传文件,管理员删除用户的呢过。

3)不需要控制的功能,只要登陆就可以使用,不需要进行控制。例如:注销、使用主页等。三类权限关系如图5.8所示:

 


      
  
   
     
   
     

 


 

 

 

 

 


   

5.8 权限分类说明

4. 确定并分配权限

权限定义在程序开发完成后应该是确定的,这个时候整个系统有哪些url可以访问,哪些需要控制都可以确定了。比如系统后台管理中心只能是管理员才能访问,这就需要将后台的访问URL加如权限表里,并为管理员用角色分配这些权限。如果要对普通用户进行权限控制,则需要对普通用户的角色分配权限。这样就可以针对系统的不同角色分配不同的权限,为系统实现权限控制做好了准备,接下来就要通过Struts的拦截器来使用权限,对用户的URL访问实施控制。

5.      使用权限,通过拦截器实现权限拦截

权限管理模块对URL实施拦截的示意图如图5.9

5.9  权限拦截示意图

文本框: public String intercept(ActionInvocation invocation) throws Exception { ………… if (user == null) return "login";//未登录跳转到登录 if (user.hasPrivilegeByUrl(privUrl)) { // 如果已登 录,就判断权限 return invocation.invoke();// 如果有权限,就放行 } else { return "noPrivilegeError";// 如果没有权限,就转到提示页面 } } } Struts中的Action应用权限拦截器后,对用户的每一个URL请求都进行拦截,拦截后检查权限,即判断用户当前访问的URL有没有在用户拥有的所有角色的权限集合中,如果在则有权限访问该URL,不做任何操作,放行用户,否则反回用户无权限的错误提示,并结束用户的此次请求。

5.3.3文件共享模块实现

1.      基于Hadoop的企业网盘文件共享分为以下五类

五类共享设置如图5.10

5.10设置共享图

 

(1)        外链分享

顾名思义,外链分享就是给用户的某个文件提供一个对外公开的链接,供别人下载。主要问题就是怎么生成链接,本系统使用的策略是为每个文件生成一个唯一的提取码code,利用这个code在加上系统对外的公开的提起文件Action地址即可生成外链地址。文件提取码code的生成是通过UUID(通用唯一识别码 Universally Unique Identifier)来生成的,不会有重复,也不容易被盗用,因为32位随机字母下划线根本不可能记住。外链下载如图5.11所示:    

                                                5.11外链下载图

2)邮件分享

其实也是外链分享,还需要的就是要把外链地址发到指定邮箱中。使用javax.mail包下的API通过smtp协议来发送邮件。

3)指定用户分享

同样是需要产生外链地址,因为是指定分享所以通过这种方式分享的文件不能同外链分享一样能被任意用户查看和下载。与外链分享不同的是,将文件分享给指定用户后,该用户只有登录后,而且外链分享的对象是该用户该用户才能查看和下载分享。

4)部门分享     

用户有个人空间,部门有部门空间,部门的共享是通过用户将自己个人空间的文件复制到部门空间来实现的。只有管理员能删除和移动等操作,普通部门成员只能查看和下载。

5)群组分享

和部门分享类似,群组分享是通过用户将自己个人空间的文件复制到群组空间来实现的,但在权限方面较部门基本没什么限制,因为群组共享设计的初衷是为方便一个项目组、团队的诸如代码分享等需求的。         

2.      分享实体Share的设计与其他实体的关联关系

1)分享实体Share,对应数据库表hd_share

文本框: public class Share { //基本属性  private Long id; private String name; private Integer isFolder  = 0; private String type = "外链分享";//指定分享 private Date startTime = new Date(); private Date endTime; private String password; private String limits  = "1111"; private Set<Email> emails; private Long downloadCount = 0l; //提取码 private String code; //指定分享 private User fromUser; private User toUser; //关联实体 private File file; private Folder folder; //geters setters…… }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

其中,fromUsertoUser属性都关联这用户实体User,分别表示分享的发起人,和分享的接收者(指定分享时有效)。

filefolder 分别关联着文件实体和目录实体Folder,如果分享的是文件则folder值为null ,isFolder 值为false,如果分享的是目录,isFolder值为truefilenullfolder不为null

Code属性为在用户点击分享时使用UUID生成的唯一文件提取码。

此外,分享还包含分享时间startTime,分享密码password,如果是邮件分享还会有emails,它关联着一个简单的实体Email

2)相关表物理模型图,如图5.12

         5.12 数据库物理模型分享相关

3. 查看分享模块设计

用户可以查看自己的所有分享,并能取消分享即删除分享记录。考虑到实体分享Share的设计关联复杂,不便于输入转换为Json数据直接输出,所以自定义了ShareJson类,其属性主要有:

boolPassword:是否需要密码

fileType0是目录,1是文件

shareId:即UUID生成的文件提取码

sharedType:分享类型,01分别表示指定分享,外链分享和邮件分享

userId:分享人,分享发出者

fileSzie文件大小,visitCount下载数量,fileName文件名等。

文本框: public class ShareJson { private Long fileType;//0 folder 1 file private Long fileSize; private String fileName; private Date createDate;  private String path; private Long userId; private String sharedId;//code private Long sharedType; //0 1 2  appoint link email private boolean boolPassword; private String visitCount;//downloadcount private String name; private Set<Email> emails; }

 

 

 

 

 

 

 

 

 

 

             

然后需要一个分享实体ShareShareJson转化的工具类,通过shareService业务操作从数据库中查找fromUser的某个用户的分享,这是个List<Share>集合,通过转化工具类将这个List<Share>集合转化成List<ShareJson>集合,再经由StrutsAction将这个List<ShareJson> 转化为Json数组,返回给前台Javascript代码处理,根据收到的返回json数据,解析,更新界面,将数据展现给用户。

 

 

 

 

 

 

 

 

 

 

 

 

 

6 系统测试

6.1软件测试定义

软件测试就是利用测试工具按照测试方案和流程对产品进行功能和性能测试,甚至根据需要编写不同的测试工具,设计和维护测试系统,对测试方案可能出现的问题进行分析和评估。执行测试用例后,需要跟踪故障,以确保开发的产品适合需求。

软件测试就是在软件投入运行前,对软件需求分析、设计规格说明和编码实现的最终审查,它是软件质量保证的关键步骤。

6.2软件测试目的

测试是程序的执行过程,目的在于发现错误;不能证明程序的正确性,除非仅处理有限种情况。检查系统是否满足需求也是测试的期望目标。一个好的测试用例在于发现还未曾发现的错误;一次成功的测试则是发现了错误的测试。

6.3软件测试方法

软件测试技术按照不同的划分方法,有不同的分类:静态测试、动态测试;黑盒测试、白盒测试;单元测试、集成测试、回归测试、系统测试、验证测试以及确认测试。

6.4功能模块测试

6.4.1文件上传功能测试

1)点击上传按钮弹出选择文件对话框,选择文件Debug.rar。如图6.1

 

6.1 选择上传文件

 

       2)选择的文件要符合用户可上传的类型规定,不能超过用户可上传的单文件大小限制,文件选择对话框一关闭就开始上传了,上传过程中有文件总大小、已上传大小、当前上传速度、剩余时间以及上传进去百分比等提示信息。如图6.2

                                                        6.2 正在上传中

     3)上传完成后,去掉上传状态信息显示,提示上传成功,如图6.3

6.3 上传完成

6.4.2文件下载功能测试

1)右击文件列表里的文件,在弹出的菜单中间选择下载,当然还有其他当时点击下载。如图6.46.5

6.4 点击下载

6.5 成功下载

6.4.3文件其他操作测试

对文件的其他操作,目录或文件的重命名、移动、删除、复制等,

1)目录或文件的重命名,如图6.66.7

6.6 目录重命名

6.7 重命名成功

2目录或文件的删除,可以删除单个文件或目录,也可以批量删除文件和目录,通过CheckBox标签来得到用户选择的文件和目录,如图6.86.9

6.8确定删除对话框

6.9删除成功

3目录或文件的复制和移动,当用户选择复制到或移动到时会弹出一个窗口显示用户的目录树,用户选择要复制到或移动到的目录后点击即可,如图6.10

 

6.109 移动文件

6.4.4文件共享功能测试

       1选择一个文件,分享,群组分享,选择一个群组目录,如图6.11

6.11 群组共享

2)外连分享,选择一个文件点击分享,弹出分享窗口,点击创建外链分享就为该文件或目录创建了一个对外公开访问的外链,如图6.12

6.12外链分享

(3)外链分享查看,在浏览器中输入外链地址打开后,可以下载和保存到自己网盘空间,如果有密码下载会验证密码,如图6.13

                                                       图6.13 外链分享查看

 

 

 

       4)点击左侧导航我分享的文件,可以查看和管理用户分享的所有文件,为外链分享设置密码等,如图6.14

6.14 我分享的文件

5)点击左侧导航我收到的文件,可以查看其他用户分享给我的文件,如图6.15

6.15我收到的文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7 总结

在经过了这么长时间的努力后,本人已基本完成了基于Hadoop的企业级网盘后台管理系统的基本功能,但仍有很多不足,有一些功能需要改进和进一步完善。

在过去的四年里,学习了很多的课程及编程语言,虽然通过学习对这些课程有所了解和掌握,但是始终处于理论知识的掌握阶段,并没有真正应用于实践设计和开发,所以对知识的掌握还不够全面和熟练。通过本次毕业设计系统开发不仅把课本上学到的知识得到了运用,而且学习了很多课堂上学不到了实践经验。

在毕业设计的过程中遇到很多难题,在解决问题的时候和同学一起商讨方案,通过网络资源、图书资源和指导老师等途径来共同解决问题。每次解决一个难题,那种说不出来的喜悦更带动我努力来完成每一个功能,并且不断完善,不断的调试,更加锻炼了我的耐心和毅力,只有自己不怕困难,用于对待,成功才会向你招手。

本次毕业设计是对大学四年理论知识的一个综合运用,将我们学习到的理论知识用到实际的开发项目中,对我来说是一次能力的真正提高的过程,对我以后的工作提供了一个重要并良好的开端,并将有助我在工作中的实际开发。


参考文献

[1] 王少亚.Hadoop在企业中的应用现状分析[J].商场现代化,201318

[2] 曹英忠.基于Hadoop的云存储实践[J].现在计算机,201110

[3] 周洪波.云计算:技术、应用、标准和商业模式[M].北京:电子工业出版社,2011

[4] Tom White.Hadoop权威指南[M](2).北京:清华大学出版社,2011

[5] 李刚.疯狂讲义之轻量级Java开发Java+Struts+Spring+Hibernate[M].北京:电子工业出版社,201310

[6] 余志龙.改编 GoogleAndroidSDK开发范例大全[M].北京:人民邮电出版社,2010

[7] 郭宏志.Android应用开发详解[M].北京:电子工业出版社,20106

[8] 孙福权,张达伟,程勖,刘超.基于Hadoop企业私有云存储平台的构建[J]. 辽宁工程技术大学学报,201112

[9] 王峰,雷葆华.Hadoop分布式文件系统的模型分析[R].中国电信股份有限公司北京研究院,201011

[10] Konstantin Shvachko, Hairong Kuang, Sanjay Radia, Robert Chansler.(2010).The Hadoop Distributed File System[R]. Yahoo!Sunnyvale,  CaliforniaUSA

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

致谢

感谢裴斐老师的热情指导,感谢高宁和张俊杰,整个系统在开发过程中,他们几个一直陪伴着我,大家一起交流、一起讨论问题。不仅让我切身体会到只有团队才是更强,而且在他们身上还学到了很多东西。

感谢这四年来教过我的和那些为教育事业奋斗的老师们。

感谢全班同学这四年来对我的支持和帮助,在这个大家庭里,我们一起上课,学习,一起娱乐,这些一切都令我终生难忘。

感谢本寝室全体人员四年来的照顾和帮助,这四年的欢声笑语是永远的美好回忆。

最后感谢父母多年来在学业和生活上给予我的物质帮助,感谢所有支持过我的人你们的关心和鼓励使我在工作和学习中不断进取。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

附录A: 主要源程序

基于Hadoop的企业级网盘系统后台的源程序

1. SSH框架的配置

l           struts配置文件中的配置如下:

<?xml   version="1.0" encoding="UTF-8" ?>

<!DOCTYPE   struts PUBLIC

    "-//Apache Software Foundation//DTD   Struts Configuration 2.1.7//EN"

    "http://struts.apache.org/dtds/struts-2.1.7.dtd">

 

<struts>

       <constant   name="struts.multipart.maxSize"   value="1000000000"></constant>

        <constant   name="struts.i18n.encoding"   value="UTF-8"></constant>

       <!-- 配置为开发模式 -->

    <constant   name="struts.devMode" value="true" />

    <!-- 把扩展名配置为action -->

    <!-- 把主题配置为simple -->

    <constant   name="struts.ui.theme" value="simple" />

   

       <package name="haodisk"

              extends="struts-default,json-default">

                     <interceptors>

                     <!-- 自定义拦截器,用于登陆检查 -->

                     <interceptor   name="checkPrivilege"></interceptor>

                     <!-- 注册拦截器栈,包含登陆检查拦截器, Struts2默认的拦截器  -->

                     <interceptor-stack   name="myStack">

                            <interceptor-ref   name="checkPrivilege"></interceptor-ref>

                            <interceptor-ref   name="defaultStack"> </interceptor-ref>

                     </interceptor-stack>

              </interceptors>

              <!-- 通用的Result,当前包下的Action都能用 -->

              <global-results>

                     <result   name="login"

                            type="redirectAction">

                            <param   name="namespace">/user</param>

                            <param   name="actionName">toLogin</param>

                     </result>

                     <result   name="adminLogin">/WEB-INF/jsp/userAction/loginUI.jsp</result>

                     <result   name="registerUI">/WEB-INF/jsp/userAction/registerUI.jsp</result>

                     <result   name="noPrivilegeError">/noPrivilegeError.jsp</result>

                     <result   name="activate"

                            type="redirectAction">

                            <param   name="namespace">/user</param>

                            <param   name="actionName">activate</param>

                     </result>

              </global-results>

              <action   name="install">

                     <result   name="json" type="json">

                            <param   name="root">json</param>

                     </result>

              </action>

       </package>

        

    <!-- 后台管理 -->

   <package name="admin"   namespace="/admin" extends="haodisk">

              <!-- 首页 -->

              <action   name="home_*"   method="{1}">

                     <result   name="{1}">/WEB-INF/jsp/adminHomeAction/{1}.jsp</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

             

              <!-- 角色管理 -->

              <action   name="role_*"   method="{1}">

                     <result   name="list">/WEB-INF/jsp/roleAction/list.jsp</result>

                     <result   name="saveUI">/WEB-INF/jsp/roleAction/saveUI.jsp</result>

                     <result   name="setPrivilegeUI">/WEB-INF/jsp/roleAction/setPrivilegeUI.jsp</result>

                     <result   name="toList"   type="redirectAction">role_list</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

             

              <!-- 群组管理 -->

              <action   name="group_*"   method="{1}">

                     <result   name="list">/WEB-INF/jsp/groupAction/list.jsp</result>

                     <result   name="saveUI">/WEB-INF/jsp/groupAction/saveUI.jsp</result>

                     <result   name="toList" type="redirectAction">group_list</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

 

              <!-- 部门管理 -->

              <action   name="dept_*"   method="{1}">

                     <result   name="list">/WEB-INF/jsp/departmentAction/list.jsp</result>

                     <result   name="saveUI">/WEB-INF/jsp/departmentAction/saveUI.jsp</result>

                     <result   name="toList"   type="redirectAction">dept_list?parentId=${parentId}</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

             

             

              <!-- 用户管理 -->

              <action   name="user_*"   method="{1}">

                     <result   name="list">/WEB-INF/jsp/userAction/list.jsp</result>

                     <result   name="saveUI">/WEB-INF/jsp/userAction/saveUI.jsp</result>

                     <result   name="toList"   type="redirectAction">user_list</result>

                     <result   name="logout">/WEB-INF/jsp/userAction/logout.jsp</result>

                     <result   name="viewOnlineUser">/WEB-INF/jsp/userAction/viewOnlineUser.jsp</result>

                     <result   name="toAdminIndex"   type="redirectAction">home_index</result>

                     <result   name="toIndex" type="redirectAction">

                            <param   name="actionName">home_index</param>

                            <param   name="namespace">/user</param>

                     </result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

             

              <action   name="user_register"   method="register">

                     <result   name="regSuccess">/WEB-INF/jsp/userAction/regSuccess.jsp</result>

                     <result   name="regFail">/WEB-INF/jsp/userAction/regFail.jsp</result>

                     <result   name="invalid.token">/WEB-INF/jsp/userAction/error.jsp</result>  

                     <interceptor-ref   name="myStack"></interceptor-ref>

                     <interceptor-ref   name="token" />

              </action>

             

              <!-- 权限管理 -->

              <action   name="privilege_*"   method="{1}">

                     <result   name="list">/WEB-INF/jsp/privilegeAction/list.jsp</result>

                     <result   name="addUI">/WEB-INF/jsp/privilegeAction/addUI.jsp</result>

                     <result   name="editUI">/WEB-INF/jsp/privilegeAction/editUI.jsp</result>

                     <result   name="result">/WEB-INF/jsp/privilegeAction/result.jsp</result>

                     <result   name="toList"   type="redirectAction">privilege_list</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

             

              <!-- 系统配置 -->

              <action   name="sys_*" method="{1}">

                     <result   name="configUI">/WEB-INF/jsp/sysAction/configUI.jsp</result>

                     <result   name="info">/WEB-INF/jsp/sysAction/info.jsp</result>

                     <result   name="dfs">/WEB-INF/jsp/sysAction/dfs.jsp</result>

                     <result   name="result">/WEB-INF/jsp/sysAction/result.jsp</result>

                     <interceptor-ref   name="myStack"></interceptor-ref>

              </action>

                  </package>

       <include   file="struts-uspace.xml"></include>

       <include   file="struts-user.xml"></include>

    <!-- Add packages here -->

</struts>

l           spring配置文件中的配置如下:

<?xml version="1.0" encoding="UTF-8"?>

<beans   xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

                            http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-2.5.xsd

                            http://www.springframework.org/schema/tx   http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

       <!-- 自动扫描与装配bean -->

       <context:component-scan   base-package="com.haodisk"></context:component-scan>

       <!-- 导入外部的properties文件 -->

       <context:property-placeholder   location="classpath:jdbc.properties" />

       <!-- 定义dbcp提供的连接池对象 -->

       <bean   id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">

              <property   name="url" value="${jdbcUrl}">

              </property>

              <property   name="driverClassName" value="${driverClass}">

              </property>

              <property   name="username" value="${user}">

              </property>

              <property   name="password" value="${password}">

              </property>

 

              <property   name="timeBetweenEvictionRunsMillis" value="20000" />

              <property   name="minEvictableIdleTimeMillis" value="3600000" />

              <!--连接池启动时的初始值  -->

              <property   name="initialSize" value="10"></property>

              <!-- 连接池最大值 -->

              <property   name="maxActive" value="20"></property>

              <!--最大空闲值  -->

              <property   name="maxIdle" value="10"></property>

              <!--最小空闲值  -->

              <property   name="minIdle" value="3"></property>

              <property   name="maxWait" value="10000" />

              <!--

                     <property   name="preferredTestQuery" value="'SELECT 1'" />   <property

                     name="idleConnectionTestPeriod"   value="18000" /> <property

                     name="testConnectionOnCheckout"   value="true" />

              -->

              <property   name="testOnBorrow" value="true"></property>

              <property   name="testOnReturn" value="true"></property>

              <property   name="testWhileIdle" value="true"></property>

              <property   name="validationQuery" value="SELECT   1"></property>

       </bean>

 

       <bean   id="sessionFactory"

              class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

              <!-- 注入hbm.xml文件 -->

              <property   name="mappingResources">

                     <list>

                            <value>com/haodisk/pojo/User.hbm.xml</value>

                            <value>com/haodisk/pojo/Folder.hbm.xml</value>

                            <value>com/haodisk/pojo/File.hbm.xml</value>

                            <value>com/haodisk/pojo/Department.hbm.xml</value>

                            <value>com/haodisk/pojo/Group.hbm.xml</value>

                            <value>com/haodisk/pojo/Privilege.hbm.xml</value>

                            <value>com/haodisk/pojo/Role.hbm.xml</value>

                            <value>com/haodisk/pojo/Config.hbm.xml</value>

                            <value>com/haodisk/pojo/DeptFolder.hbm.xml</value>

                            <value>com/haodisk/pojo/DeptFile.hbm.xml</value>

                            <value>com/haodisk/pojo/GroupFile.hbm.xml</value>

                            <value>com/haodisk/pojo/GroupFolder.hbm.xml</value>

                            <value>com/haodisk/pojo/Share.hbm.xml</value>

                     </list>

              </property>

              <!--   hibernate框架参数 -->

              <property   name="hibernateProperties">

                     <props>

                            <prop   key="hibernate.show_sql">false</prop>

                            <prop   key="hibernate.format_sql">false</prop>

                            <prop   key="hibernate.hbm2ddl.auto">update</prop>

                            <prop   key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>

                     </props>

              </property>

              <!-- 指定数据库连接基本参数 -->

              <property   name="dataSource" ref="myDataSource">

              </property>

       </bean>

       <!-- 配置声明式事务管理(采用注解的方式) -->

       <bean   id="txManager"

              class="org.springframework.orm.hibernate3.HibernateTransactionManager">

              <property   name="sessionFactory"   ref="sessionFactory"></property>

       </bean>

       <tx:annotation-driven   transaction-manager="txManager" />

</beans>

 

 

 

 

 

附录B: 软件使用说明书

基于Hadoop的企业级网盘系统的软件使用说明

软件概述

见需求分析中的中“系统需求”部分。

1.1 功能

见需求分析中的中“功能需求”部分。

软件部署

2.1   系统要求

Tomcat6.0应用服务器

Mysql数据库服务器

Hadoop集群HDFS文件系统

2.2   部署前的准备

将该系统调试正确运行,配置系统所需运行环境。并为该系统建立相应网站。

2.3 部署

.将该系统发布到网站。

2.4 部署后

对发布的网站进行测试,确保正确性。

运行说明

在发布系统之前,要将该系统对应的数据库导入到对应的mysql中,并测试是否连接正常。

疑难解答

发布运行后可能会出现数据库连接的问题,请检查数据库连接的配置文件中配置是否正确。

服务与支持

如果在使用本系统的过程中遇到一些不能解决的问题,请及时与本系统的开发者联系。

  • 10
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值