一、项目简述
进入github下载本项目(开源)
这是一个模仿网盘的项目,主要是为了熟悉Struts2框架,该项目不涉及底层DAO操作,只涉及到Struts2的相关知识,底层DAO操作是使用数据单元进行模拟的。
本项目涉及到的知识有:网页布局、action的实现与配置、输入校验、树、Struts2的AJAX支持、Filter、文件上传下载。
实现的功能有:
1.登录、注册、注销
2.目录层次浏览
3.在任意目录层次下新建文件夹、删除文件夹
4.在任意目录层次下上传文件
5.在任意目录层次下删除文件、文件夹
6.返回上一级目录
7.文件下载
查看效果:项目效果展示
本节主要对项目进行分析以及对其中涉及到的一些知识点进行回顾。
二、知识点回顾
1.登录注册
登录注册功能是很普遍的功能。
所谓注册是指:网页收集用户填写的表单信息提交给RegisterAction处理,在RegisterAction的execute()方法中调用业务逻辑组件,业务逻辑组件调用DAO组件完成对用户数据的保存并返回逻辑视图名。
所谓登录:网页收集用户填写的表单信息提交给LoginAction处理,在LoginAction的execute()方法中调用业务逻辑组件,业务逻辑组件调用DAO组件完成对用户名和密码的验证,验证成功保存用户信息并返回SUCCESS逻辑视图名,失败返回ERROR逻辑视图名。
不要忘了在struts.xml文件中配置action,并定义逻辑视图名与资源视图的映射关系。
2.目录相关功能
这个功能对我来说是最难的了,有几下几个问题:
-
2.1目录存储结构
很自然的可以想到使用树形结构实现,每一个文件或者文件夹都是一个文件结点,每个结点都有多个孩子结点并有自身属性,每个用户都有一个根目录结点,这个根结点在用户注册时应该创建并建立起用户与根结点的映射关系。
我们需要实现几个相关的方法,比如获取指定路径的所有孩子结点、删除多个文件结点
-
2.2 路径表示方法
为完成上一个目标,我们必须定义一个路径的表示方法。
第一次尝试:
根路径:/
某路径:/文件夹1/文件夹2本来我是直接使用这种方式来定义的,第一行是根目录的定义方式,第二行是某个路径的定义方式。后来发现这种方式并不靠谱,系统内部会把/给转义。
第二次尝试:
根路径:“”或null
某路径:文件夹1/文件夹2第二次我把根路径设为空,但是路径的表示中分隔符仍然会被转义,所以我用#来代替路径的分隔符,最终路径表示方法如下:
根路径:“”或null
某路径:文件夹1#文件夹2 -
3.在指定路径下创建文件夹
用户点击触发点击事件,我们将文件夹名、路径封装起来通过Ajax提交给DirAction下的指定方法。
- 取出Session范围内保存的用户信息。
- 根据用户信息调用业务逻辑组件,业务逻辑组件调用DAO组件获取指定用户、指定路径对应的文件结点。
- 根据文件夹名创建文件夹结点
- 根据文件结点获取其孩子结点集合
- 将文件夹结点添加到该孩子结点集合中
- 设置DirAction的集合属性为当前路径的孩子集合,因DirAction的返回结果是Json,DirAction的所有属性名、属性值以及getter方法会被封装成Json数据返回。
-
4.获取指定路径所有孩子结点
- 取出Session范围内保存的用户信息。
- 根据用户信息调用业务逻辑组件,业务逻辑组件调用DAO组件获取指定用户、指定路径对应的文件结点。
- 根据文件结点获取其孩子结点集合
- 设置DirAction的集合属性为当前路径的孩子集合,因DirAction的返回结果是Json,DirAction的所有属性名、属性值以及getter方法会被封装成Json数据返回。
-
5.删除多个文件夹
- 取出Session范围内保存的用户信息。
- 根据用户信息调用业务逻辑组件,业务逻辑组件调用DAO组件获取指定用户、指定路径对应的文件结点。
- 在参数中分解出要删除的多个文件夹名,遍历待删除的文件夹名数组,在文件结点的所有孩子中依次删除指定的文件夹
- 返回文件结点
- 获取其孩子集合,设置属性,返回逻辑视图名
-
6.路径搜索
可以看到前面三个功能实现步骤基本相同,都需要先查找到对应的目录层次才能进行下一步操作,我们需要定义以下两种操作:
-
搜索指定路径的结点
该方法的实现是重点,用户传入路径,如:file1#file2#file3
将路径拆分为数组arr={“file1”,”file2”,”file3”}
DAO组件根据用户名获取到根目录结点,然后获取到根目录结点的孩子结点集合childs
定义当前匹配的结点curDirNode并初始化为根结点
定义当前匹配的结点的孩子集合curDirNodes并初始化为curDirNode的孩子集合遍历数组,设当前遍历结点为node,在curDirNodes搜索与node结点的文件夹名属性值相同的结点,如果搜索到位置为pos,则令:
//设置当前结点
curDirNode = curDirNodes.get(pos);
//设置孩子集合
curDirNodes = curDirNode.getChilds();如果搜索不到,返回空。
遍历结束,返回://返回当前结点
return curDirNode;- 搜索指定路径的孩子结点
根据上一个方法的实现搜索出指定路径结点然后获取其孩子结点
//直接调用上一个方法获取根节点然后获取它的孩子集合
return findRootNode(username, password, dirPath).getChilds(); -