1. 设计概述
本设计中,我们使用了来自如下来源的一些内容:
- Editor.md,用于实现 Markdown 的编辑和阅读;
- 耿晨歌老师提供的 Demo 中的部分 CSS;
- 文末 参考资料 中的一些实现思路或代码。
本设计参考了助教陆涛涛老师提供的《SpringBoot 入门》。该文档给我的入门提供了很大的帮助!
1.1 选题及基本功能
基于 SpringBoot 设计了一个简单的文档管理编辑器 咸鱼雀 (xianyuque),功能包括:
- 注册、登录和个人资料修改
- 使用 Cookies 保存登录状态
- 在数据库中使用 MD5 保存密码,提供一定的 安全性
- 文档编辑:Markdown 文档的阅读和编辑、发布
- 在进入文档阅读和编辑页面,以及发布时,进行 权限检查,保证隐私性
-
读写分离,用户未手动点击发布时,阅读页面仍为上一次发布的结果
- 编辑页中 每 2 分钟自动保存到缓存
- 从编辑页 退出时自动保存 到缓存
- 下一次 编辑时恢复缓存
- 文档管理
- 文件的列表展示
- 文件的新增、删除
- 文件归档
1.2 数据库模型设计
根据我们的需求,我们设计出了如下的数据库结构:
其中,实体
Users
保存了用户的用户名、MD5 加密的密码和昵称等信息;
FileInfo
保存了文件的 ID、标题、内容、最近修改时间等信息。
关系
VisibleTo
保存了权限关系,
Editing
保存了占用关系,
CacheOf
保存了文件的缓存(用于读写分离),
Inside
保存了文件的归档信息,
RevisionOf
保存了文件的历史版本信息。
这里说明读写分离和自动保存的实现思路:对于每一个文档,都有一个发布版和缓存版,这两个版本通过
CacheOf
关系连接。
-
- 当且仅当用户在编辑页面点击“发布”时,发布版才会被更新;
- 当发布版更新,或者用户在编辑界面每 2 分钟,或者用户退出编辑界面时,缓存版会被更新。
当用户进入编辑页面时,服务器展现的始终是 缓存版;当用户进入发布页面时,服务器展现的始终是发布版。
这个数据库结构的 DDL (Data Define Language) 代码在后文详细展示。
1.3 基本功能与逻辑
以下功能在本地环回地址下测试。
1.3.1 初始界面 /
在浏览器地址栏键入 localhost:8080,服务器会根据当前 request 是否携带服务器分配的 Cookies 判断当前用户是否登录。
- 如果未登录,则跳转到登录页面 /login;
- 如果已经登录,服务器根据 Cookies 找到当前用户的 ID,跳转到用户文件列表 /list/{userID}。
1.3.2 登录界面 /login
在登录界面中,用户可以输入用户名和密码进行登录。
登录界面样式
用户点击登录按钮时,会发送目的为 /login 的 POST 消息,服务器会将用户名和 MD5 加密后的密码与数据库中的信息进行比对:
如果错误,会提示“用户名或密码错误”或“用户不存在”:
如果登录成功,服务器会给用户分配一个 Cookie,记录其登录状态,有效期为 1 天;然后跳转到用户的文件列表 /list/{userID}。
用户可以点击“注册”按钮跳转到注册页面 /register。
1.3.3 注册界面 /register
用户点击注册按钮时,会向 /register 发送一个 POST 消息,服务器检查用户名是否已经存在。如果存在,进行错误提示:
如果没有冲突,则成功注册。跳转到用户文件列表 /list/{userID}。此时由于列表中没有文件,因此跳转到 /start 引导用户创建文档:
注册后跳转
数据库中新增的用户
1.3.4 文档列表界面 /list/{userID}
文档列表展示了 当前用户可见 的所有文档的标题和最新更改时间,同时展现了层级关系。
- 用户点击“新建”时,会跳转到 /new,实际上服务器会生成一对新的文件,返回 /edit/{fileID} 进入编辑页面;
- 用户点击“我的”时,会跳转到信息更改界面 /profile;
- 用户点击某个文档的标题时,会跳转到对应的文档阅读界面 /read/{fileID};
- 用户点击“编辑”时,会跳转到对应文档的编辑界面 /edit/{fileID} ;
- 用户点击“移动”时,会跳转到对应文档的移动界面 /move/{fileID};
- 用户点击“删除”时,浏览器会给出提示,用户确认后进行删除。
删除功能
用户点击删除的提示
1.3.5 用户信息更改界面 /profile
用户可以在这个界面更新个人信息。留空则不更新。
用户可以点击“退出登录”,服务器会删除保存的用户当前 Cookie,然后跳转到 /,随后会因为未登录跳转到 /login。
用户点击“返回”,会跳转到 /,随后会因为已登录跳转到 /list/{userID}。
1.3.6 开始引导界面 /edit/ {fileID}
用户点击“新建文档”会跳转到 /new,点击“我的”会跳转到 /profile。
1.3.7 新建文档 /new
用户访问“新建文档”时,服务器会首先检查用户是否登录(用 Cookies),如果没有登录,则跳转到 /。
如我们在 1.2 中所说,当我们新建文档时,服务器会新建 2 个文档分别作为发布版和缓存版。然后服务器将返回到 /edit 的 forward,并将缓存版的信息(ID 等)加入到返回的 ModelAndView 中。
1.3.8 文档编辑 /edit/ {fileID}
服务端会对 edit 的 request(包括 GET 和 POST)进行权限检查,如果有权限则返回内容。
Markdown 支持
文档编辑支持 Markdown 标记语言语法,并且可以实时看到对比:
支持 Markdown 语法和对比阅读,所见即所得
可以显示图片
点击标题可以进行修改
更新逻辑
- 用户点击“发布”时,发送一个 POST 到 /publish/{fileID},更新对应的 发布版 和 缓存版;
- 每 120 秒,客户端自动发送一个 POST 到 /autoSave/{fileID},更新对应的 缓存版;
- 用户关闭页面时,客户端的 unload 监听器会调用方法发送一个 POST 到 /autoSave/{fileID},更新对应的 缓存版。
自动更新的 JS 代码,以及服务器中的更新 log
1.3.9 文档阅读 /read/ {fileID}
服务端会对 read 的 request 进行权限检查,如果有权限则返回内容。
1.3.10 归档:移动文档 /move/ {fileID}
用户点击文档列表中的某个文档的“移动”按钮后,进入移动界面,选择将这个文档移动到哪个文档的内部:
移动前
移动“程序设计方法学”文档
移动后
在用户选择移动目的后,会给 /moveTo/{fileID}/{toFileID} 发送一个 POST,这时服务端会首先判断用户对这两个文件是否有权限,然后判断这个移动是否合法(即,目的文件不能是当前文件为根的子树中的节点;或者说,不能成环);如果合法则进行移动。然后跳转回列表。
1.3.11 错误页面 /error
当用户试图访问一个不存在的页面,或者访问无权访问的文件(包括其阅读、编辑、移动等操作)时,会跳转到 /error 页面。
用户点击“返回”回到 /。
2. 代码简述
2.1 基本配置
2.1.1 工程建立
在 https://start.spring.io/ 建立了 SpringBoot 工程:
用 IDEA 打开工程,加载依赖项。
2.1.2 数据库
安装配置 MySQL
数据库设计:
数据库建立:
```c++ create database xianyuque;
use xianyuque;
create table users ( ID varchar(32), Name varchar(64), EnKey char(64), primary key(ID) );
create table file_info ( ID int, title varchar(64), localName varchar(64), isFolder boolean, isTopLev boolean, lastEdit datetime, cacheFor int, insideOf int, primary key(ID), foreign key(cacheFor) references file_info(ID) on delete cascade on update cascade, foreign key(insideOf) references file_info(ID) on delete cascade on update cascade );
create table visible_to ( userID varchar(32), fileID int, isFirstAuthor boolean, isWritable boolean, primary key(userID, fileID), foreign key(userID) references users(ID) on delete cascade on update cascade, foreign key(fileID) references file_info(ID) on delete cascade on update cascade );
create table revision_of ( srcFileID int, revFileID int, primary key(revFileID), foreign key(srcFileID) references file_info(ID) on delete cascade on update cascade, foreign key(revFileID) references file_info(ID) on delete cascade on update cascade );
create table editing_by ( fileID int, userID varchar(32), primary key(fileID), foreign key(userID) references users(ID) on delete cascade on update cascade, foreign key(fileID) references file_info(ID) on delete cascade on update cascade ) ```
参考配置:
application.properties 全文
```python
application.properties
server.address=0.0.0.0 server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/xianyuque?characterEncoding=utf8&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=721121 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath:mapper/*.xml ```
pom.xml 追加
c++
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.2 代码结构简述
在本工程中:
resources 是一些资源;其中:
-
static 存放图标以及 Editor.md 的部分资源
-
templates 是网页的 HTML 文件
Java 中的 com.xuaninsr.xianyuque 中是主要的 Java 代码;其中:
-
类 XianyuqueApplication 是工程的入口
-
包 pojo (Plain Ordinary Java Object) 中包含了 Article, FileInfo, User 这三个简单的 JavaBean
- 包 mapper 和 service 操作数据库取得与文件、用户有关的一些信息,构成我们的 mapper 和 service 层,为 controller 层提供服务
-
包 controller 是 controller 层,用于处理 HTTP request
-
包 utils 包装了我们在文件操作以及 MD5 加密时用到的一些工具方法
关于代码的具体细节,请参见源代码。
3 总结与讨论
本工程在实现了选题的基础功能的基础上,还完成了如下 亮点:
- 使用 Cookies 保存登录状态
- 在数据库中使用 MD5 保存密码,提供一定的安全性
- 支持 Markdown
- 进行权限检查,保证隐私性
- 读写分离,定期和退出时自动保存到缓存
本工程在设计之初还考虑实现 多人编辑(数据库中的 Editing)、历史版本(数据库中的 RevisionOf)等功能,但由于考试周时间紧张,最终没有能够完全实现。当然,产品会经过迭代的过程;在后续的版本中(如果有),这些功能在已经建立了这些数据库的基础上也能更好地完成。
本工程在设计过程中,对 UI 做了一定的考量,但最终由于时间有限只优化了部分页面的 UI。这也是可以进一步提升的部分。
本工程在设计过程中使用了 GitHub 做版本管理,经过了 5 天的开发。
非常感谢陆助教提供的《SpringBoot 入门》指南,这个指南帮助我较为轻松地入门这个框架并设计出了这个工程。
过程中遇到了各种各样的问题,我也都通过搜索引擎尝试解决;其中比较有价值的内容我也以连接附在了文末的“参考资料”部分。
4 参考资料
除了之前提到的参考资料外,本工程还参考了:
4.1 Thymeleaf 相关
●Thymeleaf POST
https://stackoverflow.com/questions/17669212/send-datas-from-html-to-controller-in-thymeleaf
●返回 ModelAndView
https://blog.csdn.net/weixin_44075963/article/details/103625527
●Thymeleaf 及 JS 如何取 CONTROLLER 中返回的 MODEL 里的值
○https://www.freesion.com/article/1135452868/
●Thymeleaf + Editor.md
○https://juejin.cn/post/6899038096805855246
○https://blog.csdn.net/qq_26212181/article/details/103762957
4.2 Cookies 相关
●登录
https://blog.csdn.net/qq_42595527/article/details/110495208
●Cookies
https://blog.csdn.net/weixin_42061487/article/details/105935331
●保存登录状态
https://blog.csdn.net/zeping891103/article/details/76032949/
4.3 JS 相关
●定时自动保存
https://stackoverflow.com/questions/63763061/regularly-send-post-request-when-user-changes-value-in-textarea
●关闭网页时自动保存
https://glados.rocks/console/shop
●JS 实现 POST
https://www.cnblogs.com/blog-cq/p/6038410.html
4.4 HTML 和 CSS 相关
●表格实现点击
https://stackoverflow.com/questions/47519295/onclick-thymeleaf-dynamic-url-parameter
●提示框确认删除
https://www.cnblogs.com/szy13037-5/articles/9778071.html
●HTML span 两端对齐
https://blog.csdn.net/lkp1603645756/article/details/105297560/
4.5 SQL 相关
●返回值为 NULL 时设置默认值
https://blog.csdn.net/weixin_42300435/article/details/111893842
参考文献
- 基于混合架构的档案扫描管理系统的设计与实现(浙江工业大学·李冬冬)
- 建筑设计院图档管理系统的设计与实现(吉林大学·时淮龙)
- 基于SpringBoot技术的行波管设计文件管理系统的设计与实现(电子科技大学·陈凯)
- 基于SSH的档案管理系统的设计与实现(电子科技大学·张苗)
- 基于SSH的档案管理系统的设计与实现(电子科技大学·张苗)
- 基于JAVA的高校学生管理系统的设计与实现(电子科技大学·王盾)
- 建筑设计院图档管理系统的设计与实现(吉林大学·时淮龙)
- 基于Spring技术的政府机关文档管理系统的设计与实现(电子科技大学·文绪源)
- 办公文档管理系统的设计与实现(华东师范大学·张伟)
- 基于JAVA的高校学生管理系统的设计与实现(电子科技大学·王盾)
- 办公文档管理系统设计与实现(电子科技大学·潘攀)
- 行政单位档案管理系统的设计与实现(电子科技大学·高寰宇)
- 基于SSH框架的博客用户分享平台的设计与实现(河北工业大学·刘磊)
- 办公流程管理系统的设计与实现(北京邮电大学·王影)
- 建筑设计院图档管理系统的设计与实现(吉林大学·时淮龙)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码项目助手 ,原文地址:https://m.bishedaima.com/yuanma/36081.html