摘 要
随着互联网的不断发展,人们由Web 1.0以静态、单向阅读为主的只读式网络走向了以分享为内核的实时现代化网络,即Web 2.0时代逐渐向着Web 3.0迈进。
随着技术的不断更新迭代,互联网从业者也必须处于终身学习的状态,他们要不断的学习新的技术,解决新的问题。在学习的过程中就会积攒出很多的学习笔记以及各种错误的解决经验。将其写成文章记录下来,成为人们的公共智慧,以便其他人随时查阅,吸取经验就将是一个很好的选择。所以需要一个平台来记录和管理这些文章,同时可以让创作者与读者相互讨论交流,互相学习成长。
Java是现如今最盛行的技术之一,Java EE非常适合于Web应用程序的开发。并且基于Java EE的开源技术框架已经发展多年积攒出大量实践经验,尤其是以Spring Boot为代表的Spring系列框架,他们几乎已经成为Java Web开发领域的开发者所必备的技能之一,Java 社区也是十分活跃,可以给与开发者非常大的支持。本文的目的就是利用Spring Boot技术设计并且实现个人学习记录平台。最后为了给予用户更好的使用体验,本系统将使用缓存技术将本地MySQL数据库中的一部分数据存储入内存中的Redis数据库。
关键词:Java Web;Spring Boot;MyBatis
Design and Implementation of Personal Learning Recording Platform Based on Spring Boot
Abstract
With the continuous development of the Internet, people have moved from a read-only network based on static and one-way reading of Web 1.0 to a real-time modern network with sharing as the core, that is, the Web 2.0 era is gradually moving towards Web 3.0.
With the continuous update and iteration of technology, Internet practitioners must also be in a state of lifelong learning, they must continue to learn new technologies and solve new problems. In the process of learning, many study notes and various error-solving experiences will be accumulated. It will be a good choice to write it as an article and record it, and it will become people's public wisdom so that other people can check it at any time and learn from experience. Therefore, a platform is needed to record and manage these articles, while allowing creators and readers to discuss and communicate with each other, and learn from each other.
Java is one of the most popular technologies today, and Java EE is very suitable for the development of Web applications. And the open source technology framework based on Java EE has been developed for many years and accumulated a lot of practical experience, especially the Spring series framework represented by Spring Boot. They have almost become one of the necessary skills for developers in the field of Java web development, and the Java community is also Very active and can give developers a lot of support. The purpose of this article is to use Spring Boot technology to design and implement a personal learning record platform. Finally, in order to give users a better experience, this system will use caching technology to store part of the data in the local MySQL database into the Redis database in memory.
Key Words:Java Web;Spring Boot;MyBatis
目 录
摘 要
Abstract
引 言
1 系统概述
1.1 Spring Boot介绍
1.2 MyBatis介绍
1.3 MySQL数据库
1.4 Redis缓存
1.5 Maven构建
2 系统需求分析
2.1 可行性分析
2.1.1 技术可行性分析
2.1.2 经济可行性分析
2.1.3 操作可行性分析
2.2 功能需求分析
2.2.1 前台功能需求分析
2.2.2 后台功能需求分析
3 系统设计
3.1 功能设计
3.1.1 前台功能设计
3.1.1 后台功能设计
3.2 数据库设计
3.2.1 概念结构设计
3.2.2 逻辑结构设计
4 系统实现
4.1 验证码
4.2 后台登录功能
4.3 权限认证功能
4.4 后台主界面
4.5 分类管理
4.6 标签管理
4.7 添加文章
4.8 文件上传
4.9 文章管理
4.10 友链管理
4.11 基于Druid的数据监控层
4.12 缓存实现
4.13 前台功能实现
5 系统测试
5.1 测试分析
5.2 前台功能测试
5.3 后台功能测试
5.3.1 后台登陆功能测试
5.3.2 文章管理功能测试
5.3.3 标签管理功能测试
5.3.4 分类管理功能测试
5.3.5 评论管理功能测试
结 论
致 谢
参 考 文 献
引 言
计算机行业是一个需要其从业者终身学习的行业。在现代的计算机行业中,技术迭代越来越快,开发者需要不停的去学习新的技术,新的设计理念并应用在工作学习之中。在信息化的社会中学习的方式有很多中,视频、音频、以及各式各样的书籍文章都可以供开发者学习。但是,最高效的学习方式还是书籍,通过书籍和官方文档才可以更加细致深入地学习到新技术。如今的互联网上有许多人在写自己的技术文章,记录自己的学习笔记和感悟,并将其加以分析整理,以供他人观看学习。同时可以通过读者的反馈对其再加以修正改版,修改自己的错误。
因此他们可以为自己搭建一个属于自己的互联网学习记录平台。这样做开发者既可以拥有最大的自主权,搭建出自己喜欢的网站,又可以根据这次系统的实践加深其对技术的理解,使其在实践中更加了解现代企业开发所用的技术。
此次平台搭建,本系统前端以Bootstrap[1]和jQuery[2]为主体搭建,后端则以Spring Boot为核心搭建,同时包括以MyBatis为基础的系统持久层,以SpringMVC为基础的web层等等。同时数据库方面将使用简单但功能又强大的MySQL数据库,再配以Redis缓存中间件优化系统。
1 系统概述
1.1 Spring Boot介绍
Java Web开发一直被人诟病的一点就是臃肿、麻烦。其中最主要的原因就是复杂的配置和混乱的依赖管理。
学习Spring的第一件事情就是学习它的配置文件的编写,整个Spring的运行都是建立在那些繁多的配置文件之上的,开发者通过修改配置而对Spring的底层进行影响。而配置文件就是一个麻烦的代名词,它使得开发者不仅要学习Spring的编程技巧,还要学习其对应的配置文件的编写,让开发者的思维跳转与业务逻辑和配置编写之间,很影响编程效率。
得益于Java的跨平台的特性,人们可以在任意平台使用他人编写好的jar包,从而避免很多重复的工作。但是由此也衍生除了依赖管理方面的问题,因为使用第三方jar包就意味着本程序的运行要在第三方包的基础之上,同时此依赖是需要开发者手动来管理的(虽然Maven的出现解决了一部分问题),一旦引用错误的jar包甚至是错误的版本的jar包就会使程序发生一些难以理解的错误,会极大拖慢开发进程。
Spring Boot顾名思义,其就是一个Spring框架的启动器,它极大地简化了Spring的配置文件,可以使开发者快速搭建出一个适用的Spring框架。其理念是约定大于配置。其最大的作用就是让文件配置,开发,项目发布与测试调试变得简单,简化了Spring中繁琐的配置文件,同时它还与海量的外围框架进行了集成,使得软件开发站在了巨人的肩膀上[3]。
1.2 MyBatis介绍
MyBatis是轻量级的Java持久层中间件,完全基于JDBC[4]实现持久化的数据访问,支持以XML和注解的形式进行配置,能灵活、简单地进行SQL映射,也提供了比JDBC更丰富的结果集,应用程序可以从中选择对自己的数据更友好的结果集。MyBatis 从创建到现在,一直秉持着小而精的聚焦理念,这使其做到定位准确、轻量化、运行稳定和便于集成,并因此得到广泛应用。开发者可以使用MyBatis灵活多样的配置功能将应用程序中的SQL在执行前配置好。所有SQL都被放到统一的位置,这样既方便查找,又增强了可维护性。MyBatis也向开发者提供了统一的SQL执行方法,并且支持丰富的扩展定制来满足开发者的个性化需求。尽管大部分公司都会通过某种模板方法来简化JDBC访问,但事实证明MyBatis在这方面做得更好[5]。
1.3 MySQL数据库
MySQL是现如今最常用的一个关系型开源数据库管理系统,其服务器逻辑架构图如下图所示:
图1.1 MySQL服务器逻辑架构图
中间一层是MySQL中核心部分。大多数 MySQL的核心服务功能都在这一层包括查询解析、分析、优化、缓存以及所有的内置函数(例如日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:储过程、触发器、视图等。最下面一层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取。
MySQL有多种引擎,最为常见的是InnoDB、MyISAM、MEMORY。MyISAM 是早期MySQL的默认数据库引擎,虽然MyISAM的性能极佳但其并不支持事务处理,后被InnoDB代替。如今MySQL的默认引擎为InnoDB,它可以处理大量的短期事务(很少会被回滚)。InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行[6]。
1.4 Redis缓存
Redis是一种基于键值对(key-value)的NoSQL[7]数据库,与很多键值对数据库不同的是,Redis中的值可以是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、HyperLogLog、GEO(地理信息定位)等多种数据结构和算法组成,因此Redis可以满足很多的应用场景,而且因为Redis会将所有数据都存放在内存中,所以它的读写性能非常惊人。并且,Redis还可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障的时候,内存中的数据不会“丢失”[8]。
1.5 Maven构建
Maven是Java程序开发中常用的构建和依赖管理的工具。它可以完成对项目所依赖的jar包进行有效的管理, 可以让项目保持最基本的依赖, 排除冗余jar包, 可以让开发者轻松的完成对所依赖的jar包进行版本的升级工作[9]。它可以帮助开发者完成项目的构建、编译、测试、打包部署的自动化。它现如今已经成为开发中的必备工具。其项目结构如图1.2所示。
图1.2 Maven项目结构图
其中main存放的是项目相关的东西,test目录存放的为测试所需资源,其目录下的java和resource分别存放源代码和所需资源。Maven中最关键的是pom.xml文件,这是整个Maven项目的配置文件。
2 系统需求分析
2.1 可行性分析
2.1.1 技术可行性分析
本系统使用Maven进行统一的构建和依赖管理,数据库采用简单而又实用的MySQL,并使用MyBatis作为ORM框架。使用SpringMVC作为前端控制器,用以接受浏览器的请求并返回处理结果。本项目所使用的技术都是在开发领域中久经市场验证的,经过长时间的迭代优化,其安全、可用、可靠性都是极高的。
2.1.2 经济可行性分析
本系统采用的后端技术框架有Spring、SpringMVC、MyBatis,数据库有MySQL、Redis,前端技术有HTML、CSS、JS、Bootstrap和jQuery。这些都是现代的开源技术。使用开发工具为IDEA学生优惠版本,开发人员为一人,经济消费很低,可行性极高。
2.1.3 操作可行性分析
本系统所使用的技术都非常成熟了,在网上由很多的经验积累,同时所作的系统在网上也有一些功能相类似的网站可以供本系统借鉴,所以开发的条件充足,可行性极高。
2.2 功能需求分析
本系统可以分为前台和后台,前台主要用来展示文章,所有人都可以访问呢,没有权限限制。后台只有拥有管理员权限的人才可以访问,管理员在这里可以对系统进行修改调整。
2.2.1 前台功能需求分析
系统的前台主要为展示效果,所以功能并不多,仅有搜索文章、热门标签,最新发布、点击最多、友链、和点击标签或分类展现出该标签和分类下的所有文章几个功能。这些就是普通的用户所希望看到的东西以及基本的功能需求,并且应当针对用户的需求进行相应的功能模块开发,并持续的与用户沟通,提高用户的使用体验。
2.2.2 后台功能需求分析
后台只允许管理员用户访问,其主要拥有系统信息展示和一些基本的对于文章、标签、分类、评论、友链的管理功能。另外,再加上一些基本的系统设计和管理员信息编辑就可以构成整个后台。
登录功能是后台的第一个功能同时也是最重要的功能之一。管理员只有通过登录模块的验证,成功登录才可以进行之后的管理员操作。这样才可以保证程序后台的安全性。
文章管理是一个非常重要的模块,通过这个模块管理员可以编辑文章,修改文章,并对其加标签、加分类、评论等等多项操作。
评论管理是对平台用户的评论进行维护的模块,其主要的功能在前台,后台只给管理员提供删除不合规评论以及回复的功能的功能。
分类管理和标文章签管理比较类似,都是对于一种标记,一个文章可以属于一个大模块,并带上多个技术标签。管理员可以在这两个功能模块出查询出所有的标签或分类,并对其修改或删除同时也可以新增一个分类或标签。
3 系统设计
3.1 功能设计
通过上述的功能分析,可以得出本系统的大致功能设计如图3.1所示。
3.1.1 前台功能设计
前台为普通用户所访问的界面,主要功能为通过不同的条件向用户展示文章。通过不同的筛选条件,主要分为首页、分类页、标签页、关于我、文章页这五个主要页面。
首页为普通用户打开网页的所能看见的第一个页面,这个页面的内容繁多复杂,从上到下主要分为三个模块。最上面的模块为一张背景图片,左上角为通往其他页面的链接。中间部分则分为两个部分,左边为文章列表,右边是搜索、热门标签、最新发布、最多点击三个模块。首页的底部就是一些基本信息。
分类展示和按标签展示也是首页的一个重要功能,当在首页点击一个标签或者分类时就会跳转到这里,然后在这展示出该标签或分类下的文章列表。
关于这个界面为一个普通的静态页面,不做动态数据展示,给与一些关于本平台和作者的一些基本信息。
文章页面是本网站前台最为重要的页面,此页面会展示平台文章的具体内容,应将其做的美观完善。在此页面上应该给文章加上一些排版样式,让其变得更加美观。
3.1.1 后台功能设计
后台为管理员所能访问到的页面,并不对普通游客开放,所有要有一个机制过滤掉所有非管理员用户对后台API的请求,这个机制就是俗称的登录功能。在登陆模块中,程序通过对用户名、密码和验证码的验证,过滤掉所有的非管理员用户,剩下的激素系统管理员,他们可以访问系统后台并对系统进行各种操作。
当管理员登陆成功之后就会进入后台管理界面,管理界面主要分为文章管理、标签管理、分类管理、评论管理、系统管理几个功能模块。
3.2 数据库设计
3.2.1 概念结构设计
根据系统的不同功能,最后系统数据模型的总体E-R图如图3.2所示。
图3.2 系统总体E-R图
3.2.2 逻辑结构设计
(1)管理员用户表
管理员用户表存放着系统的管理员信息,该表的实体-属性图如图3.3所示。
图3.3 管理员用户实体-属性图
图中包括管理员ID,主键且自动递增,其他包括:管理员显示昵称、管理员登录名称、管理员登陆密码、是否锁定。其数据库表设计见表3.1。
表3.1 管理员用户信息表
列名 | 中文名称 | 数据类型 | 是否允许 为空 | 约束条件 | 备注 |
admin _user_id | 管理员ID | int(11) | NOT NULL | PRIMARY KEY | |
login_user _name | 管理员显示 昵称 | varchar(50) | NOT NULL | ||
Login _password | 管理员登录 名称 | varchar(50) | NOT NULL | ||
nick_name | 管理员登陆 密码 | varchar(50) | NOT NULL | ||
locked | 是否锁定 | tinyint(4) | 是否锁定 0未锁定 1已锁定无法登陆 |
(2)文章表
文章表存放的是系统文章的各项信息,该表的实体-属性图如图3.4所示。
图3.4 文章表实体-属性图
图中包括管理员id,主键且自动递增,其他包括:标题、封面图、内容、分类id 外键等等诸多字段。其具体数据库表设计见表3.2。
表3.2 文章信息表
列名 | 中文名称 | 数据类型 | 是否允许为空 | 约束条件 | 备注 |
blog_id | id | bigint(20) | NOT NULL | PRIMARY KEY | |
blog_title | 标题 | varchar(200) | NOT NULL | ||
blog _coverimage | 封面图 | varchar(200) | NOT NULL | ||
blog _content | 内容 | mediumtext | NOT NULL | ||
blog_category_id | 分类id | int(11) | NOT NULL | 外键 | |
blog_category_name | 分类名称 | varchar(50) | NOT NULL | 冗余字段, 方便查询 | |
blog_tags | 标签 | varchar(200) | NOT NULL | ||
blog_status | 草稿还是发布 | tinyint(4) | NOT NULL | 0-草稿 1-发布 | |
blog_views | 阅读量 | bigint(20) | NOT NULL | ||
enable _comment | 是否允许评论 | tinyint(4) | NOT NULL | 0-允许 1-不允许 | |
is_deleted | 是否删除 | tinyint(4) | NOT NULL | 0-否 1-是 | |
create_time | 添加时间 | datetime | NOT NULL | ||
update_time | 修改时间 | datetime |
(3)分类表
分类表存储系统中表的分类信息,该表的实体-属性图如图3.5所示。
图3.5 分类表实体-属性图
图中包括管理员Id,主键且自动递增,其他包括:分类的名称、分类的图标、分类的排序值、是否删除、创建时间。其具体数据库表设计见表3.3。
表3.3 分类信息表
列名 | 中文名称 | 数据类型 | 是否允许为空 | 约束条件 | 备注 |
category _id | id | int(11) | NOT NULL | PRIMARY KEY | |
category _name | 分类的名称 | varchar(50) | NOT NULL | ||
category _icon | 分类的图标 | varchar(50) | NOT NULL | ||
category _rank | 分类的排序值 | int(11) | NOT NULL | 被使用的越多数值越大 | |
is_deleted | 是否删除 | tinyint(4) | NOT NULL | 是否删除 0=否 1=是 | |
create_time | 创建时间 | datetime | NOT NULL |
(4)评论表
评论表存储的是系统文章的评论信息,该表的实体-属性图如图3.6所示。
图3.6 评论表实体-属性图
评论表的具体实现见表3.4。
表3.4 评论信息表
列名 | 中文名称 | 数据类型 | 是否 允许为空 | 约束条件 | 备注 |
blog_id | 关联的 blog主键 | bigint(20) | NOT NULL | 外键 | |
commentator | 评论者名称 | varchar(50) | NOT NULL | ||
| 评论人邮箱 | varchar(100) | NOT NULL | ||
website_url | 网址 | varchar(50) | NOT NULL | ||
comment _body | 评论内容 | varchar(200) | NOT NULL | ||
comment _create _time | 评论提交 时间 | datetime | NOT NULL | ||
commentator_ip | 评论时的 ip地址 | varchar(20) | NOT NULL | ||
reply_body | 回复内容 | varchar(200) | NOT NULL | ||
reply _create _time | 回复时间 | datetime | NOT NULL | ||
comment _status | 是否 审核通过 | tinyint(4) | NOT NULL | 0-未审核 1-审核通过 | |
is_deleted | 是否删除 | tinyint(4) | 0-未删除 1-已删除 |
(5)标签表
标签表存放的是系统文章的标签信息,其数据库表设计见表3.5。
表3.5 标签信息表
列名 | 中文名称 | 数据类型 | 是否允许 为空 | 约束条件 | 备注 |
tag_id | id | int(11) | NOT NULL | PRIMARY KEY | |
tag_name | 标签名称 | varchar(100) | NOT NULL | ||
is_deleted | 是否删除 | tinyint(4) | NOT NULL | ||
create_time | 创建时间 | datetime | NOT NULL |
(6)配置项表
配置项表存放的是系统的一些配置信息,其数据库表设计见表3.6。
表3.6 配置信息表
列名 | 中文名称 | 数据类型 | 是否允许 为空 | 约束条件 | 备注 |
config_name | 配置项的 名称 | varchar(100) | NOT NULL | PRIMARY KEY | |
config_value | 配置项的值 | varchar(200) | NOT NULL | ||
create_time | 创建时间 | datetime | NOT NULL | ||
update_time | 修改时间 | datetime | NOT NULL |
(7)友链表
友链表存储的是管理员推荐的网站连接,其数据库表设计见表3.7。
表3.7 友链信息表
列名 | 中文名称 | 数据类型 | 是否允许为空 | 约束条件 | 备注 |
link_id | id | int(11) | NOT NULL | PRIMARY KEY | |
link_type | 友链类别 | tinyint(4) | NOT NULL | 0-友链 1-推荐 2-个人网站 | |
link_name | 网站名称 | varchar(50) | NOT NULL | ||
link_url | 网站链接 | varchar(10) | NOT NULL | ||
link_rank | int(11) | NOT NULL | 用于列表排序 | ||
create_time | 添加时间 | datetime | NOT NULL |
(8)文章-标签关系表
因为在本系统的设计中一篇文章可以对应多个标签,一个标签可以对应多个文章,所以需要另外一张表去维护文章和标签之间的多对多之间的关系。其数据库表设计见表3.8。
表3.8 配置信息表
列名 | 中文名称 | 数据类型 | 是否允许 为空 | 约束条件 | 备注 |
relation_id | 关系表id | bigint(20) | NOT NULL | PRIMARY KEY | |
blog_id | 文章id | bigint(20) | NOT NULL | 外键 | |
tag_id | 标签id | int(11) | NOT NULL | 外键 | |
create_time | 修改时间 | datetime | NOT NULL |
4 系统实现
该系统主要有前台和后台两个部分组成,主要的业务处理逻辑都在后台完成,前台仅仅是一些查询展示操作。所以,本文的系统实现便由后台讲起。
4.1 验证码
在现代的,验证码遍布人们生活中的各个地方。顾名思义,验证码便是一组起到验证作用的密码,其主要作用就是证明这个操作是“我”自己做出来的,不是机器人做的。如果没用验证码,网站的后台就很容易受到大国民机器注册和暴力破解密码等危害,所以需要一个东西判断当前进行操作的是人还是机器,验证码就是一个极优解。所以,在讲述后台第一个功能模块的登录模块之前,先讲述一下本系统的验证码功能的实现。
在本系统中的验证码计划采用Kaptcha来实现,这是一个简单而又实用的验证码生成器,仅需配置一些参数就可以按要求生成对应的验证码。最后再以图片的形式显示,从而无法进行复制粘贴。
想要使用Kaptcha,首先应当导入其jar包,其Maven依赖如下:
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> |
然后需要在相应的配置类中配置关于验证码的一些信息,需要配置验证码的图片边框、字体颜色 、图片的宽高、字体大小、验证码的长短。配置好这些信息后再将验证码放入Session中并设置key和保存时间。此时,关于Kaptcha的配置都结束了,在以后的程序中便可以随意调用,生成验证码。
因为其验证码是网站中常用的一个功能,所以应当将其抽象出来做成一个工具类,以后每当用户访问GET请求的“/common/kaptcha”API时就会得到一个相应的验证码图片的二进制流。
4.2 后台登录功能
后台登陆功能是系统后台最基础也是最重要的一个功能,因本系统只是一个单用户的系统,所以本系统的后台只提供给管理员登陆,没有管理员权限的用户都无法访问后台的的任何页面。其后台登录流程如图4.1所示。
图4.1 登录流程图
根据此流程图可以看出系统登录的大致流程,首先是用户以GET方式请求后台,后台控制器会返回一个登录的页面。其样式如图4.2所示。
图4.2 登录界面图
然后用户要在此界面中填写用户名、密码和验证码,然后点击登录。信息便会通过POST方式提交到后端。后端接收到数据再进行校验,如果其中一个为空或者验证码不正确,就会停止登陆操作,向前台返回错误信息。如果信息校验都通过了才会进行下一步的连接数据库的校验,代码如下:
AdminUser adminUser = adminUserService.login(userName, password); |
程序会先调用此方法向MySQL数据库进行查询操作,执行如下语句并返回。
<select id="login" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from tb_admin_user where login_user_name = #{userName,jdbcType=VARCHAR} AND login_password=#{password,jdbcType=VARCHAR} AND locked = 0 </select> |
当程序拿到查询的结果时就需要再次进行判断,如果查询结果为空,就说明不存在该用户,这时系统应当重新回到登陆页面。当结果不为空,说明存在该用户,此时应当将该用户的信息放入Session中以便之后的权限验证,之后再跳转到后台主界面。
4.3 权限认证功能
此时系统的登录功能已经完成了,但是对于整个系统来说又没有完全完成,因为此时非管理员用户还是可以直接通过链接访问到后端的其他页面的,没有任何权限的验证。所以系统还应该再实现一个拦截器,拦截所请求到后台的请求,然后判断当前是否有用户成功,如果有就放行,如果没有就让其登录。Spring的拦截器实现有很多中,本系统采用新建一个AdminLoginInterceptor类去实现HandlerInterceptor接口,并重写preHandle方法,在请求之前做一些事情。代码如下:
// 只拦截以/admin为开头的后台请求 If(requestServletPath.startsWith("/admin") &&null==request.getSession().getAttribute("loginUser")) { request.getSession().setAttribute("errorMsg", "请重新登陆"); response.sendRedirect(requ}est.getContextPath() + "/admin/login"); return false; } |
当然仅仅写完拦截器还是不够的,还应当将其启动起来,此时可以考虑使用WebMvcConfigurer来实现此功能。创建一个MyWebMvcConfigurer类,实现此接口,同时调用addInterceptors添加一个拦截器。
public void addInterceptors(InterceptorRegistry registry) { // 添加一个拦截器,拦截以/admin为前缀的url路径 registry.addInterceptor(adminLoginInterceptor).addPathPatterns("/admin/**") .excludePathPatterns("/admin/login") .excludePathPatterns("/admin/dist/**") .excludePathPatterns("/admin/plugins/**"); } |
此时,整个系统的登录功能才算真正的完成。任何未登录的用户都不能非法的访问后台管理员的界面了。
4.4 后台主界面
当登录成功时,系统就会跳转到系统后台的主界面,此界面主要展示一些系统的基本信息,如图4.3所示。
图4.3 后台系统主界面
此界面展示了系统的文章、评论、分类、标签和友链的一些基本统计情况,可以使管理员一登陆进来就对系统的总体情况有个大致的了解。
4.5 分类管理
每一篇文章都有自己的分类和标签,同样在后台也就需要对标签和分类进行管理。因为其实现比较类似,本文就选择分类来进行讲解。对于文章类别的管理总结起来也就是增、删、改、查四个操作,这是现如今绝大多数软件的常态化业务,本节也是对其四个操作进行讲解。其界面如图4.4所示。
图4.4 分类管理界面
在此界面中管理员最开始感受到的便是查询操作,随着文章的增多,管理员以后添加的分类也会越来越多。所以,本系统使用了分页查询来完成分类列表的查询展示。当后端接口接收到前端的参数时,首先会对参数进行校验,校验通过了,才会调用分页查询工具类进行计算分页的各种信息,最后才会根据分页工具类进行查询。当系统查询到数据时,便会像前端返回一个类型为Result 集合的JSON字符串,其主要由序列化ID、状态码、提示信息、数据四个部分组成。前端的JS就会对JSON字符串进行解析,同时将其展示出来。
增加一个分类的功能时,程序还是要先进行数据校验,判断分类的信息是否填写完整,分类名称是否重复,当着一切都没问题时才会进行添加操作。
修改一条数据的时候,系统应该先向数据库请求这条数据,将其回显在页面上,然会再将修改完的内容更新到数据库之中。
最后当删除一个分类时就要对其小心判断,因为一个文章是绑定一个分类的,所以系统不能直接就删除这一分类。只有当一个分类不关联任何一篇文章时,系统才可以对其进行删除。为了更加保险一点,本系统对于数据库中的数据都进行软删除,在数据库中设置一个字段,用它来表示数据是否删除。
4.6 标签管理
一篇文章只会属于一个分类,但却会有很多个标签,分类是一篇文章的大致所属区域,标签是更为细分的领域。标签管理的大致功能和上述的分类管理差不多,但是其细节方面还是有一些不同之处。其中最主要的区别就在于,标签与文章是多对多的一种关系,这一点在上述的数据库设计中也可以看出。在数据库设计中使用一张新表来维护文章与标签的关系。
4.7 添加文章
文章是整个系统的核心,本系统最重要的功能就是对文章进行编辑存储和展示。在编辑文章时管理员需要访问到文章编辑发布页,如图4.5所示。
图4.5 文章编辑发布页面
如图所示管理员应当填写好相应的内容,并提交。同时注意到,文章正文采用的是Markdown格式的富文本编辑器。在这里本系统采用的是Editor.md开源的Markdown编辑器,其配置简单,功能强大,是一个非常好的选择。
当点击提交之后,系统便会在Controller层对前端数据进行简单校验并封装成一个文章对象,然后再调用相应的方法保存此对象。同时还应当处理好文章、标签、分类之间的依赖关系,文章与分类之间的关系由文章表中的一个外键维护,文章与标签是多对多的管旭,需要额外一张表来维护,添加文章时也应在这张表中加入维护数据。最后将整个操作放入同一个事务之中。此时运行成功才保存好了一篇新的文章。
4.8 文件上传
当管理员在写博客时,经常需要向里卖弄插入图片,所以应该为博客中的富文本编辑器准备好文件上传的代码。首先应当将Editor.md的文件上传路径设置为” /blogs/md/uploadfile”,然后我们就可以在后台接收到前端传进来的参数。将参数解析再加上随机数拼接之后就可以生成系统保存的文件名。得到文件名后就可以创建这个文件,并将图片写入此位置。这样便可以将一个图片保存到指定的地方并等待以后调用。
4.9 文章管理
文章管理的最重要的一个功能,增加一篇文章在上述部分已经讲述的很清楚了,接下来在这一部分内容就讲述一下文章管理的剩下一点内容。
删除一篇文章的核心代码如下所示:
修改一篇文章的步骤略显复杂,首先要访问要修改的文章的内容并将其回显在页面上,之后就可以随意进行修改。当修改完文章之后就是对修改后的数据进行再次保存,其代码与增加一个文章很类似,此处仅展现最核心,多余逻辑代码便不再赘述。
4.10 友链管理
友链管理是个人学习平台的一个附属功能,其旨在项本系统的读者推荐一些其他优质的网站。这个并不是本系统的核心功能,所以仅简单介绍其代码。
删除的核心逻辑代码如下:
if (ids.length < 1) { return ResultGenerator.genFailResult("参数异常!"); } if (linkService.deleteBatch(ids)) { return ResultGenerator.genSuccessResult(); } else { return ResultGenerator.genFailResult("删除失败"); } |
4.11 基于Druid的数据监控层
Java程序很大一部分都是要对数据库进行操作的,要对数据库进行操作就需要数据库连接,每创建一个数据库连接都是非常耗费资源的事情。因此为了提升程序的性能,就需要用到数据库连接池,每次操作完后不释放连接,而是将其归还如数据库连接池中,随用随取。常用的数据库连接池有c3p、dhcp、proxool、druid等。Druid是Java语言中最好用的连接池之一,它能够提供强大的监控和扩展功能。本系统就采用Druid数据库连接池,同时依靠其强大的监控功能构建数据监控。使用Druid时应当首先在Maven中导入Druid的依赖,然后应该在Spring Boot中配置数据源的属性。
对于Druid的配置信息有很多,首先要启用Druid数据源:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource |
然后就要配置Druid数据源的其他信息,比如设置初始化物理连接个数为5,最小连接池数量为5,最大连接池数量为20,获取连接时最大等待时间为60000毫秒,还有对于连接的一些检验的配置等等。
之后就要编写Druid配置类对其进行更进一步的配置,首先配置Druid的后台路径映射、后台登录用户名和密码。同时还要对其访问控制进行配置过滤无用请求。
最后将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建绑定。
这样数据库连接便已经配置好可以使用了。当管理员登录之后就可以访问到Druid的监控界面,如图4.6所示。
图4.6 Druid数据源监控界面
4.12 缓存实现
在本系统中会有大量的查询操作存在,且系统中的很多数据都会保持长时间不变,所以可以将一部分查询结果缓存在内存数据库当中,依次来减少访问MySQL数据库的次数。在有大量请求访问时,这样会大大优化用户的使用体验。对于Redis需要对其进行数据库索引、服务器地址、服务器连接端口、密码、最大连接数、最大阻塞等待时间、连接池中的最大空闲连接、连接池中的最小空闲连接、连接超时时间等设置。
4.13 前台功能实现
系统的前台是为系统的展示页面,其没有重要的代码逻辑,均为一个个的查询请求构成,具体将在下面详细说明。
用户访问的第一个页面是整个系统的首页面,在此界面整个系统会去请求博客列表分页信息、最新博客、点击最多的博客、点击最多的标签,然后将这些信息回显到页面中。如图4.7所示。
图4.7 系统前台首页图
其他的页面显示原理和首页类似,只不过是增加了一个查询条件,根据不同条件显示出来的结果也就是不同的页面。根据标签查询出的结果就是标签页,根据分类查询出的结果就是分类页面,根据关键词查询出的结果就是关键词查询页面。在这些页面中存放着不同情况下查询出的各项文章。
此外还有几个页面的实现逻辑这些不同,那就是友链页面、About页面以及具体的文章展示页面。
友链页面和About页面里面的东西大部分都是固定的,仅需查询响应数据库在页面中展示出信息即可。
文章展示页面的实现逻辑略微复杂,因为文章在后台是以Markdown文本的格式存储的,这是不能直接在页面上面展示的,需要将后台的Markdown文本解析为HTML页面上的元素,并展示出来。其页面效果如图4.8所示。
图4.8 系统文章展示图
此处的Markdown文本解析使用commonmark来实现,这是一个非常灵活小巧的Markdown文本解析渲染器。它的使用也很简单,我们仅需一点代码便以轻松的使用这一插件。
5 系统测试
5.1 测试分析
软件测试的方法较多,最为人熟知的便是黑盒白盒两种测试方法。
白盒测试中测试人员是可以观察到盒子中的内部结构的,并依靠这些设计测试用例。
黑盒测试又称功能测试、数据驱动测试或基于规格说明书的测试, 它是一种从用户观点出发的测试.测试人员把被测程序当作一个黑盒子.它是已知产品所应具有的功能, 通过测试来检测每个功能是否都能够正常使用[10]。本次采用的是黑盒测试。
5.2 前台功能测试
前台功能测试主要测试普通用户可以使用的功能模块,其主要测试用例见表5.1。
表5.1 前台功能模块测试用例表
测试模块 | 输入操作 | 期待输出 | 真实输出 |
前台功能测试 | 访问http://127.0.0.1:8080/ | 成功进入首页 | 成功进入首页 |
点击一篇文章 | 进入文章页面 | 进入文章页面 | |
点击一个标签 | 页面展示了该标签的所有文章 | 页面展示了该标签的所有文章 | |
点击一个分类 | 页面展示了 该分类下的所有文章 | 页面展示了 该分类下的所有文章 | |
点击友链 | 程序跳转到友链页面 | 程序跳转到友链页面 | |
点击关于 | 程序跳转到 About页面 | 程序跳转到 About页面 | |
搜索一个关键词 | 显示出了与这个 关键词有关的文章 | 显示出了与这个 关键词有关的文章 |
5.3 后台功能测试
5.3.1 后台登陆功能测试
后台登录功能非常重要,关乎系统的安全,应该进行全方位测试,不能错漏每一种情况。只有当验证码、用户名、密码全正确时才可以正确登录,有一项出错误就回报错。具体测试用例见表5.2。
表5.2 后台登陆功能测试用例表
测试模块 | 输入值 | 期待输出 | 真实输出 |
后台登陆功能测试 | 正确的用户名 正确密码 正确的验证码 | 成功进入首页 | 成功进入首页 |
正确的用户名、 正确的密码 错误的验证码 | 验证码错误 | 验证码错误 | |
正确的用户名 正确的验证码 错误的密码 | 登陆失败 | 登陆失败 | |
正确的密码 正确的验证码 错误的用户名 | 登陆失败 | 登陆失败 | |
正确的验证码 错误的密码 错误的用户名 | 登陆失败 | 登陆失败 | |
正确的密码 错误的验证码 错误的用户名 | 登陆失败 | 登陆失败 | |
正确的用户名 错误的验证码 错误的密码 | 登陆失败 | 登陆失败 | |
错误的验证码 错误的密码 错误的用户名 | 验证码错误 | 验证码错误 |
5.3.2 文章管理功能测试
文章管理功能测试主要用于测试后台文章管理功能模块,文章管理功能模块是一个非常重要的功能模块,本系统的所有功能模块都是依托于文章之上而建立出来的,其具体测试用例见表5.3。
表5.3 文章管理功能测试用例表
测试模块 | 输入操作 | 期待输出 | 真实输出 |
文章管理 | 增加一篇文章 | 成功增加了一篇文章 | 成功增加了一篇文章 |
删除一篇文章 | 成功删除了一篇文章 | 成功删除了一篇文章 |
续表5.3 文章管理功能测试用例表
测试模块 | 输入操作 | 期待输出 | 真实输出 | |||||
文章管理 | 修改一篇文章 | 成功修改了一篇文章 | 成功修改了一篇文章 | |||||
查询文章 | 分页查询出了 所有文章 | 分页查询出了 所有文章 |
5.3.3 标签管理功能测试
标签管理功能测试主要用于测试后台标签管理功能模块,具体测试用例见表5.4。
测试模块 | 输入操作 | 期待输出 | 真实输出 |
标签管理 | 增加一篇标签 | 成功增加了一篇标签 | 成功增加了一篇标签 |
删除一篇标签 | 成功删除了一篇标签 | 成功删除了一篇标签 | |
修改一篇标签 | 成功修改了一篇标签 | 成功修改了一篇标签 | |
查询标签 | 分页查询出了 所有文标签 | 分页查询出了 所有标签 |
5.3.4 分类管理功能测试
分类管理功能测试主要用于测试后台分类管理功能模块,具体测试用例见表5.5。
测试模块 | 输入操作 | 期待输出 | 真实输出 |
分类管理 | 增加一篇分类 | 成功增加了一篇分类 | 成功增加了一篇分类 |
删除一篇分类 | 成功删除了一篇分类 | 成功删除了一篇分类 | |
修改一篇分类 | 成功修改了一篇分类 | 成功修改了一篇分类 | |
查询分类 | 分页查询出了 所有分类 | 分页查询出了 所有分类 |
5.3.5 评论管理功能测试
评论管理功能测试主要用于测试后台评论管理功能模块,具体测试用例见表5.5。
测试模块 | 输入操作 | 期待输出 | 真实输出 |
评论管理 | 审核一条评论 | 评论出现在 文章评论区 | 评论出现在 文章评论区 |
回复一条评论 | 在原评论下 出现回复 | 在原评论下出现回复 | |
删除一条评论 | 此评论消失 | 该评论消失 |
通过此次测试可以得出本系统的前台展示以及后台管理的登录、文章管理、标签管理、分类管理、评论管理等功能模块并无明显Bug,错误都在可以接受范围之内,且基础功能完善,已经初步完成设计需求,只需在以后逐步更新换代,慢慢完善功能即可。