基于SpringCloud的动漫论坛《BOKI》
摘要:鉴于现如今的互联网网站的存在形式,网站内部有可能内嵌论坛,因此,该项目中实现一个整体的、可移植性强的插件式论坛,论坛就有可能突破ACG主题的限制,实现论坛与主站的分离,只要提供前端,就能够正真实现论坛的插件式引入。
在如今主流的web项目框架中,该项目中将使用Spring框架作为后端基础,使用mysql数据库。项目的运行环境包括但不限于windows 7以上环境。mysql与redis将在CentOS环境中使用docker容器,以实现快速启动。由于数据的增删改查并非完全以PO形式,故在项目的dao层使用灵活度较高的mybatis框架。
该论坛主要实现未登录的游客的帖子浏览,已登录用户的发帖回帖、个人信息管理,管理团队对普通用户和帖子的调控,实现论坛环境的正常运行和提升用户的发帖与浏览体验。针对核心的发帖模块,经过对后端接口的严格测试,已经能够正确地实现发帖、回贴,甚至是二级回复。其他接口同样地,均通过黑盒测试,能够稳定地提供数据交互。通过对系统各项功能的优化与测试,系统能够对用户不合理的操作进行提示,所设计的系统能够正常运行、业务处理逻辑比较合理,符合初期的目标和系统的实际要求。
关键词:spring框架,论坛,mysql,动漫,VUE框架
ACG Forum “BOKI” Based on Spring Cloud
Abstract:In view of the existing form of Internet websites nowadays, it is possible to embed forums inside the websites. Therefore, in this project, a whole plug-in forum with strong portability can be realized, which may break through the limitation of ACG theme and separate the forum from the main station. As long as the front end is provided, the plug-in introduction of the forum can be realized.
In today’s mainstream web project framework, the project will use the spring framework as the back-end foundation and MySQL database. The running environment of the project includes but is not limited to the environment above Windows 7. MySQL and redis will use the docker container in the CentOS environment for quick startup. Since the addition, deletion, modification and query of data are not entirely in the form of Po, the mybatis framework with high flexibility is used in the Dao layer of the project.
The forum mainly realizes the post browsing of the visitors who have not logged in, the post reply and personal information management of the users who have logged in, the regulation of the management team on the ordinary users and posts, the normal operation of the forum environment and the promotion of the post and browsing experience of the users. For the core posting module, after the strict testing of the back-end interface, it has been able to correctly implement posting, reply, or even secondary reply. The other interfaces also pass the black box test and can stably provide data interaction. Through the optimization and test of various functions of the system, the system can prompt the unreasonable operation of users, the designed system can operate normally, the business processing logic is more reasonable, and meet the initial goal and the actual requirements of the system.
Key words: Spring, BBS, MySql,ACG,VUE
目录
第1章 绪论 1
1.1系统的开发背景及意义 1
1、课题目的 1
2、课题意义 1
1.2国内外研究现状 3
1.3系统的主要研究内容 4
1.4系统开发环境与开发工具 5
第2章 系统需求分析 7
2.1 系统的核心业务流程分析 7
2.2 系统的整体功能需求分析 9
2.3 动漫论坛系统功能需求 11
2.3.1参与者 11
2.3.2用户客户端基础功能需求 12
2.3.3管理员客户端基础功能需求 14
2.4 本章小结 16
第3章 系统的设计与实现 17
3.1 系统总体架构设计 17
3.2 数据库设计 18
3.2.1 概念结构设计 18
3.2.2 逻辑结构设计 21
3.3 客户端子系统详细设计 27
3.3.1 客户端后端接口设计 27
3.3.2 客户端关键代码与难点实现 31
3.4 管理端子系统详细设计 35
3.4.1 管理端后端接口设计 35
3.4.2 管理端关键代码与难点实现 37
3.5 前端服务器详细设计 39
3.4 本章小结 39
第4章 系统测试 40
4.1 测试的意义 40
4.2 测试的目的 40
4.3 测试方法 40
4.4 测试用例及结果 40
4.5 本章小结 40
第5章 结束语 41
5.1 全文总结 41
5.2 课题展望 41
参考文献 42
致 谢 43
第1章 绪论
1.1系统的开发背景及意义
1、课题目的
所谓论坛,随着Internet技术的快速发展,BBS论坛在网络上已成为人们彼此沟通、交流信息的主要方式。在论坛上,人们可以对某一领域提出自己遇到的问题,随后,论坛上的其他人会根据自己的学识、经验发表意见或提出问题的方法。BBS论坛接近了人们之间的距离,它早已成为人们网上生活的必备工具。所以说BBS论坛对当今社会是相当重要的。
对于日渐增多的动漫爱好者社团活动的需求,我决定实现一个为动漫爱好者定制的论坛系统,实现动漫爱好者彼此之间的线上交互。作为论坛,首要目标就是要实现用户界面的美观,可读性,以及用户发帖和对帖子的阅读。
2、课题意义
关于动漫的解释,动漫,指动画与漫画的集合,即动画、漫画的合称,取这两个词的第一个字合二为一称之为“动漫”,与游戏无关,并非专业术语。现如今的动漫论坛不再单单是讨论动漫,往往包含了游戏领域。
动画和漫画的合称,在台湾一般为“动漫画”,简称“动漫”,在大陆则一般为“动漫”。常见的搭配有“动漫(画)迷”、“动漫(画)产业”等。除“动漫(画)”以外,华语圈也经常使用ACG(动画·漫画·游戏)、ACGN(动画·漫画·游戏·小说)等合称。1995年,台湾的动漫爱好者AIplus在国立中山大学山抹微云BBS站开设新版面,使用“ACG_Review板”作为名称以代动画、漫画、游戏,乃为“ACG”一词之始。由傻呼噜同盟推广下,三个字母的顺序渐渐固定下来,并流传至中国大陆、香港等华人社会。
现如今在轻小说改编的动画、漫画、游戏越来越多之际,又衍生出“ACGN”,小说。主要指轻小说(Light Novel)。ACG所指内容也涵盖轻小说,因此虽有人提出使用ACGN作为该演进说法的词,但实际上绝大多数场合仍在使用ACG。不过近年来由于轻小说的发展,使用ACGN的人群正逐渐增多。
所谓论坛,随着Internet技术的快速发展,BBS论坛在网络上已成为人们彼此沟通、交流信息的主要方式。在论坛上,人们可以对某一领域提出自己遇到的问题,随后,论坛上的其他人会根据自己的学识、经验发表意见或提出问题的方法。BBS论坛拉近了人们之间的距离,所以说BBS论坛对当今社会是相当重要的。它早已成为人们网上生活的必备工具。
对于日渐增多的动漫爱好者社团活动的需求,我们决定实现一个为动漫爱好者定制的论坛系统,实现动漫爱好者彼此之间的线上交互。作为论坛,首要目标就是要实现用户界面的美观,可读性,以及用户发帖和对帖子的阅读。
该论坛研发意义有以下几点:
(1)为有有相同爱好的动漫爱好者、动漫爱好群体和有兴趣的人们提供一个交流的平台。
(2)动漫论坛的开发成本相对php项目开发成本高,但是,由于使用了稳定性、拓展性和维护难度较低的Spring框架,大大提升了系统的可用性和运行效率,具备了论坛的必要功能。. BIKI动漫论坛具备了发帖与回复,个人中心和其他论坛常见模块,并实现一整发帖流程。
(3)BIKI动漫论坛具备有管理系统,拥有对用户的发言管理、惩罚机制、以及关键的帖子置顶等功能,方便论坛管理人员对论坛进行管理,并减少无意义发帖、刷帖、不良内容等恶意扰乱秩序的行为。
(4)BIKI动漫论坛本身作为开放性交流平台,游客不需要登陆也能够浏览帖子,扩大了用户的访问便利性。 发帖或回复则需要登陆才能实现,限制了游客经行无意义发帖、刷帖、举报等恶意扰乱秩序的行为。
目前流行的动漫论坛中,有三中类型,一是资源型,资源型论坛注重对ACG(Animation(动画), Comic( 漫画)和Game(游戏)的缩写)资源的掌控。二是发布型,发布型论坛注重对ACG新闻热点和实时消息的通知、公告、发布。三是交流型,交流型论坛注重对用户之间的交互,言论自由,但不乏官方限制,比如百度贴吧、知乎、CSDN论坛。
本系统主要设计形式为为第三种,交流型论坛。
1.2国内外研究现状
以动漫作为主题的论坛,它的发展情况应分为两部分来分析-------也就是对动漫与论坛进行分析与结合。没有人愿意接触的领域,没有建立论坛的必要性。如果没有人愿意接触动漫,BOKI论坛也就失去了的意义。反之,一个交流平台没有的便利性与互动性,热门领域和热门产业也就不会选择这样的平台。如果BOKI论坛没有的便利性与互动性,动漫爱好者也就不会选择这样的平台。
首先是动漫领域的分析:
基于IP的繁荣和产业链的成熟,各方都在不停的摸索,不停的尝试,但没有一家能拿出大手笔,也没有一家真正拿出分蛋糕的方法。因为没人敢于拿出更大的资金和精力去尝试做一部剧情、分镜、音乐、做画质量等都足够优秀的动画,百千万的投资对于沉寂了十来年的中国动画市场来说无疑是一种赌博,而相关技术人员的匮乏也会让保证质量的动画周期变长,保证周期的动画质量下降,加重动画的制作成本,导致国内情况并不算乐观。
尤其是05年之后,随着互联网的发展,随着社交网络的发展,动漫作为一种艺术载体其实有了很多新的一些小趋势。同时受众从原来单纯的收听率调查对象到真正参与进整个作品的企划也是一个比较良性的特征,也就是受众与作品的互动逐渐增多,并且受众对作品的影响也从原来的商品属性转向一种多义性的属性。
国外情况以动漫产业发达的日本为例,市场化经济体制的核心就是竞争。竞争是促进产业进步的动力。日本漫画业已是一个十分成熟的产业,杂志社间的竞争自然必不可少。 本漫画杂志依照消费群体不同而笼统分为男性向(以男性读者为主体)和女性向(以女性读者为主体)两类。由于互联网近些年的快速发展,动漫文化的交流已经在中国,乃至世界各地占有了一席之地,日渐火爆。
其次是基于论坛的分析:
抛出结论:论坛依旧是互联网交流的主力,大型论坛有百度贴吧、天涯、猫扑等,中小型论坛作为小群体的主要交流平台,更是数不胜数。
论坛本身是一种形式,主贴为一个话题点,评论是话题的延伸,而话题以某个主题聚集在一起,就形成了论坛。
这种形式是不死的。因为他很松散,很活跃,很适合互联网,所以他会形变,会衍生,但就是不会消亡。
具有鲜明主题的论坛将持续存在且越来越活跃。经过无数网络平台的大浪淘沙,依然人气不减的存在,就是主题鲜明的专业论坛。比如摄影主题下的色影无忌、蜂鸟论坛等等。论坛的字数一般很多,图文并茂,可以以数千上万字来诠释一个专业的主题,加上精华和热门的筛选机制,使得优质的内容可以类似电子版图书一般持久存在,即使论坛一时间人气不足,凭借优质的精华内容,依然可以吸引很多新手来到论坛中进行系统化的学习。
动漫在国内外作为近年来兴起的未来发展空间无限的产业,以及在互联网上经久不衰的论坛,二者的结合使得动漫主题得以延续,借助动漫火爆热度的同时,论坛的功能与结构得以拓展。
1.3系统的主要研究内容
首先对本课题的主要研究题目——《动漫论坛BOKI》诠释如下:
对于日渐增多的动漫爱好者社团活动的需求,我们决定实现一个为动漫爱好者定制的论坛系统,实现动漫爱好者彼此之间的线上交互。作为论坛,首要目标就是要实现用户界面的美观,可读性,以及用户发帖和对帖子的阅读。
随着Internet技术的快速发展,BBS论坛在网络上已成为人们彼此沟通、交流信息的主要方式。在论坛上,人们可以对某一领域提出自己遇到的问题,随后,论坛上的其他人会根据自己的学识、经验发表意见或提出问题的方法。BBS论坛接近了人们之间的距离,它早已成为人们网上生活的必备工具。所以说BBS论坛对当今社会是相当重要的。
论坛配备有管理端系统,能够很好地提高管理员的工作效率和降低工作量。论坛基于SpringCloud框架制作,维护人员也能够较好进行维护。
需要解决的主要问题是:该论坛能否完成发帖和回复、用户个人信息管理、帖子调控等这几个问题,以及服务端之间的协调。
动漫论坛《BOKI》可分为包括以下几个子系统:
1.4系统开发环境与开发工具
系统开发环境配置 :windows 10系统,8GB运行内存。CentOS 7虚拟机一台,1GB运行内存。
开发环境及其开发工具:jdk1.8,ideaIU,Mysql server,redis。
以下是系统主要使用的研究方法和关键技术:
论坛的发帖和回复应该呈现一个关联的状态,即每个主题对应的回复都有严格的关联。以及用户的权限,个人信息的维护,关注、动态、私信、举报、以及系统发生错误时对客户端的回复等实现,需要借助的方法和技术也多种多样。以下技术归纳有:
1、SpringCloud框架:SpringCloud框架使得服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率。可以更精准的制定优化服务方案,提高系统的可维护性。微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量。适于互联网时代,产品迭代周期更短。
2、Myabatis:Mybatis是一种持久层框架,也属于ORM映射。mybatis为半自动化,需要自己书写sql语句,需要自己定义映射。增加了程序员的一些操作,但是带来了设计上的灵活,并且也是支持hibernate的一些特性,如延迟加载,缓存和映射等;对数据库的兼容性比hibernate差。移植性不好,但是可编写灵活和高性能的sql语句。
3、Thymeleaf:thymeleaf是一种Java模板引擎,模板引擎就是为了使用户页面和业务数据相互分离而出现的,将从后台返回的数据生成特定的格式的文档,这里说的特定格式一般都指HTML文档。它能够处理html、xml、js、css甚至纯文本,类似于freemarker。它的优点是语法优雅易懂、原型即页面、遵从web标准。原型即页面是它的特色。
4、eureka:Eureka是基于REST(Representational State Transfer)服务,主要以AWS云服务为支撑,提供服务发现并实现负载均衡和故障转移。我们称此服务为Eureka服务。Eureka提供了Java客户端组件,Eureka Client,方便与服务端的交互。客户端内置了基于round-robin实现的简单负载均衡。
5、feign:Feign是一个声明式的Web服务客户端,使用Feign可使得Web服务客户端的写入更加方便。它具有可插拔注释支持,包括Feign注解和JAX-RS注解、Feign还支持可插拔编码器和解码器、Spring Cloud增加了对Spring MVC注释的支持,并HttpMessageConverters在Spring Web中使用了默认使用的相同方式。Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的http客户端。
6、hystrix:给依赖于第三方库的应用程序提供给保护,在复杂的分布式系统当中避免级联失败,快速失败并且快速恢复,在可能的情况下提供回退和优雅降级的能力,通过近乎实时的指标,监控和警报来优化发现故障的时间。
7、mysql:MySQL体积小,命令执行的速度快。MySQL是开源的,且提供免费版本,对大多数用户来说大大降低了使用成本。与其他大型数据库的设置和管理相比,其复杂程度较低,易于使用。MySQL能够运行与多种系统平台上,如windouws,Linux,Unix等。支持最常用的数据管理功能,适用于中小型企业甚至大型网站应用。
8、redis:一般部署在linux系统中。速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O。并且支持丰富数据类型,支持string,list,set,sorted set,hash。支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除。
9、centOS7:用于部署持久化数据服务。作为免费开源的系统。centOS7是一款完全免费的操作系统,任何人都可以从网络上下载到它的源代码,并可以根据自己的需求进行定制化的开发,而且没有版权限制。
10、腾讯邮箱服务:腾讯出品的邮箱服务,用于用户注册时进行账户修改密码时进行邮箱验证。
上面介绍的论坛开发的常用技术,可以完成这些任务,不同技术完成的任务和侧重点有很大不同。
第2章 系统需求分析
需求分析,指对用户的实际需求进行调查,分析和表达这些需求以达成共识。需求分析包括以下步骤:一、对用户想要解决的问题和想法进行详细的分析,分层次的分析。二、将客户需求转化为系统业务需求,形成对系统分析的完整和特定要求。三、对先面的调查结果进行初步分析,以确定系统的功能。四、根据后续需求拓展业务。
2.1 系统的核心业务流程分析
本文在项目系统中的主要工作是对论坛客户端的客户端的业务流程进行分析与展示。在该论坛的用户客户端,水友和论坛职务人员用户可以通过论坛的发帖和回复功能进行相应的交流,以及对个人信息进行更新等等。
论坛客户端发帖与回复流程如图2-1所示。
图2-1 系统核心业务流程图
此发帖流程。以已游客客户端软件用户浏览帖子至登陆发帖为的业务流程为例。当用户打开论坛首页时,无论是否登陆该论坛,均可以浏览帖子信息。未授权的游客用户提交功能功能不能使用,包括发帖、回复、个人信息等进行提交的操作;登陆后的合法用户用户浏览帖子过程中,可以将喜欢的对感兴趣的帖子尽兴回复,或者发帖与爱好者一同讨论。发帖或回复完毕完后,在可继续对帖子进行浏览。
2.2 系统的整体功能需求分析
论坛系统将会分为两大模块进行设计,分别是用户功能模块和管理员功能模块。
系统用户功能模块如图所示:
图2-2 系统用户模块功能结构图
系统管理员功能模块如图所示:
图2-2 系统管理员模块功能结构图
2.3 动漫论坛系统功能需求
通过分析动漫论坛功能模块,可以确定为动漫论坛分为两大用户,一般用户和管理员用户。一般用户未登录时可以对帖子进行浏览,但不能进行任何提交操作。用户登陆后可以进行其他操作,发帖,回复,个人信息管理等等。。
2.3.1参与者
系统参与者之间的 关系如下角色层次图所示:
参与者说明:
一般用户:论坛的核心成员,可以执行用户发帖、关注、动态、私信、回复、举报等用户交互操作。享受登陆、维护个人基本信息、等级、收藏、删帖、信用度,违规受罚等权益。
游客:游客基本权限为注册,浏览。不提供注册以外的任何提交数据的权限和操作。
管理员:论坛的核心成员,可以执行用户发帖、关注、动态、私信、回复等用户交互操作,但没有用户权益模块的所有子功能。额外享有较高的权限,包括帖子置顶、论坛数据总览、查看用户信用度、查看用户违规情况、查看用户发帖记录,对用户删帖、警告、关小黑屋等等权限。
2.3.2用户客户端基础功能需求
下面是对图2-2 系统用户模块功能结构图的基本功能模块的详细解释:
(1)登录模块
主要包括用户登录和权限分配管理。
用户已有账号,在登陆界面,输入【邮箱】【密码】登陆即可。默认为【水友】权限,即一般用户权限。
(2)用户互动模块:作为用户在论坛上活跃的手段。用户除了最基本的浏览之外,还应该具有互动的方式,该模块实现了用户之间的互动。该子系统包括以下模块:
①发帖子模块:
作为论坛最基本的功能,发帖是必备的一项。
用户在已经的登陆的状态下,在论坛发帖处输入【主题】【内容】之后点击【发送】即可发帖;
②关注子模块
用户之间必须拥有能够多对多的关注。
用户在对另一个用户的【关注】按钮点击之后,实现添加到关注列表,关注后可收到对方的发帖通知。
③动态与消息子模块。
用户所关注的对象的动态应及时通知到用户,用户被回复时必须【通知】到用户。
④私信子模块
不作为帖子发送的信息,属于私人发送信息。
用户点击对方【私信】按钮,打开会话,输入【内容】,点击【发送】,对方收到私信【通知】,可进行回复操作,输入【内容】,点击【发送】。
⑤回复子模块
除了基本的回复(俗称“楼层”),该模块支持了二级发帖(俗称“楼中楼”)。
用户在进入帖子之后,在帖子的回复处输入【内容】,之后点击【发送】即可发送回复。
用户在对楼层进行二级回复,在楼层的回复处输入【内容】,之后点击【发送】即可发送回复。
⑥举报子模块
对违规帖子进行举报。
用户在帖子的【举报】按钮,输入【理由】,点击【提交】,帖子将进入审核状态。
(3)用户权益模块:用户在论坛上享受的权力与义务,在该系统上展现出来,根据用户的行为与习惯,对用户本身的评价。该子系统包括以下模块:
①注册子模块
新用户注册。
游客用户进行注册,首先进入注册页面,输入【昵称】【邮箱】【密码】之后,点击【发送验证码】,用户在自己的邮箱收到验证码之后将验证码填入【验证码】,完成注册。
②基本信息子模块
用户基本信息完善与修改;
用户进入【个人信息】页面,修改信息后点击【完成】即可完成个人信息的提交。
③等级子模块
根据用户经验代表的用户资质。
根据发帖程度决定【经验值】,【经验值】决定【等级】,每次发帖经验值+5,回复帖子经验值+2,被回复时+1,【经验值】不受自己回复自己的叠加。
④收藏子模块
在帖子【收藏帖子】按钮点击,可收藏帖子到【我的收藏】列表。以便用户随时找到该贴。
⑤删帖子模块
用户删除自己的帖。
用户对自己的帖子进行【删除】操作,出现确认窗口之后,【确认】即可删除。只能对自己发送的帖子删除,不能删除其他人的帖子。
当帖子被删除,帖子所包含的回复也应该一同被【清除】。
⑥信用度子模块
信用度过低,用户权益将受到一定程度的限制。
用户每次被管理员删帖,【信誉值】将会降低10点,初始值为100点。被删除回复时【信誉值】-5。【信誉值】每天+1,直到150。
⑦违规子模块
用户违规,将被处罚。
【信誉值】低于50将收到小黑屋触发,即封号处理。
2.3.3管理员客户端基础功能需求
下面是对图2-2 系统用户模块功能结构图的基本功能模块的详细解释:
(1)登录模块
主要包括用户登录和权限分配管理。
用户已有账号,在登陆界面,输入【邮箱】【密码】登陆即可。默认为【小站长】权限,即管理员权限。
(2)论坛总览模块
包括一个子模块,在【论坛总览】页面,其功能具有帖子数量总览,在线用户数量,作为用户活跃度展示。数据总览。
(3)用户信息模块:管理员可以对某一用户的违规记录和发帖记录进行查看。该子系统包括以下子模块:
①违规处理子模块
查看用户违规情况及其日志。
在【用户列表】中通过输入【用户ID】或【用户名】作为条件进行查询,在【查看详情】页面浏览用户违规情况。
②发帖记录子模块
用户一段时间内的发帖记录。
在【用户列表】中通过输入【用户ID】或【用户名】作为条件进行查询,在【查看详情】页面浏览用户发帖情况。
(4)赏罚模块:根据用户行为为用户赋予荣誉勋章,或者删帖、禁封账号等处理,该子系统包括以下子模块:
①删帖子模块
管理员有最高权限的删帖能力。
在帖子浏览过程中,管理员点击【删除】按钮,输入【理由】进行删帖,被删贴用户将收到删帖【通知】。
②小黑屋子模块
禁封非法用户,违规用户。
在【用户列表】中通过输入【用户ID】或【用户名】作为条件进行查询,点击【禁封】,输入【禁封时长】,完成禁封。
③信誉度勋章模块
表彰用户资质与素质的奖励。
根据信用度决定【勋章等级】,详细数据可在数据库中决定。
④帖子装饰模块
该系统功能不多,但对论坛浏览起关键作用,能够对帖子进行置顶,和对贴纸升级为精华贴。
在帖子浏览中,对帖子点击【升华】,帖子即被升级为精华贴。
在帖子浏览中,对帖子点击【置顶】,帖子即被升级为置顶贴,需要设置置顶持续天数。
2.4 本章小结
本章主要分析《BOKI》论坛的具体需求。在对论坛的基本需求的确定时,除了其中确定的基本需求,开发过程中可能需要针对其中的一些需求做出调整。论坛总体,不论用户客户端还是管理员客户端,需求都是比较明确的,这一点非常体现一个论坛的运转与管理方式。
第3章系统的设计与实现
详细的系统设计是本论坛系统核心,根据所提供的需求以设计符合需求的系统,基于论坛的基本上一章的基本功能需求,设计了该系统。包括系统总体框架的设计、数据库设计、系统详细设计,以及在文中末尾对本章做了总结。
3.1 系统总体架构设计
系统的总体设计分为两个核心后端系统,分别是用客户端系统和管理端系统,如图3-1所设计。系统通过必要的后端组件对客户端系统和管理端系统的运转进行支持,消息通知与验证码等非持久化数据信息将存储在redis缓存中,如有必要,redis还能作为数据库缓存使用。数据库使用mysql。由于一般用户和管理员都属于用户的分支,且拥有相似的功能权限,故使用同一个数据库,方便数据管理。/
图3-1 系统总体框架图
3.2 数据库设计
设计合适的数据库是最基础和最核心的,能够对数据进行持久化。本系统选用mysql 数据库,它具有以下优势:
(1)更好的读写性能,因为和windows framework绑定一起,底层操作系统级优势。而mysql则有可能oom,被linux无差别清理掉;
(2)数据可靠性更好:数据安全,一致性;
(3)存储过程。oracle和mssql都有强大的存储过程,银行系统甚至有规定凡是和资金相关的逻辑必须写在存储过程里,禁止写在应用程序里。而mysql的存储过程则一直是鸡肋。用c语言写的扩展存储过程,即运行在数据库内存中的程序代码,两个都支持,这个不在讨论范围;
(4)方便的性能监控。打开profiler,可以在生产环境中实时看各个query的执行详情,还可以按需过滤,而且不影响系统性能之内。
3.2.1 概念结构设计
概念结构设计是将用户需求抽象为信息结构,E-R图是常用模型。E-R图由实体、属性、联系组成。正方形表示的是实体,椭圆形表示的是属性。实体间联系分为:一对一、一对多、多对多,共三种。该动漫论坛系统主要实体信息如下:
(1)用户信息实体图如图3-2。
图3-2 用户信息实体图
(2)帖子信息实体图如图3-3。
图3-3 帖子信息实体图
(3)楼层信息实体图如图3-4。
图3-4 楼层信息实体图
(4)楼中楼(二级回复)回复信息实体图如图3-5。
图3-5 楼中楼(二级回复)信息实体图
由系统实体及实体间的关系得出该论坛系统的总体E-R图。
一对一关系有:用户表对用户表(私信)。
一对多关系有:用户表与帖子表、用户表与楼层表、用户表与楼中楼表、帖子表与楼层表、楼层表与楼中楼表。
多对多关系有:用户表与用户表(关注)。
矩形表示实体,椭圆形表示属性,菱形表示联系。如图3-6所示:
图3-6 总体E-R图
3.2.2 逻辑结构设计
将概念结构设计的E-R图转换成为逻辑结构,确定关系模式属性和码。根据关系的需求将会对系统表添加关系表,系统的数据模型以数据表的形式展现。数据库表详细设计如下:
(1)用户信息基本数据表user,如表3-1。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
mail varchar 否 邮箱
pwd varchar 否 密码
user_name varchar 否 昵称
photo varchar 是 头像url
sex varchar 否 保密 性别
birth date 否 1970-01-01 生日
come_from varchar 是 来自
exp int 否 0 经验值
credit_degree int 否 100 信用度
role_id int 否 1 职位
intro varchar 是 自我介绍
show varchar 是 个性签名
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-1 用户信息表
(2)帖子信息基本数据表boki_post,如表3-2。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
user_id int 否 楼主id
title varchar 否 标题
content varchar 否 内容
last_replier_id int 否 最后回复者id
replies_count int 否 0 回复数
type_id int 否 1 帖子类型
is_top varchar 否 n 是否置顶
report_status int 否 1 举报状态
report_reason int 是 举报理由
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-2 帖子信息表
(3)楼层信息基本数据表boki_reply,如表3-3。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
post_id int 否 所属帖子id
user_id int 否 层主id
floor_no int 否 第x楼
content varchar 否 内容
replies_count int 否 0 楼层回复数
report_status int 否 1 举报状态
report_reason varchar 否 举报理由
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-3 楼层表
(4)楼中楼(二级回复)基本数据表orderDetail,如表3-4。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
storey_id int 否 所属楼层id
user_id int 否 回复者id
content varchar 否 内容
report_status int 否 1 举报状态
report_reason varchar 否 举报理由
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-4 楼中楼信息表
(5)私信信息基本数据表boki_whisper,如表3-5。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
first_user_id int 否 甲
second_user_id int 否 乙
show_in_first varchar 否 y 在甲列表显示
show_in_second varchar 否 n 在乙列表显示
last_content varchar 否 最后一条私信
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-5 私信信息表
(6)私信内容信息基本数据表boki_whisper_detail,如表3-6。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
whisper_id int 否 私信id
user_id int 否 发送方
target_user_id int 否 接收方
content varchar 否 内容
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-6 私信内容信息表
(7)黑名单信息基本数据表boki_blacklist,如表3-7。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
user_id int 否 用户
target_user_id int 否 被拉黑用户
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-7 boki_blacklist信息表
(8)关注基本信息表boki_follow,如表3-8。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
user_id int 否 粉丝
target_user_id int 否 被关注者
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-8 关注信息表
(9)帖子收藏基本信息表boki_collection,如表3-9。
字段名 类型 是否为空 缺省值 中文
id int 否 主键
user_id int 否 用户
post_id int 否 收藏帖子
title varchar 否 帖子标题
create_time timestamp 是 CURRENT_TIMESTAMP 创建时间
modified_time timestamp 是 CURRENT_TIMESTAMP 更新时间
creator varchar 是 创建人
modifier varchar 是 修改人
is_deleted varchar 是 n 删除标记
表3-9 帖子收藏表
3.3 客户端子系统详细设计
由于该系统整体上使用了前后端分离的设计理念,后端使用springcloud的一些组件以实现服务之间的对接,后端统一数据请求接口为负载均衡ribbon,对该服务的请求会被转发到对应的客户端服务或对应的管理端服务。由于使用了请求转发,以及前后端分离,传统的通过session存储当前用户信息(id、userName、sessionId等)将不再生效,因此设计分离时将寻找新的认证方式。
3.3.1 客户端后端接口设计
在使用前后端分离的开发过程中,由于前后端数据对接是主要是前端对后端的接口请求以达到数据增删改查的目的,因此在设计过程中对接口明确定义能够提高开发方向和提升开发效率。
ribbon接口入口:http://localhost:8001/
(1)登录模块接口设计
① 登陆
登陆请求:
post请求:http://localhost:8001/cli/login
请求数据:邮箱mail、密码pwd
(2)用户互动模块
① 发帖
发帖请求,需要登陆后才能发帖
post请求:http://localhost:8001/cli/post/send
数据:主题title、内容content
② 关注
关注他人
post请求:http://localhost:8001/cli/user/addFollow/{targetUserId}
从关注列表中移除
post请求:http://localhost:8001/cli/user/removeFollow/{targetUserId}
打开关注列表
get请求:http://localhost:8001/cli/user/followList?page=
我的粉丝
get请求:http://localhost:8001/cli/user/myFans?page=
③动态与消息
获取通知数量
get请求:http://localhost:8001/cli/notice/count
打开通知列表
get请求:http://localhost:8001/cli/notice/list
移除一条通知
post请求:http://localhost:8001/cli/notice/remove/{id}
清空通知列表
post请求:http://localhost:8001/admin/login
④ 私信
发起或打开私信
post请求:http://localhost:8001/cli/whisper/open/{targetUserId}
发送私信
post请求:http://localhost:8001/cli/whisper/send
数据:私信id、对方的userId、内容content
打开私信列表
get请求:http://localhost:8001/cli/whisper/list?page=
从列表中移除私信
post请求:http://localhost:8001/cli/whisper/remove/{id}
拉黑
post请求:http://localhost:8001/cli/whisper/addBlacklist/{targetUserId}
黑名单
get请求:http://localhost:8001/cli/whisper/blacklist?page=
从黑名单中移除
post请求:http://localhost:8001/cli/whisper/removeBlacklist/{blacklistId}
⑤ 回复
打开帖子,这是论坛最基本的帖子浏览功能
get请求:http://localhost:8001/cli/p/{postId}?page=
加载楼层回复数据,加载二级回复
get请求:http://localhost:8001/cli/p/reply/open?id=&page=
回帖请求,需要登陆后才能回帖
post请求:http://localhost:8001/cli/post/reply/send
数据:帖子id、内容content
回复层主,二级回复也需要登陆
post请求:http://localhost:8001/cli/post/storeyReply/send
数据:楼层storeyId、内容content
⑥ 举报
举报帖子
post请求:http://localhost:8001/cli/post/report
数据:帖子id、举报理由reason
举报楼层
post请求:http://localhost:8001/cli/post/reply/report
数据:楼层id、举报理由reason
举报二级回复
post请求:http://localhost:8001/cli/post/storeyReply/report
数据:二级回复id、举报理由reason
(3)用户权益模块
①注册与改密
校验码发送请求,这是用于注册和修改密码时获取校验码的请求:
get请求:http://localhost:8001/cli/login/sendCheckCode/{mail}
注册请求,注册时需要校验码:
post请求:http://localhost:8001/cli/login/register
请求数据:邮箱mail、密码pwd、昵称userName、校验码checkCode
改密请求,修改密码、找回密码的请求,需要配合校验码进行改密:
post请求:http://localhost:8001/cli/login/modifyPwd
数据:邮箱mail、新密码pwd、校验码checkCode
②基本信息
用户个人信息
get请求:http://localhost:8001/cli/user/info
修改个人信息
post请求:http://localhost:8001/cli/user/modifyInfo
数据:性别sex、生日birth、来自from、简介intro、签名show、
更改头像
post请求:http://localhost:8001/cli/user/modifyPhoto
数据:头像url
我的发帖历史
get请求:http://localhost:8001/cli/user/replyHistory?page=
我的回复历史
get请求:http://localhost:8001/cli/user/replyHistory?page=
③ 等级
用户等级功能不对外暴露任何接口。
④收藏
收藏帖子
post请求:http://localhost:8001/cli/user/collect/{postId}
移除收藏的帖子
post请求:http://localhost:8001/cli/user/removeCollection/{postId}
帖子收藏列表
get请求:http://localhost:8001/cli/user/postCollection?page=
⑤删帖
删除帖子
post请求:http://localhost:8001/cli/post/delete/{id}
删除楼层
post请求:http://localhost:8001/cli/post/reply/delete/{id}
删除楼中楼
post请求:http://localhost:8001/cli/post/storeyReply/delete/{id}
⑥ 信誉度
信誉度模块不对外暴露任何接口。
⑦ 违规
违规在用户客户端不提供任何接口。
⑧ 其他
图片上传
post请求:http://localhost:9001/image/upload
数据:图片fileName
图片下载
get请求:http://localhost:9001/images/{fileName}
3.3.2 客户端关键代码与难点实现
(1)请求拦截
由于这是一个开放性的动漫论坛,在设置请求拦截的时候,应该避免未登录的游客正常浏览被拦截导致无法看到帖子或其他开放内容。系统接口设计中,大部分接口属于需要验证的接口,因此在设置请求拦截时我选择了拦截所有请求,并开放部分接口。关键代码如下:
InterceptorRegistration registration = registry.addInterceptor(clientInterceptor);
registration.addPathPatterns(“/");
registration.excludePathPatterns(
"/p/”, //开放性页面
“/”, //首页
“/login/register”, //注册
“/login/sendCheckCode/*”, //发送邮箱校验码
“/login”, //登录
“/static/**” //静态资源
);
(2)登陆校验
在本动漫论坛中,属于前后端分离开发,且后端是微服务架构风格,因此传统的HttpSerevletSsession 将无法继续用于存储临时信息。本系统后端token+redis的形式,认证用户登陆,关键代码如下:
userId = JWT.decode(token).getAudience().get(0);
Map tokenCache = redisTemplate.opsForHash().entries(Common.TOKEN + userId);
if (tokenCache.size() == 0){
throw new BusinessException().setType(RequestResultCode.LOGIN_TODO);
}
String time = tokenCache.get(“time”).toString();
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256( time )).build();
jwtVerifier.verify(token);
redisTemplate.expire(Common.TOKEN + userId, 1800, TimeUnit.SECONDS);
附加了@TOKEN注解的方法,每次被请求都将执行一次校验,使用redis临时存放token,token有效期为半个小时,每次请求后刷新有效期。
在负载均衡服务端使用了请求模板,请求时将头部将带上TOKEN字段。
@Bean
public RequestInterceptor requestInterceptor(){
return requestTemplate -> {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(null != attributes){
HttpServletRequest request = attributes.getRequest();
if (request.getHeader(TOKEN) != null) {
requestTemplate.header(TOKEN, request.getHeader(TOKEN));
}
}
};
}
(3)邮箱校验码
邮箱校验码使用了腾讯提供的qq邮箱服务,配合spring框架提供的邮箱发送类进行验证邮件的发送。
@Autowired
private JavaMailSenderImpl mailSender;
验证码采用即时生成8位数字的方式,生成后5分钟内有效。
public String randomCode(){
Random random = new Random();
String code = random.nextDouble() + “”;
code = code.substring(code.length()-8);
return code;
}
(4)全局异常捕获
一个系统,使用时,会不可避免地发生异常,但是如果异常被清晰地展示到页面上,比如404错误,403错误,或者后端错误日志打印等,这是非常不可取的,必须采取措施。
本论坛采用了spring提供的一个全局异常处理功能,配合我所写的BusinessException自定义运行时异常类,实现代码异常时也能够给返回有效的信息。
全局异常:
@ControllerAdvice
public class BokiExceptionHandler{…}
自定义BusinessException
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ResultVO handleValException(BusinessException e){
if (e.getMessage() != null) {
log.warn(“原因:” + e.getMessage());
}
if ( e.getType() != null ) {
log.info(e.getType().getCode()+e.getType().getMsg());
return e.getType().getResult().setData(e.getInfo());
}else {
log.info(RequestResultCode.SERVER_ERROR.getCode()+RequestResultCode.SERVER_ERROR.getMsg());
return RequestResultCode.SERVER_ERROR.getResult();
}
}
(5)用户等级的制定
用户等级的制定参考了较为成熟的百度贴吧,等级划分为1到10级,依次需要经验值0,100,300,1000,3000,6000,10000,15000,22000,30000,每次发帖+5点经验,每次回帖+3经验,每次二级回复+2经验,发送成功后进行结算。使用线程进行结算,关键代码:
发帖经验结算:
//经验+5,告辞
postDao.updateExpById(dto.getUserId(), 5);
回帖经验结算:
//经验结算,楼主回复自己的贴,经验+2
if(postDao.findPostByIdAndUser(dto.getPostId(),dto.getUserId()) != 0){
postDao.updatePosterSendReply(po);
//非楼主回帖,帖子回帖数更新,楼主经验+1,层主经验+3
}else{
postDao.updateReplierSendReply(po);
}
二级回复经验结算:
//经验结算,楼主回复自己的贴,经验+2
if(postDao.findPostByIdAndUser(dto.getPostId(),dto.getUserId()) != 0){
postDao.updatePosterSendReply(po);
//非楼主回帖,帖子回帖数更新,楼主经验+1,层主经验+3
}else{
postDao.updateReplierSendReply(po);
}
(6)信誉度与奖赏的挂钩
用户初始信誉度为100,每天将会+1,直到150点。当用户信誉度低于30的时候将会被封禁,直到信誉度达到50点时解封。每次被管理员删帖将会减少10点信誉度,删楼将会减少5点信誉度,删除二级回复将会减少5点信誉度。使用mysql定期事件执行任务。
(7)动态与消息的实现
通知的实现使用了通知生成类,统一管理了通知的生成。
public enum NoticeMessage {
/*** 类型 1 私信通知*/
TYPE_1(1,"%s 在私信中回复了你:“%s”。"),
TYPE_2(2,"%s 在“%s” %s楼回复了你:“%s”。"),
TYPE_3(3,"%s 在“%s” %s楼 @了你。"),
TYPE_4(4,"您的帖子“%s”被管理团队删除,原因是%s,您的信誉值-10。"),
TYPE_5(5,"您的楼层“%s”被管理团队删除,原因是%s,您的信誉值-5。"),
TYPE_6(6,"您的回复“%s”被管理团队删除,原因是%s,您的信誉值-5。"),
TYPE_7(7,"您关注的大佬 %s 发帖了:“%s”。");private Integer type;
private String raw;
但是通知生成后可能会发送给许多人,不可避免地占用请求时间,此时有两个实现思路:方案一、使用线程发送通知,可能有大量通知需要发送。方案二、由用户获取通知,可能有大量通知需要获取。
鉴于我所设计的系统属于中小型系统,因此采取了方案一生成并发送通知。
(8)结果数据类
返回数据使用统一的数据类,其中泛型装载了返回的数据主体。
@Data
@Accessors(chain = true)
public class ResultVO {
private Integer code;
private String msg;
private T data = null;
}
其中的状态code和附带信息由枚举类RequestResultCode提供,以下为部分代码:
public enum RequestResultCode {
/**
* 数据错误
*/
ERROR_MAIL(2001,“邮箱格式错误.”),
ERROR_DATE(2001,“错误的日期.”),
MAIL_ALREADY_EXIST(1000,“邮箱已被注册.”),
统一的数据格式使得请求后获得的数据能够容易地被处理和分析。
3.4 管理端子系统详细设计
由于该系统整体上使用了前后端分离的设计理念,后端使用springcloud的一些组件以实现服务之间的对接,后端统一数据请求接口为负载均衡ribbon,对该服务的请求会被转发到对应的客户端服务或对应的管理端服务。由于使用了请求转发,以及前后端分离,传统的通过session存储当前用户信息(id、userName、sessionId等)将不再生效,因此设计分离时将寻找新的认证方式。
在使用redis缓存认证信息后,管理端的认证也能够通过用户客户端共享,极大方便了管理端的开发流程。
3.4.1 管理端后端接口设计
(1) 登录模块接口设计
① 登陆
登陆请求:
post请求:http://localhost:8001/cli/login
请求数据:邮箱mail、密码pwd
(2)论坛总览模块
①数据总览
数据统计接口
get请求:http://localhost:8001/admin/statistics
(3)用户信息模块
①违规处理
帖子举报待审核列表
get请求:http://localhost:8001/admin/post/report/{type}?page=
驳回举报
post请求:http://localhost:8001/admin/post/report/reject
数据:举报类型type、id、执行者userId、
举报通过
post请求:http://localhost:8001/admin/post/report/pass
数据:举报类型type、id、执行者userId、理由reason
②发帖记录
用户列表,条件查询
get请求:http://localhost:8001/admin/user/list?elem= &maxLevel= &minLevel= &maxCreditDegree= &minCreditDegree= &isBanned= &page=
用户精准查询
get请求:http://localhost:8001/admin/user/info?idOrMail=
用户发帖历史
get请求:http://localhost:8001/cli/user/replyHistory?page=
用户回复历史
get请求:http://localhost:8001/cli/user/replyHistory?page=
(4)赏罚模块
①删帖
不提供直接删帖接口,管理员删帖应该通过举报流程。
②小黑屋
封禁用户
post请求:http://localhost:8001/admin/user/ban
数据:目标用户userId、封禁天数days、
解封用户
post请求:http://localhost:8001/admin/user/release/{userId}
③信誉度
信誉度不暴露任何接口,而是根据用户行为结算。
(5)帖子装饰
①帖子加精或降级
post请求:http://localhost:8001/admin/post/upgrade
数据:加精或降级type、帖子postId
②帖子置顶
post请求:http://localhost:8001/admin/post/setTop
数据:帖子postId、置顶天数topDays
(6)其他
晋升或贬职,站长权力
post请求:http://localhost:8001/admin/user/role/change
数据:用户id、角色roleId
3.4.2 管理端关键代码与难点实现
(1)关于用户举报审核成功被管理员删帖的情况,应该发送通知给被删贴用户。假如用户被删贴却得不到任何通知,这并不友好。
NoticePO po = new NoticePO()
.setUserId(elem.getTargetUserId())
.setCreator(elem.getFromUserId().toString())
.setNotice( msg.createNotice(elem))
.setTypeId(msg.getType());
//持久化一条通知
noticeDao.insertNotice(po);
//设置通知数
setKeyValueByUid(elem.getTargetUserId());
(2)管理员删帖时应该把该帖子下的所有楼层和二级回复,同时被举报用户信誉值应该被结算。
– 删帖,连同回复,楼中楼一起删
UPDATE boki_post SET is_deleted = ‘y’,report_status = 3, report_reason = #{reason}
WHERE id = #{id} AND user_id = #{userId} AND report_status = 2;
UPDATE boki_reply SET is_deleted = ‘y’ WHERE post_id = (
SELECT id FROM boki_post WHERE id = #{id} AND user_id = #{userId} AND report_status = 3
);
UPDATE boki_storey_reply bsr,(
SELECT br.id brid FROM boki_reply br
JOIN boki_post bp ON br.post_id = bp.id
WHERE bp.id = #{id} AND bp.user_id = #{userId} AND bp.report_status = 3
) a SET bsr.is_deleted = ‘y’ WHERE bsr.storey_id = a.brid;
– 被举报者信誉值结算 -10
UPDATE boki_user SET credit_degree = credit_degree-10 WHERE id = #{userId} AND role_id != 3;
(3)管理员删楼时应该连同所包含的楼中楼一起删除,同时帖子显示的回复数减少n+1,n表示楼层对应的楼中楼数。同时被举报用户信誉值应该被结算。
– 删楼,连同楼中楼一起删
– 帖子回复数 -(1 + n)(n 楼中楼数量)
UPDATE boki_post SET replies_count = replies_count - (
SELECT COUNT(1)+1 FROM boki_storey_reply WHERE storey_id = #{id} AND is_deleted = ‘n’
) WHERE id =(
SELECT post_id FROM boki_reply WHERE id = #{id} AND user_id = #{userId} AND floor_no != 1
AND is_deleted = ‘n’ LIMIT 1
);
UPDATE boki_reply SET is_deleted = ‘y’,report_status = 3, report_reason = #{reason}
WHERE id = #{id} AND user_id = #{userId} AND floor_no != 1 AND report_status = 2;
UPDATE boki_storey_reply SET is_deleted = ‘y’ WHERE storey_id = (
SELECT id FROM boki_reply WHERE id = #{id} AND user_id = #{userId} AND floor_no != 1 AND report_status = 3
);
– 被举报者信誉值结算 -5
UPDATE boki_user SET credit_degree = credit_degree-5 WHERE id = #{userId} AND role_id != 3;
(4)管理员删楼中楼时,所属的楼层回复数减1,所属的帖子回复数减1,被举报者信誉值-5。
– 删除楼层回复
– 帖子回复数-1
UPDATE boki_post SET replies_count = replies_count -1 WHERE id =(
SELECT br.post_id FROM boki_reply br
JOIN boki_storey_reply bsr ON br.id = bsr.storey_id
WHERE bsr.id = #{id} AND bsr.user_id = #{userId}
);
– 楼层回复数-1
UPDATE boki_reply SET replies_count = replies_count - 1 WHERE id =(
SELECT storey_id FROM boki_storey_reply WHERE id = #{id} AND user_id = #{userId}
);
UPDATE boki_storey_reply SET is_deleted = ‘y’,report_status = 3, report_reason = #{reason}
WHERE id = #{id} AND user_id = #{userId} AND report_status = 2;
– 被举报者信誉值结算 -5
UPDATE boki_user SET credit_degree = credit_degree-5 WHERE id = #{userId} AND role_id != 3;
3.5 前端服务器详细设计
由于该系统整体上使用了前后端分离的设计理念,前端使用国内较为成熟的VUE框架惊醒开发工作。选择VUE,是因为VUE具备了上手简单,技术沉淀厚,语法简易,沿用了js的数据风格,配合axios进行数据请求。另外,VUE的数据驱动视图的理念也非常符合近年来的web系统开发理念。前端的开发工具也有非常多,我在设计这个前端时,使用vscode进行开发,它的风格与idea接近,即使是新人也能快速上手。
VUE前端框架,加入element UI,配合scss进行页面开发,使界面美观整洁。
3.5.1 前端路由配置
VUE的路由配置决定了论坛的各个组件的访问地址,由于VUE倾向于单页面开发,因此在这只路由地址的时候需要规范地使用组件对应的地址。
论坛的地址基本配置如下:
const router = new VueRouter({
// mode: ‘history’,
mode: ‘hash’,
base: process.env.BASE_URL,
routes:
[
{path: ‘/p/:postId’,component: PostDetail,},
{path: ‘/’,component: Main,},
{path: ‘/register’,component: Register,},
{path: ‘/modifyPass’,component: ModifyPass,},
{path: ‘/user’,component: User,redirect:‘/user/info’,
children:[
{path: ‘/user/info’,component: UserInfo,},
{path: ‘/user/notice’,component: UserNotice,},
{path: ‘/user/collecion’,component: UserCollection,},
{path: ‘/user/follew’,component: UserFollew,},
{path: ‘/user/fans’,component: UserFans,},
{path: ‘/user/whisper’,component: UserWhisper,},
{path: ‘/user/blacklist’,component: UserBlanklist,},
{path: ‘/user/history/Post’,component: UserHistoryPost,},
{path: ‘/user/history/Reply’,component: UserHistoryReply,},
{path: ‘/user/‘,redirect:’/unfound’}
]
},
{path: ‘/UID:userId’,component: OtherUser,redirect:‘/UID:userId/info’,
children:[
{path: ‘/UID:userId/info’,component: OtherInfo,},
{path: ‘/UID:userId/history/last’,component: OtherHistoryLast,},
{path: ‘/UID:userId/history/post’,component: OtherHistoryPost,},
{path: ‘/UID:userId/history/reply’,component: OtherHistoryReply,},
{path: '/UID:userId/’,redirect:‘/unfound’}
]
},
{path:‘/admin’,component:Administrator,redirect:‘/admin/Statistics’,
children:[
{ path: ‘/admin/statistics’,component: Statistics},
{ path: ‘/admin/report/post’,component: JudgePost},
{ path: ‘/admin/report/storey’,component: JudgeStorey},
{ path: ‘/admin/report/storeyReply’,component: JudgeStoreyReply},
{ path: ‘/admin/users’,component: UserList},
{ path: ‘/admin/‘,redirect:’/unfound’},
]
},
{path: ‘/unfound’,component: Unfound,},
{path: '/’,redirect: ‘/’,},
在根组件中使用element UI 常见的header、main、footer垂直布局,其中作为页面的路由入口。
3.5.2 前端关键页面设计
(1) 首页,对首页的设计,论坛首页为大家展示了最新的帖子列表:
图3-7 论坛首页
论坛首页如上,能够进行帖子搜索,以及根据帖子的类型进行查看。
(2)论坛的登陆。登陆通过模态框达到即时登陆的目的,而不再通过登陆页面进行登陆,这样的好处在于登陆后页面不会因此丢失或重新加载,用户体验得到明显改善。
图3-8 论坛登陆
(3)发帖。发帖时能够在首页底部能够进行发帖(当然需要登陆),输入标题后,内容除了文字和表情,甚至能够插入自己上传的图片。发贴后能够获得相应的5点经验值。
图3-9 发帖模块
(4)回帖。进入刚刚发送的帖子,我们能看到帖子的内容并进行回复,同样能够恢复文字、表情、以及自己上传插入图片。同时还能对楼层进行回复,生成楼中楼(二级回复)。
图3-10 进入帖子进行回复和二级回复
(5)个人页面中,你可以拥有丰富的个人资源。
图3-11 个人信息(展示状态)
对个人信息的编辑也极为简单,点击编辑后即可进入编辑状态。除了常规的可编辑信息,点击头像能够上传新的头像。
图3-12 个人信息(编辑状态)
(6)通知。这里囊括了论坛的所有通知,在发现新的通知时,将会在头部显示。
图3-13 在头部显示的3条消息
这里根据不同类型的通知展示不同的颜色的通知项。除了能够移除一条通知,还能够清空所有通知。
图3-14 不同类型的通知
(7)收藏帖子。在打开一个帖子后,点击收藏按钮即可收藏本贴。通过收藏列表中的红色按钮能够移除收藏。
图3-15 右上角绿色的收藏按钮
图3-16 收藏列表
(8)关注。关注包括了粉丝。通过用户头像附近的橙色按钮能够关注对方。
图3-17 橙色关注按钮(楼层中显示)
图3-18 橙色关注按钮(个人信息显示)
在关注列表中能够查看所关注的用户,和那些正在关注你的用户。点击头像旁边的灰色按钮即可取消关注对方。
图3-19 关注列表以及灰色的取关按钮
(9)私信。论坛除了基本发帖,还应该配备私信功能。点击用户头像附近的私信按钮能够发起私信。
图3-20 私信按钮(楼层中显示)
图3-21 私信按钮(个人信息显示)
在私信列表中能够进行对话。以及能够看到私信列表,还能够关闭对应的会话。为了防止用户骚扰,当然配备了黑名单,加入黑名单后对方就不能够再私信你。
图3-22 私信会话
图3-23 红色拉黑按钮
(10)历史。历史中你可以查看你所有过去的发帖记录和回复记录,管理员也能够查看,其他用户能够查看你最近3天的历史。
图3-24 发帖记录
图3-25 回复记录
(11)论坛综合数据。当用户拥有足够的权限,即可进入管理界面。
图3-26 管理入口,权限不足时不显示
数据统计界可以看到论坛的许多数据,帖子、用户数等。对于论坛的其他数据,我暂时没有加入过多的统计元素。
图3-27 数据统计页面
(12)举报与审核。用户可以在帖子中进行举报,可以举报的有帖子、楼层、二级回复,举报时需要填写举报信息。举报后将会在管理界面进行审核。
图3-27 举报帖子按钮
图3-28 举报楼层或回复
帖子审核界面中,使用了审批条的形式,而不是以表格的形式,能够明确被举报的帖子条目,被举报的帖子所属的用户。通过驳回和同意按钮进行审核。
图3-29 审核帖子
图3-30 审核楼层
图3-31 审核楼中楼
(13)用户列表。管理界面能够进行用户查询。同时对用户进行封号处理。点击用户的关入小黑屋链接,填写禁封天数,确认之后即可禁封用户,被禁封的用户将不可登陆。
图3-32 用户查询界面(正常用户)
图3-33 用户查询界面(禁封用户)
3.5.3 前端代理
直接访问后端接口时,浏览器将产生跨域问题,导致无法获取后台数据。前端代理配置如下。
proxy: {
“/boki”: {
target: “http://localhost:8001/”,
ws: true,
changeOrigin: true,
pathRewrite: {
‘^/boki’: ‘’
}
}
}
3.4 本章小结
本章主要分析《BOKI》论坛的具体实现及其使用的技术支持。后端技术在集成的过程中需要注意的是所用的技术是否符合系统的需求,以及在数据接口的设计中需要符合规范,以便在前端进行数据请求的时候能够正确获取到数据。
前端设计页面的要点是清晰,简易,整洁,链接指向明确,以及访问链接的完整性,可用性。设计前端的数据时,要把自己想象成用户,从用户的角度出发,得到用户想要的功能与结果。设计登陆的时候,强调了即时登陆,避免了当前页面跳转;前端代理中对后端的feign服务进行代理,避免跨域的问题的产生。
第4章 系统测试
4.1 测试的意义
在软件开发过程中,我们需要设计一种规范来对论坛进行把控系统质量,提高论坛的的完整性、正确性、安全性。检查软件产品是否符合用户的需求。如果用户提出的各种功能和需求,软件没有满足需求的话,也就根本提不上交付软件了,因为根本达不到交付程度,所以软件测试非常必要。
4.2 测试的目的
测试的目的是为了在规定的条件下对动漫论坛《BOKI》系统进行操作,对程序质量进行检查,把关需求与设计的落实,查询用户期望是否同输入的数据一致,等。
4.3 测试方法
软件测试方法有很多,包括白盒测试、黑盒测试、灰盒测试等。
黑盒测试,指不考虑程序内部结构与处理,将测试对象当作不可见黑盒子。黑盒面对的是产品设计,白盒针对的是程序功能的实现,灰盒针对兼而有之,既要考虑产品设计要求,又考虑到功能实现的效果。
根据需求,对系统各个功能和页面,本文功能测试用例,将采用黑盒测试方法。
4.4 测试用例及结果
考虑到本论坛的功能与接口较多,所有功能测试完了产生了众多重复的过程与结果,下面将展示的是部分核心功能测试。以及对开发难度较大的接口进行测试,简单接口测试结果不进行展示。
4.4.1 核心接口测试
(1)发帖测试。
.测试接口 post请求:http://localhost:8001/cli/post/send
.前置条件 1、已登陆
.测试数据 {
“title”: “如果在赤手空拳的情况下,阿尼可以凭借格斗术压制兵长吗?”,
“content”: “莱纳在那么多人旁边直接把希斯…\n看着好像就是官方的啊,这到底怎么一回事”
}
.预期结果 1、正常发帖,用户经验+5。
2、防止15秒内连续发帖。
3、粉丝得到发帖通知。
.测试结果 结果1:{“code”:10000,“msg”:“成功.”,“data”:null}
结果2:{“code”:10401,“msg”:“防灌水,15秒后可继续发帖.”,“data”:null}
结果3:粉丝得到发帖通知。
表4-1 发帖测试
(2)打开帖子
.测试接口 get请求:http://localhost:8001/cli/p/1?page=
.前置条件 ——
.测试数据 page=1
.预期结果 帖子基本信息,帖子楼层列表,楼层用户信息
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“id”: 1,
“title”: “我来发第一贴”,
“userId”: 2,
“repliesCount”: 22,
“type”: “精品贴”,
“totalCount”: 5,
“storeys”: [
{
“userId”: 2,
“userName”: “阿立你别秀了”,
“photo”: “https://cdn.donmai.us/preview/2c/c5/2cc57942f9f8f158173567fa426e24da.jpg”,
“exp”: 74,
“level”: 1,
“creditDegree”: 100,
“honorId”: 4,
“role”: “小站长”,
“show”: “不亏是你”,
“id”: 1,
“postId”: 1,
“floorNo”: 1,
“createTime”: “2020-03-03 20:08:44”,
“content”: “我要曰你啊”,
“repliesCount”: 0
},
…
]
}
}
表4-2 打开帖子
(3)加载二级回复
.测试接口 get请求:http://localhost:8001/cli/p/reply/open?id=&page=
.前置条件 id 不能为空
.测试数据 id=3
.预期结果 出现楼中楼列表的回复列表
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: [
{
“id”: 1,
“storeyId”: 3,
“userId”: 1,
“userName”: “全村最坚挺乌蝇哥”,
“createTime”: “2020-03-04 18:52:08”,
“content”: “想要生活过得去”
},
{
“id”: 2,
“storeyId”: 3,
“userId”: 2,
“userName”: “阿立你别秀了”,
“createTime”: “2020-03-04 20:10:42”,
“content”: “头上就得带点绿”
},
…
]
}
表4-3 加载二级回复
(4)回帖
.测试接口 post请求:http://localhost:8001/cli/post/reply/send
.前置条件 1、已登陆
.测试数据 {
“postId”: 12,
“content”: “我觉得不行,@先有弱智后有天 出来解释”
}
.预期结果 1、正常回帖,帖子回复数+1,楼主经验+1,层主经验+3
2、防止15秒内连续回帖。
3、用户“先有弱智后有天”得到通知。
.测试结果 结果1:{“code”:10000,“msg”:“成功.”,“data”:null}
结果2:{“code”:10401,“msg”:“防灌水,15秒后可继续发帖.”,“data”:null}
结果3:受@用户得到通知。
表4-4 回帖测试
(5)二级回复
.测试接口 post请求:http://localhost:8001/cli/post/storeyReply/send
.前置条件 1、已登录
.测试数据 {
“storeyId”: “30”,
“content”: “废物,谁允许你@我”
}
.预期结果 1、正常回复,帖子和楼层回帖数各+1,回复者经验+2,层主和楼主经验+1
2、防止15秒内连续回复。
3、层主收到通知,被@用户收到通知
.测试结果 结果1:{“code”:10000,“msg”:“成功.”,“data”:null}
结果2:{“code”:10401,“msg”:“防灌水,15秒后可继续发帖.”,“data”:null}
结果3:层主收到通知,受@用户得到通知。
表4-5 二级回复测试
(6)修改用户个人信息
.测试接口 post请求:http://localhost:8001/cli/user/modifyInfo
.前置条件 1、已登录
.测试数据 {
“sex”: “女”,
“birth”: “2012-12-12”,
“from”: “我从草原来我从草原来我从草原来我从草原来”,
“intro”: “杀杀杀”,
“show”: “老子这波天秀”
}
.预期结果 用户数据更新
.测试结果 {“code”:10000,“msg”:“成功.”,“data”:null}
表4-6 修改用户个人信息
(7)发起或打开私信
.测试接口 post请求:http://localhost:8001/cli/whisper/open/{targetUserId}
.前置条件 1、已登陆
.测试数据 targetUserId=3
.预期结果 返回私信双方数据和对话内容
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“id”: 5,
“firstUserId”: 1,
“firstUserName”: “全村最坚挺乌蝇哥”,
“firstUserPhoto”: “https://cdn.donmai.us/preview/aa/43/aa43d1d2d1c0e1c4452223b4dc4acd93.jpg”,
“secondUserId”: 3,
“secondUserName”: “先有弱智后有天”,
“secondUserPhoto”: “https://cdn.donmai.us/preview/0f/7d/0f7d0a678308c6ab5e03c5d74f642fab.jpg”,
“list”: null
}
}
表4-7 发起或打开私信
(8)我的发帖历史
.测试接口 get请求:http://localhost:8001/cli/user/postHistory?page=
.前置条件 1、已登陆
.测试数据 page=2
.预期结果 历史发帖列表,及其历史发帖总数
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“totalCount”: 26,
“list”: [
{
“postId”: 9,
“title”: “别让楼主寂寞太久,快来顶贴”,
“repliesCount”: 8,
“content”: “你这屌毛!”,
“reportStatus”: null,
“reportReason”: null
},
…]}
}
表4-8 我的发帖历史
(9)我的回复历史
.测试接口 get请求:http://localhost:8001/cli/user/replyHistory?page=
.前置条件 1、已登陆
.测试数据 page=1
.预期结果 历史回复列表,及其历史回复总数
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“totalCount”: 26,
“list”: [
{
“postId”: 1,
“title”: “我来发第一贴”,
“repliesCount”: 22,
“content”: “回复 @先有弱智后有天 :弱智是真的牛逼@小佳佳,辣鸡 这是我最后的回复了,收下吧!!”,
“reportStatus”: null,
“reportReason”: null
}, …
]
}
}
表4-9 我的回复历史
(10)首页的帖子列表
.测试接口 get请求:http://localhost:8001/cli?type= &page=
.前置条件 ——
.测试数据 type=1 ,page=1
.预期结果 帖子列表,按更新时间排序
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“totalCount”: 9,
“list”: [
{
“id”: 1,
“userName”: “阿立你别秀了”,
“creditDegree”: 100,
“title”: “我来发第一贴”,
“content”: “我要曰你啊”,
“createTime”: “2020-03-03 20:08:44”,
“lastReplier”: “全村最坚挺乌蝇哥”,
“lastReplyTime”: “2020-03-16 16:40:51”,
“repliesCount”: 22,
“type”: “精品贴”,
“isTop”: “n”
},
{
“id”: 5,
“userName”: “阿立你别秀了”,
“creditDegree”: 100,
“title”: “我发帖了,快来顶贴”,
“content”: “快来顶贴 快来顶贴”,
“createTime”: “2020-03-11 16:12:18”,
“lastReplier”: “全村最坚挺乌蝇哥”,
“lastReplyTime”: “2020-03-15 22:29:37”,
“repliesCount”: 1,
“type”: “普通贴”,
“isTop”: “n”
},
…
]
}
}
表4-10 首页的帖子列表
(11)数据统计接口
.测试接口 get请求:http://localhost:8001/admin/statistics
.前置条件 1、已登录
.测试数据 ——
.预期结果 得到统计数据
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“userCount”: 6,
“postCount”: 12,
“deletedCount”: 0,
“averagePost”: 2.0,
“monthlyPosting”: 12
}
}
表4-11 数据统计接口
(12)帖子举报审核列表
.测试接口 get请求:http://localhost:8001/admin/post/report/{type}?page=
.前置条件 1、已登录
2、type类型正确
.测试数据 http://localhost:8001/admin/post/report/post?page=1
.预期结果 得到举报待审核列表
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“totalCount”: 2,
“list”: [
{
“id”: 12,
“type”: “post”,
“userId”: 1,
“userName”: “全村最坚挺乌蝇哥”,
“content”: “如果在赤手空拳的情况下,阿尼可以凭借格斗术压制兵长吗?”,
“reportReason”: " k k ",
“reportTime”: “2020-03-21 16:36:15”
},
…
]
}
}
表4-12 帖子举报审核列表
(13)用户列表查询
.测试接口 get请求:
http://localhost:8001/admin/user/list?elem= &maxLevel= &minLevel= &maxCreditDegree= &minCreditDegree= &isBanned= &page=
.前置条件 1、已登录
.测试数据 elem=马&maxLevel=10&minLevel=1&maxCreditDegree=100
&minCreditDegree=30&isBanned=n&page=1
.预期结果 得到符合条件的用户
.测试结果 {
“code”: 10000,
“msg”: “成功.”,
“data”: {
“totalCount”: 1,
“list”: [
{
“id”: 5,
“mail”: “1078968706@qq.com”,
“userName”: “猎马人屑鹏亮”,
“level”: 1,
“honorId”: 4,
“banUntil”: null
}
]
}
}
表4-13 用户列表查询
(14)图片上传接口
.测试接口 post请求:http://localhost:9001/images/upload
.前置条件 ——
.测试数据 D:\temporary\新建文件夹\596afe18ebc4b745ff28096dd8fc1e178b8215c9.jpg
.预期结果 上传成功,返回可访问url
.测试结果 {“code”:10000,“msg”:“成功.”,“data”:“http://localhost:9001/images/20200313002601_23dd581ed21b0ef491573c16d3c451da80cb3ede.jpg”}
表4-14 图片上传接口
(15)禁封用户
.测试接口 post请求:http://localhost:8001/admin/user/ban
.前置条件 1、已登录
.测试数据 {“userId”: 3,“days”: 2}
.预期结果 封禁用户,并设置解封时间
.测试结果 {“code”:10000,“msg”:“成功.”,“data”:null}
表4-15 禁封用户
4.5 本章小结
本章主要针对开发难度较大的接口,和论坛的部分核心接口进行测试,当然本论坛的接口众多,如果将所有测试结果进行展示,文章将变得臃肿且毫无重点。在以上测试虽然是部分测试,但是难度系数明显大于简单接口(关注、拉黑等接口),非常具有代表性。
至此,所有接口均已经通过测试,接口测试的通过,意味着论坛的功能得以实现。BOKI论坛的能够进行交付。
第5章 结束语
5.1 全文总结
在对论坛的功能进行设计的时候,很大程度上参考了百度贴吧,百度贴吧是非常成功又经典的例子,是许多论坛史上的一个标杆,值得我们所有开发者去参透其中的奥妙。BOKI是一个简单又简洁的论坛,它包含了论坛的所有基本功能,包括发帖、回复、关注、消息、私信、举报、注册、个人信息、等级、收藏、删帖、信誉度等用户功能,同时又把简便性放在了第一位。
现如今的互联网网站的存在形式,网站内部有可能内嵌论坛,因此,该项目中实现一个整体的、可移植性强的插件式论坛,论坛就有可能突破ACG主题的限制,实现论坛与主站的分离,只要提供前端,就能够正真实现论坛的插件式引入。当然,本项目中提供了一个前端服务,这个前端使用了VUE进行开发。
开发本论坛的难点在于对技术的选择,在如今主流的web项目框架中,该项目中使用了Spring框架作为后端基础,使用mysql数据库。项目的运行环境包括但不限于windows 7以上环境。mysql与redis将在CentOS环境中使用docker容器,以实现快速启动。由于数据的增删改查并非完全以PO形式,故在项目的dao层使用灵活度较高的mybatis框架。项目前端则使用VUE框架进行开发。
该论坛主要实现未登录的游客的帖子浏览,已登录用户的发帖回帖、个人信息管理,管理团队对普通用户和帖子的调控,实现论坛环境的正常运行和提升用户的发帖与浏览体验。针对核心的发帖模块,经过对后端接口的严格测试,已经能够正确地实现发帖、回贴,甚至是二级回复。其他接口同样地,均通过黑盒测试,能够稳定地提供数据交互。通过对系统各项功能的优化与测试,系统能够对用户不合理的操作进行提示,所设计的系统能够正常运行、业务处理逻辑比较合理,所有功能均已达标。
5.2 课题展望
在对互联网的调查中发现,大多数网站离不开论坛,网站至少匹配一个评论区,可见论坛的存在是互联网必不可缺的一部分,以及论坛在互联网存在形式的多样性,可以说,论坛能够衍生出无数种可能性,互联网离不开论坛。动漫主题的论坛更是符合当下时代的发展背景,日益壮大的ACG圈,使得动漫主题论坛越来越多。
论坛后期展望:
1、BOKI论坛实际上还存在很多不足之处,由于是在我本人的硬件设备上进行开发与测试,本人硬件设备并不好,系统的一些性能因此有所限制。
2、BOKI论坛的安全性问题需要加强。由于前后端分离,在访问后端时只需访问接口即可,其中可以加入Nginx进行访问过滤。
3、性能调优方面,我使用的一些java代码为自己封装的api,其中代码逻辑与效率比不上高手所写的代码,包括sql语句,数据库接口,都是有值得优化的地方,这些优化能够提升整体流畅度。
4、BOKI论坛的功能虽然齐全,可拓展方面也很多,正如上面所提到的,论坛的发展方向是无数的,在目前功能完善的基础上,论坛是能够进一步开发的,比如分区,资源库,公布栏,系统监测等。
参考文献
[1] Spring [Spring Boot] 官方文档 https://spring.io/projects/spring-boot
[2] Spring [Spring Data Redis] 官方文档 https://spring.io/projects/spring-data-redis
[3] Spring [Spring Cloud OpenFeign] https://ng.io/projects/spring-spricloud-openfeign
[4] redislabs [redis] 官方文档 https://redis.io/commands
[5] Oracle [mysql] 中文官方文档 https://www.mysqlzh.com/
[6] Thymeleaf团队 [Thymeleaf] https://www.thymeleaf.org/documentation.html
[7] 尚硅谷 [Apache Shiro] 视频教程 https://www.bilibili.com/av29862843
[8] W3School [HTML/CSS] https://www.w3school.com.cn/tags/index.asp
[9] 菜鸟教程 [JQurey] https://www.runoob.com/jquery/jquery-tutorial.html
[10] 菜鸟教程 [HTML] https://www.runoob.com/html/html-tutorial.html
[11] 菜鸟教程 [Java] https://www.runoob.com/java/java-tutorial.html
[12] 菜鸟教程 [Linux] https://www.runoob.com/linux/linux-tutorial.html
[13] 杜波依斯. MySQL技术内幕[M]. 第4版. 人民邮电出版社 , 2011.7
[14](美)盖茨(Goetz,B). Java并发编程实战. 机械工业出版社 , 2012.4
致 谢
慢慢地,四年过去了,大学学习生活即将结束,在这四年的每一个日日夜夜里,有老师的教诲与指导,同学的帮助,父母的支持与鼓励,总使我的步伐不断向前迈进。我是幸运的,可以结识到这么多的良师益友,顺利、愉快地完成学业。短暂而充实的四年大学生涯即将结束,曾经的我总以为时间还有很多,我们不需要着急,可现在,转眼间已是踏入社会的青年。过去的时光我们铭记在心,未来的道路我们携手前进,感谢黄长存老师和各位同志对我的关心、谆谆教诲和悉心指导。我的心里又响起的那首歌:正道的光,照在了大地上…