一、前言
部分效果图展示
话不多说,先放几张效果图展示一下项目
二、项目总述
1.项目总述
此项目为个人博客系统,分前台和后台。前台负责展示你的博客,且页面适配移动端(不过不是我的功劳,是老师lirenmi的功劳)。管理员可以登录后台来对博客、分类、评论等进行管理。
2.技术栈选择
前端:Semantic UI、thymeleaf
后端:SpringBoot、Spring、SpringMVC、Mybatis
3.环境介绍
数据库:mysql8.0
数据库连接池:Druid
前端框架:Semantic UI、thymeleaf模板引擎
后端框架:SpringBoot、SSM
语言:Java
jdk版本:11.0.5(我个人是没怎么用语法糖的,按理来说jdk8以上都可以运行)
编写的IDE:IDEA 2020.1
插件引用:
lombok(简化部分代码插件)、animate.css-master(动画效果)、editor.md-master(markdown插件)、prism(代码高亮)、tocbot-master(目录生成)、typo.css-master(网页排版)、logback(日志记录)
三、设计思路
接下来,我来讲讲我是如何一步一步来设计后台,当然过程仅供参考,勿喷。
1.根据实际背景制定相应的策略
首先开始设计的时候我已经完成了前端页面的制作
以下当时完成的前端页面:
2.总览项目,抽象功能,化为实体,画出设计图
这时候我还并没有开始写代码,而是把接下来要怎么做写个粗略的文档并画出相应的设计图(不过这也是我的习惯,我喜欢在写代码前先把思路写好,再去写代码,虽然写文档的时候确实会花一些时间,不过写代码的时候思路会很清晰,这会省下不少时间,并且能让你的代码结构清晰不少)
因为我写完前端的页面(不过后台只写了两张),所以先把所需的前端页面画出,再把这些页面汇总得到我第一张设计图——前端页面设计图
然后我就根据页面来分析我需要的功能,由此我画出了第二张设计图
随后我根据这些功能抽象分离,并划分所需的类,由此我得到了第三张设计图——UML图
3.建库建表
至此,项目结构大致清晰了。根据这个类的划分我利用Navicat开始建表(当然PowerDeigner是个很好用的工具,可以让你在一边设计的同时完成建表的工作,但无奈我不太会用,所以采取原始的方式)。
4.搭建框架结构
建完表后我开始搭建框架,先把最基础的那些建出来,分出最基本的Mapper(Dao)层、Service层、Controller层,pojo层(实体类),然后把写好的前端页面给搬过来,再配置所需要的依赖。经过一系列操作后,最基础的框架搭成了(SpringBoot已经简化了很多很多,这个操作还是蛮快的)。
然后再借助tablego神器,直接生成实体类和相应的mapper文件(当然接口还是要自己写的)
然后再对接口加些基本的增删改查操作。
到此基本的框架已经出来了,接下来的不过是根据页面实现相应的功能。
5.接口设计
唯一值得一提的是接口的设计,这是一门大学问,我原先的想法是采用restful风格来设计接口,但是实际操作中还是遇到了些问题。因为这个项目并不是正宗的前后端分离项目,后端实际上还承担了一部分渲染的工作,对于一些前端页面的变化都需要后端来完成,这样后端接口数量会因这些变化急速增长,接口设计巧不巧秒就成了至关重要的一环,因为如果接口设计少了,那么就无法应对前端错综复杂的变化,设计多了那么后端系统将会变得极其复杂,不便于后期维护。
举个例子,比如前端有个分页查询的需求,后端需根据查询的条件和分页来返回数据,如果说将这个查询和分页分开成为多个接口,那么系统将很繁杂,尤其是restful风格,难道你要对同一个资源针对不同情况命名多次?这显然不现实,所以你要解决的问题就是如何做到一个接口应对多种不同情况。
我的解决思路是采用map来接收前端数据,如果map中有相应的数据则做相应的处理。当然这需要前端的配合,不过前后端都是我写的,规矩自然由我来定。前后端不分离好处就在于此,但坏处也显而易见,后端承担前端的部分工作,那么系统复杂度会极度攀升。
说完设计接口,接下来要注意的就是一些细节的地方,比如前端没有传回相应的数据,但是如果将实体类传入做增删改查,那么没有数据的部分就是为null,而你又想要默认值,那么你要么在实体类中加默认值,要么别用实体类,用map传值。再比如null的处理,String和Integer的处理。这些都是细节,但往往出bug的都是这些细节!!!
等我做了大部分功能后,忽然发现架构的时候comment实体类和blog实体类少了个别属性,唉,无奈只能慢慢改。
所以你需要记住架构的时候千万要架构好,不然等你写代码的时候再来改,那改的成本就不是一星半点儿了。
后来针对页面做出了点调整和优化,将修改页和新增页合为一体,随后修改了我的设计图
再往后,就是一步一步写相应页面的代码了,一开始遇到很多问题,写了两个页面就花了我四天,不过解决了相应的问题后,后面的页面就写的很快了,前前后后花了半个月时间,终于完成。在这个过程中我查了无数的博客,学到了很多很多,不得不说做项目是最好的提升方式。
6.利用thymeleaf模板中的if来达到选中效果
大家应该知道选中时会出现选中状态,这对导航来说还好,因为毕竟页面切换了,选中状态也都是写静态效果。
但是如果不切换页面呢?
这对前端老手根本不是什么问题,但对于我这个前端菜鸟来说要解决就有点烦了。
这时候我想到了个取巧的方法,利用thymeleaf模板引擎中的if和switch,case来间接达到选中的效果。
举个例子,
在分类专栏上有这么一个需求,点击相应分页然后返回相应分类下的博客。然后切换分类的选中效果。我的做法就是后端传数据的时候就传入一个全局的数据,比如这里就是typeId,渲染分类栏的时候,通过if比较typeId是否一致如果一致就采用选中状态,如果不是就采用非选中状态
这样就能巧妙的间接实现选中效果切换的目的。
但对于前端大佬来说可能会不屑一顾,不过对于我这种不善前端的人来说,那确实对我还是蛮方便的。
前端虽然自己看得懂,也会写一部分,但如果要我做那种交互效果,虽然我会,但既然有取巧的办法干嘛不用呢?
六、遇到的问题
这里写一些我写代码过程中比较坑的问题。
1.Semantic UI文件的导入
视频中时采用链接的方式导入,但是我怕部署到服务器上的时候响应会变慢,所以我就采用本地的方式来导入文件,但最主要的原因是官网上找不到cdn链接了,也许是官网不推荐使用了。
不过也遇到了些问题,
首先遇到的是图标显示异常,最后找了下百度,找到了缘由
原因:图标资源未导入。
最简单的办法加入这句
`<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/components/icon.min.css'>`
或者把icon.min.css文件下载到本地,再引入你的html。
但是这有个问题,就是你如果单个文件引入的话,由于其内部src路径是按照压缩包里面写的路径写的,这样就会造成路径问题。
解决方法就是把引用的路径改成现在的路径。这很麻烦,所以我才用另外一种,将这个文件夹复制粘贴至项目根目录,这样,引用的时候只要引用这三句就行了。
<link rel="stylesheet" href="../Semantic-UI-CSS-master/semantic.min.css">、<script src="../Semantic-UI-CSS-master/semantic.min.js"/>
<script src="js/jquery-3.5.1.min.js"/>
当然你认为问题解决了吗?
不,没呢!
我发现图标还是未导入,然后多方查找发现了原因
引入图标,可以去http://www.fontawesome.com.cn/icons中找,因为semantic底层也是用它的图标库,不过引用是原来是fa-angle-double-right,改成angle
double right icon即可
这里我们就可以知道页面jquery.js的引用位置问题,如果导入了其它与jquery有关的js文件,那么jquery.js须在其它js的前面。
所以jquery.js文件的引用必须在semantic UI 的前面。
你以为问题解决了吗?
不,没呢!!!
图标还是不显示!!!
当我近乎绝望的时候,我意外的发现了原因
这两者是有区别的!不然你的js操作都没用。。。后者才能成功导入,不能以/>结尾。别问我为什么知道的!问就是老天可怜我的!
2.maven项目的静态资源问题
当你发现SpringBoot给你报无数据源,可你明明在配置中配置了时,不要怀疑,点开target文件,看看里面是否有你的配置文件!
SpringBoot项目实际上也是maven项目,其项目结构完全参照maven的结构,只是多了些额外的要求。
不例外的,SpringBoot项目启动的时候实际上执行的是target文件夹中的内容,如果你明明配置了可还是给你报错,务必查找下target文件夹下面是否有你所需的文件。
如果没有则需检查你的pom.xml文件里是否配置了静态资源扫描(即是你的某些配置文件是在resource目录下,但并不是所有文件都会扫描进target文件夹的),所以我们必须加入以下配置
<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 --><resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
当然为了一劳永逸我采取的是这种把所有在resource文件夹下文件全部扫描的方式
3.SpringBoot项目的路径问题
在SpringBoot中,引用的文件路径直接写成
不用在前面加上static,且不用…/的形式。
4.数据库中设置默认值可实际操作中字段还是为null
原因:用实体类插入时,没有数据,但是创建实体类的时候默认给了个null,所以插入数据库时会出现null。
解决办法:在实体类定义的时候就给它一个初始化的默认值,这样就不会为空了。
5.mybatis框架报数组越界
一开始我还很奇怪mybatis框架怎么会报数组越界呢?
后来我才知道是因为xml中resultmap写的字段和sql语句不匹配(实体类中不一致也会发生)是会发生这个错误
6.表单怎么发送put请求
其实SpringBoot已经有相应的措施,原理就是SpringBoot默认维护了一个WebMvcAutoConfiguration,其中如果有_method就改变请求方式,不过SpringBoot项目得在配置中开启,默认是关闭的
这时候你要做就是在配置中将这个类设置为true
后再前端表单中加入这么一句即可。
八.部分测试结果及效果展示
这部分其实我不想写的,因为前言里提到了,全部展示出来又太费空间,这里就展示一部分前言里没提到过的效果图
博客管理页
评论管理
列表页
归档页
九、博客部署
这个部分我从租服务器开始讲,直至部署完成!
1、租服务器
这里我选择阿里云的服务器来进行演示
首先把你的账号注册完后打开活动页面,找到云翼计划(因为我是学生,有学生优惠),选择你需要的服务器,我这里选择的是ecs云服务器。
购买支付后打开实例详情
2、连接服务器
点击更多设置你的密码,然后复制公网ip,打开远程桌面连接
输入你的用户名(windows用户名默认是administrator,linux默认是root)和密码即可远程连接至服务器。
3、配置服务器环境
开始安装mysql数据库,以下是下载地址
https://dev.mysql.com/downloads/file/?id=497106
具体操作看这篇博文
安装Navicat,创建myblog数据库,在此数据库中运行sql文件
把你的jdk复制粘贴至服务器,然后配上环境变量
4、把项目打成jar包发布至服务器
在pom.xml中把打包方式设置为jar(<packaging>jar</packaging>
),使用package命令,然后你的target目录下就会出现一个jar文件
将其复制粘贴至服务器上,选择你想要的存储的文件夹下,这里我直接选择c盘(不过建议大家还是创建个文件夹比较好)
在上面地址栏中输入cmd打开命令行,
输入:java -jar blog.jar
启动成功!
5、设置服务器安全组
其实就是设置外网能访问的端口,
不知道怎么打开这个界面的可以看这里https://developer.aliyun.com/article/702814
6、访问项目
博客部署成功了!