File Space——一个java structs2.0的小栗子(DIY)
1 概述
File Space系统适用于团体,主要提供的是团队文件分享以及个人文件的存储管理服务。分为个人文件存储管理平台和团队文件共享平台。
个人文件存储平台主要为个人提供相关的文件分类存储服务:该部分在用户登录后,可以选择添加新的文件,创建新的分类,修改原有的文件,查看相关的文件,以及对个人信息的管理等。
团队space主要是将个人部分添加的资料进行共享性的展示。
个人用户可以浏览团队共享的内容,然后在已登录的情况下,可以将浏览到的自己喜欢的资料添加到自己的收藏。
项目针对半封闭的团队管理方式,因此用户添加方式采用管理员添加方式。
详细的系统功能请看下图(图1-1)所示:
图:1-1
2 需求分析
2.1 系统需求概述
当今的时代推崇共享,工作团队中也需要共享。此系统为团队提供文件方面共享,通过为用户提供一个文件的存储管理平台,吸引用户进行文件上传,然后对上传的文件进行共享。
2.2 用例分析
该系统包括普通用户以及管理员两种活动者,此外,可以有游客,但是游客只能查看共享的概要信息。系统中,管理员用户是继承自普通用户,在普通用户的基础上多了对系统用户的管理功能。普通用户主要有系统的登陆登出,对于个人信息的管理,对于个人文件的管理,对于文件分类的管理以及对于收藏的管理,此外,下载文件功能单独列出,是基于用户既可以下载自己的文件,也可以下载共享区的文件。详细的用例情况请参考(图2-1)。
图:2-1
3 系统设计
3.1 技术路线
整体使用基于Model-View-Controller (MVC)模型的Struts2 web应用框架,使用JSP作为视图显示,实现前后端的分离,数据存储采用JDBC进行持久化存储。系统选用MYSQL数据库来存储数据,使用Tomcat7.0作为系统服务器。在页面表示方面综合应用了HTML5标准,JQuery等增加页面效果。此外,系统采用Tomcat自带的Tomcat JDBC Pool 增加数据访问的性能。
3.2 系统总体架构设计
总体基于MVC模式的B/S web系统,考虑扩展方便设计了4层架构:页面表示层(JSP)、请求处理转发层(Action)、业务逻辑层(Service)和持久化存储层(DAO)。
下图(图:3-1)是大部分B/S系统的架构图。
图:3-1
3.3 数据库设计
数据库根据系统的需要设计了用户表、文件表、文件类型表、收藏表,各个表中标示了实体的基本的必要属性,图中连线标示外键关系。用户与文件、文件类型、收藏都是1对多的关系,文件与收藏也是1对多的关系,同一个文件可以被不同的用户进行收藏,但每个用户只能单独收藏。此外,文件表与类型表是多对1的关系。图3-2中的连线标示外键关系。
图:3-2
3.4 系统详细设计
A.页面布局结构如下图3-3:
图:3-3
B.单页面内的操作采用调用Jquery方法,传递JSON数据的方式进行局部刷新。
C.进入首页需要执行action获取相关的文件数据,采用先进入一个页面,在该页面直接进行调用的方式实现。
D.密码使用MD5进行加密
E.使用拦截器在执行相关Action前进行登录状态的拦截。
F.使用数据库连接池提高系统性能。
G.使用存储过程,封装数据库操作。
H.使用Log4j记录DAO层的操作以及出错处理。
I.具体的Action方法实现逻辑参考功能实现。
4 系统实现
4.1 分页功能的实现
分页功能针对系统中显示的数据的数据非常多的时候采用的技术,目的是为了让系统按照页码展示相对应的数据记录,减少数据传递的数量,增加页面访问速度,提高用户体验。
分页实现采用定义分页类(图:4-1),然后需要使用分页的方法填写分页类的属性值,完成分页。
图:4-1 图:4-2
分页类定义了5个属性:当前页(currPage)、每一页显示的记录数目(ItemOfPage)、
总共的记录条数(totalItem)、总共的页数(totalPage)、对应页面的记录集合(items)。
其中当前页需要传递的前台数据,如果前台没有传递当前需要获取的是第几页则默认为第一页;每一页显示的记录数目采用的默认显示10条的方式,用户无法修改;总共的记录条数需要读取数据库中的数目,采用分页的需要首先在DAO层定义读取数据库所有数据数目的方法,然后在service层进行调用,然后填写到Pager对象中;总共的页数需要通过总共的记录条数以及每页显示的条数进行计算,然后将结果填入;最后根据该Pager对象的属性获取相应的数据库记录填写到Items列表中,传递到前台进行显示。
计算总共页数的方法:
totalItem%pager.getItemOfPage()==0?(totalItem/pager.getItemOfPage()):(totalItem/pager.getItemOfPage()+1)
4.2 日志功能的实现
日志采用Log4j的方式,首先导入如图(图4-2)的日志包,然后配置log4j.properties文件(图4-3)。然后在需要添加日志的页面通过log4j包中的方法获取日志对象,填写相应的日志信息。
private static Logger logger = Logger.getLogger(UserDaoImpl.class);
图:4-3
4.3 MD5加密(密码)的实现
首先定义加密类MD5以及加密的静态方法toMD5(),然后在需要加密的地方通过MD5调用静态方法进行加密。
toMD5()方法采用网上的博客教程,实现如下:
public final static String toMD5(String s) { char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try { byte[] btInput = s.getBytes(); // 获得MD5摘要算法的 MessageDigest 对象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字节更新摘要 mdInst.update(btInput); // 获得密文 byte[] md = mdInst.digest(); // 把密文转换成十六进制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { e.printStackTrace(); return null; } }
4.4 登录权限控制的实现
系统的权限控制是通过拦截器实现。
首先定义该拦截器,在执行相关的Action前进行拦截,该拦截器的实现通过继承
MethodFilterInterceptor并重写doIntercept方法实现。
关键代码如下:
HttpServletRequest request = ServletActionContext.getRequest(); User user = (User) request.getSession(false).getAttribute("user"); if(user == null){ //logger.info("用户没有登录!"); return "re"; } else { //logger.info("用户登录成功!"); return invoker.invoke(); }
4.5 数据库连接池的实现
数据库连接池能够有效的提高访问数据库的速度,因此采用。
该项目使用Tomcat7.0 自带的Tomcat JDBC Pool,通过在项目中添加context.xml中配置数据源,然后通过获取context中的数据源获取数据库的连接。
4.6 文件上传功能的实现
文件上传前台使用类型为file的input,因为中文文件名在下载时出现问题,难以传输,因此在这里限制上传的文件名必须是英文名。
后台上传实现直接就通过
ServletActionContext.getServletContext().getRealPath("/upload");
获取文件上传的地址(项目下面的upload文件夹),然后将文件通过文件的输入输出流写入到服务器。
最后将文件的相关的存储信息写入到数据库,以便下载。
4.7 文件下载功能的实现
首先根据前台传递过来的文件的id值,获取该文件的相关信息,然后定义一个文件输出流以及相关的getter与setter方法,确定fileName以及contentType,最后配置输出的result
<result name="download" type="stream">
<param name="inputName">fileDown</param>
<param name="contentDisposition">attachment;filename="${fileFileName}"</param>
<param name="contentType">fileContentType;charset=utf-8</param>
</result>
4.8 查看文件列表功能的实现
文件列表分为区分用户与不区分用户的列表两种,分别对应首页的共享的文件展示与个人文件的展示,首页的文件展示因为文件数量巨大,因此采用的是分页的方式进行展示,个人文件里面的文件列表因为每一次展示都需要涉及文件的分类,因此数量不是很大,没有采用分页。
首页文件的共享展示,采用的分页方式过程请参考分页的实现
个人文件的展示通过session里面的用户对象以及前台传过来的文件类型的id值获取相关的文件对象列表进行实现。
4.9 数据库设计(用户区分,文件级联删除,存储过程)
数据库的具体设计见系统设计中的数据库设计。
用户区分采用的是在用户的属性中添加判断该用户是否是管理员的字段,根据该字段的值进行判断该用户是管理员还是普通用户。
文件删除功能,项目中没有提供单个文件的删除功能。
在用户删除某个文件类型的时候,根据外键关系,级联删除这些文件信息,在管理员删除该用户时,该用户下面的文件也会被删除。
项目的数据访问都采用的是存储过程。
采用Navicat直接在数据库定义存储过程,然后在DAO层中通过
prepareCall(“call XXX”);调用该存储过程获得数据。
4.10 面包屑导航功能的实现
面包屑导航的作用是告诉访问者他们目前在网站中的位置以及如何返回,当网站中出现典型的单线3层以上的层次使用面包屑导航可以有效的提高用户的体验。
本次项目中因为要实现文件分类的无限级别的分类,因此采用面包屑导航。
项目中的页面部分展示通过后台传递的Map集合直接读取显示。
Map里面存放的当前分类的所有的父类的id值(键)以及对应的类别名称(值)。
因为考虑到需要按照一定的顺序存放,Map采用的是LinkedHashMap。
Map里面键的集合里面的值通过数据库里面定义的函数实现。
该函数通过传递的当前的类别的id值获取该类别的所有的父类并且按照一定的顺序,形成字符串输出。
该函数如下:
BEGIN DECLARE sParentList varchar(1000); DECLARE sParentTemp varchar(1000); SET sParentTemp =cast(rootId as CHAR); WHILE sParentTemp is not null DO IF (sParentList is not null) THEN SET sParentList = concat(sParentTemp,',',sParentList); ELSE SET sParentList = concat(sParentTemp); END IF; SELECT group_concat(parentid) INTO sParentTemp FROM tab_type where FIND_IN_SET(tid,sParentTemp)>0; END WHILE; RETURN sParentList; END
源码地址:https://github.com/husky00/Java/tree/master/Java/FileSpace01
sql地址:http://files.cnblogs.com/files/husky/FileSpace.zip 用的mysql 数据库,sql 使用navicat自动导出的!
File Space——一个java structs2.0的小栗子(DIY)的更多相关文章
- java网络爬虫爬虫小栗子
简要介绍: 使用java开发的爬虫小栗子,存储到由zookeeper协调的hbase中 主要过程是模拟Post请求和get请求,html解析,hbase存储 源码:https://github.com ...
- java堆溢出的小栗子
package com.xiaoysec.test; import java.util.ArrayList; import java.util.List; /** *VM Args:-verbose: ...
- 一个Java方法覆盖的小问题
class SuperClass{ public SuperClass() { System.out.println("superclass "); show(); } publi ...
- 第一个java的小东西
第一次自己写的一个java的小东西,毕竟自己第一次写的,其中可谓是历经艰难,最后总结下来就是java实在是不适合写界面化的东西代码量比较大,这还不是最关键的,最关键的是控件的位置实在是太难控制了. 这 ...
- 用java从0生成一个简单的excel
用java从0生成一个简单的excel 目标 用代码实现对一个excel的基础操作,包括创建,插入文字,(好像就这些了),生成的excel可以用wps打开,如果直接用c++的文件流会生成假的xls表格 ...
- 一个小栗子聊聊JAVA泛型基础
背景 周五本该是愉快的,可是今天花了一个早上查问题,为什么要花一个早上?我把原因总结为两点: 日志信息严重丢失,茫茫代码毫无头绪. 对泛型的认识不够,导致代码出现了BUG. 第一个原因可以通过以后编码 ...
- 出现错误:Unable to load configuration. - action - file:/E:/Java/Tomcat7.0/apache-tomcat-7.0.68-windows-x64/apache-tomcat-7.0.68/webapps/SSH2Integrate/WEB-INF/classes/struts.xml:8:43
严重: Exception starting filter struts2 Unable to load configuration. - action - file:/E:/Java/Tomcat7 ...
- Java学习笔记二十九:一个Java面向对象的小练习
一个Java面向对象的小练习 一:项目需求与解决思路: 学习了这么长时间的面向对象,我们只是对面向对象有了一个简单的认识,我们现在来做一个小练习,这个例子可以使大家更好的掌握面向对象的特性: 1.人类 ...
- Spring Framework5.0 学习(1)—— 用Gradle构建一个Java Project
1.0 安装Gradle,参考之前文章<Gradle入门实战(Windows版)> 2.0 使用gradle 快速生成一个Java project gradle init --type ...
随机推荐
- .Net Framework 与 SQL Server 2005 混乱的时间最大最小值
Net Framewrok 中,DateTime.MinValue => 0001/01/01 00:00:00SqlDateTime.MinValue.Value => 1753/01 ...
- Spring事务管理之声明式事务管理-基于AspectJ的XML方式
© 版权声明:本文为博主原创文章,转载请注明出处 案例 - 利用Spring的声明式事务(AspectJ)管理模拟转账过程 数据库准备 -- 创建表 CREATE TABLE `account`( ` ...
- cocos2dx3.0戳青蛙游戏(打地鼠)
1戳青蛙项目描写叙述 1.1功能描写叙述 实现类似打地鼠游戏.青蛙随机出如今屏幕左边5*3的格子中,并会向屏幕右边移动,在青蛙逃离之前,手指点击实现戳灭青蛙的效果.随着分数添加,青蛙越来越多,当青蛙逃 ...
- python easy install时,使用aliyun阿里云镜像提示主机名不匹配的问题
因网络问题,因此设置 easy_install 使用阿里云的源, ## 更新 easy_install 源 tee ~/.pydistutils.cfg <<-'EOF' [easy_in ...
- lua学习笔记(八)
元表与元方法 基本概念 1.lua中每个值都有一个元表 2.table和userdata可以有各自独立的元表 3.其它类型的值共享其类型所属的单一 ...
- java 原生定时执行程序(ScheduledExecutorService)
package ThreadPoolTest; import java.util.Date; import java.util.concurrent.*; public class Main { pu ...
- Python读取word文档(python-docx包)
最近想统计word文档中的一些信息,人工统计的话...三天三夜吧 python 不愧是万能语言,发现有一个包叫做 docx,非常好用,具体查看官方文档:https://python-docx.read ...
- Android Studio 2.0 稳定版新特性介绍
Android Studio 2.0 最终迎来了稳定版本号,喜大普奔. 以下这篇文章是2.0新特性的一些简介. 假设想看具体内容请看这里<Android Studio有用指南> 文章转自这 ...
- 批量删除redis某个键值
/usr/local/redis/src/redis-cli -h 172.28.6.23 -p 6383 keys "virtual*" |xargs /usr/local/r ...
- ASIHTTP
本文转载至 http://www.th7.cn/Program/IOS/201303/128223.shtml 向服务器端上传数据 ASIFormDataRequest ,模拟 Form表单提 ...