SpringBoot技术栈搭建个人博客【后台开发】

前言:在之前,我们已经完成了项目的基本准备,那么就可以开始后台开发了,突然又想到一个问题,就是准备的时候只是设计了前台的RESTful APIs,但是后台管理我们同样也是需要API的,那么就在这一篇里面一起实现了吧...
- 前序文章链接:SpringBoot技术栈搭建个人博客【项目准备】:https://www.jianshu.com/p/0293368fe750
1|0一些设计上的调整
在查了一些资料和吸收了一些评论给出良好的建议之后,我觉得有必要对一些设计进行一些调整:
- 1)数据库:命名应该更加规范,比如表示分类最好用category而不是sort,表示评论最好用comment而不是message;
- 2)RESful APIs:在准备着手开始写后台的时候就已经发现,本来想的是凡是以
/api
开头的都是暴露出来给前端用的,凡是以/admin
开头的都是给后台使用的地址,但是意外的没有设计后天的API也把一些删除命令暴露给了前端,这就不好了重新设计设计; - 3)命名规范的问题:因为使用MyBatis逆向工程自动生成的时候,配置了一个
useActualColumnNames
使用表真正名称的东西,所以整得来生成POJO类基础字段有下划线,看着着实有点不爽,把它给干掉干掉...;
1|1数据库调整
把字段规范了一下,并且删除了分类下是否有效的字段(感觉这种不经常变换的字段留着也没啥用干脆干掉..),所以调整为了下面这个样子(调整字段已标红):

然后重新使用生成器自动生成对应的文件,注意记得修改generatorConfig.xml文件中对应的数据库名称;
创建和修改时间的字段设置
通过查资料发现其实我们可以通过直接设置数据库来自动更新我们的modified_by字段,并且可以像设置初始值那样给create_by和modified_by两个字段以当前时间戳设置默认值,这里具体以tbl_article_info这张表为例:
我们通过设置DEFAULT
为CURRENT_TIMESTAMP
,然后给modified_by字段多添加了一句ON UPDATE CURRENT_TIMESTAMP
,这样它就会在更新的时候将该字段的值设置为更新时间,这样我们就不用在后台关心这两个值了,也少写了一些代码(其实是写代码的时候发现可以这样偷懒..hhh...);
1|2RESTful APIs重新设计
我们需要把一些不能够暴露给前台的API收回,然后再设计一下后台的API,捣鼓了一下,最后大概是这个样子了:
后台Restful APIs:

前台开放RESful APIs:

这些API只是用来和前端交互的接口,另外一些关于日志啊之类的东西就直接在后台写就行了,OK,这样就爽多了,可以开始着手写代码了;
2|0基本配置
随着配置内容的增多,我逐渐的想要放弃.yml的配置文件,主要的一点是这东西不好对内容进行分类(下图是简单配置了一些基本文件后的.yml和.properties文件的对比)..

最后还是用回.properties文件吧,不分类还是有点难受
2|1编码设置
我们首先需要解决的是中文乱码的问题,对应GET请求,我们可以通过修改Tomcat的配置文件【server.xml】来把它默认的编码格式改为UTF-8,而对于POST请求,我们需要统一配置一个拦截器一样的东西把请求的编码统一改成UTF-8:
但是这样设置之后,在后面的使用当中还是会发生提交表单时中文乱码的问题,在网上搜索了一下找到了解决方法,新建一个【config】包创建下面这样一个配置类:
2|2数据库及连接池配置
决定这一次试试Druid的监控功能,所以给一下数据库的配置:
2|3日志配置
在SpringBoot中其实已经使用了Logback来作为默认的日志框架,这是log4j作者推出的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J,在SpringBoot中我们无需再添加额外的依赖就能使用,这是因为在spring-boot-starter-web包中已经有了该依赖了,所以我们只需要进行配置使用就好了
第一步:创建logback-spring.xml
当项目跑起来的时候,我们不可能还去看控制台的输出信息吧,所以我们需要把日志写到文件里面,在网上找到一个例子(链接:http://tengj.top/2017/04/05/springboot7/)
在Spring Boot中你只要按照规则组织文件名,就能够使得配置文件能够被正确加载,并且官方推荐优先使用带有-spring
的文件名作为日志的配置(如上面使用的logback-spring.xml
,而不是logback.xml
),满足这样的命名规范并且保证文件在src/main/resources
下就好了;
第二步:重启项目检查是否成功
我们定义的目录位置为/log/wmyskxz/
,但是在项目的根目录下并没有发现这样的目录,反而是在当前盘符的根目录..不是很懂这个规则..总之是成功了的..

打开是密密麻麻一堆跟控制台一样的【info】级别的信息,因为这个系统本身就比较简单,所以就没有必要去搞什么文本切割之类的东西了,ok..日志算是配置完成;
实际测试了一下,上线之后肯定需要调整输出级别的,不然日志文件就会特别大...
2|4拦截器配置
我们需要对地址进行拦截,对所有的/admin
开头的地址请求进行拦截,因为这是后台管理的默认访问地址开头,这是必须进行验证之后才能访问的地址,正如上面的RESTful APIs,这里包含了一些增加/删除/更改/编辑一类的操作,而统统这些操作都是不能够开放给用户的操作,所以我们需要对这些地址进行拦截:
第一步:创建User实体类
做验证还是需要添加session,不然不好弄,所以我们还是得创建一个常规的实体:
第二步:创建拦截器并继承HandlerInterceptor接口
在【interceptor】包下新建一个【BackInterceptor】类并继承HandlerInterceptor接口:
在拦截器中,我们从session中取出了user,并判断是否符合要求,这里我们直接写死了(并没有更改密码的需求,但需要加密),而且我们并没有做任何的跳转操作,原因很简单,根本就不需要跳转,因为访问后台的用户只有我一个人,所以只需要我知道正确的登录地址就可以了...
第三步:在配置类中复写addInterceptors方法
刚才我们在设置编码的时候自己创建了一个继承自WebMvcConfigurerAdapter的设置类,我们需要复写其中的addInterceptors方法来为我们的拦截器添加配置:
- 说明:这个方法也很简单,通过在addPathPatterns中添加拦截规则(这里设置拦截/admin开头的所有地址),并通过excludePathPatterns来排除拦截的地址(这里为/toLogin,即登录地址,到时候我可以弄得复杂隐蔽一点儿)
第四步:配置登录页面
以前我们在写Spring MVC的时候,如果需要访问一个页面,必须要在Controller中添加一个方法跳转到相应的页面才可以,但是在SpringBoot中增加了更加方便快捷的方法:
- 注意:login.html记得要放在【templates】下才会生效哦...(我试过使用login绑定视图名不成功,只能写全了...)
2|5访问日志记录
上面我们设置了访问限制的拦截器,对后台访问进行了限制,这是拦截器的好处,我们同样也使用拦截器对于访问数量进行一个统计
第一步:编写前台访问拦截器
对照着数据库的设计,我们需要保存的信息都从request对象中去获取,然后保存到数据库中即可,代码也很简单:
- 注意:但是需要注意的是测试的时候别把拦截器开了(主要是postHandle方法中中无法强转handler),不然不方便测试...
BrowserUtil是找的网上的一段代码,直接黏贴复制放【util】包下就可以了:
第二步:设置拦截地址
还是在刚才的配置类中,新增这么一条:
2|6设置默认错误页面
在SpringBoot中,默认的错误页面比较丑(如下),所以我们可以自己改得稍微好看一点儿,具体的教程在这里:http://tengj.top/2018/05/16/springboot13/ ,我就搞前台的时候再去弄了...
3|0Service 层开发
这是纠结最久应该怎么写的,一开始我还准备老老实实地利用MyBatis逆向工程生成的一堆东西去给每一个实体创建一个Service的,这样其实就只是对Dao层进行了一层不必要的封装而已,然后通过分析其实主要的业务也就分成几个:文章/评论/分类/日志浏览量这四个部分而已,所以创建这四个Service就好了;
比较神奇的事情是在网上找到一种通用Mapper的最佳实践方法,整个人都惊了,“wtf?还可以这样写哦?”,资料如下:http://tengj.top/2017/12/20/springboot11/
emmmm..我们通过MyBatis的逆向工程,已经很大程度上简化了我们的开发,因为在Dao层我们已经免去了自己写SQL语句,自己写实体,自己写XML映射文件的麻烦,但在Service层我们仍然无可避免的要写一些类似功能的代码,有没有什么方法能把这些比较通用的方法给提取出来呢? 答案就在上面的链接中,oh,简直太酷了...我决定在这里介绍一下...
3|1通用接口开发
在Spring4中,由于支持了泛型注解,再结合通用Mapper,我们的想法得到了一个最佳的实践方法,下面我们来讲解一下:
第一步:创建通用接口
我们把一些常见的,通用的方法统一使用泛型封装在一个通用接口之中:
第二步:实现通用接口类
至此呢,我们的通用接口就开发完成了
第三步:使用通用接口
编写好我们的通用接口之后,使用就变得很方便了,只需要继承相应的通用接口或者通用接口实现类,然后进行简单的封装就行了,下面以SortInfo为例:
对应到SortInfo的RESTful API设计,这样简单的继承就能够很好的支持,但是我们还是使用最原始的方式来创建吧...
3|2Service接口申明
查了一些资料,问了一下实习公司的前辈老师,并且根据我们之前设计好的RESTful APIs,我们很有必要搞一个dto层用于前后端之间的数据交互,这一层主要是对数据库的数据进行一个封装整合,也方便前后端的数据交互,所以我们首先就需要分析在dto层中应该存在哪些数据:
DTO层开发
对应我们的业务逻辑和RESTful APIs,我大概弄了下面几个Dto:
① ArticleDto:
该Dto封装了文章的详细信息,对应RESTful API中的/api/article/{id}
——通过文章ID获取文章信息
②ArticleCommentDto:
该Dto封装的事文章的评论信息,对应/api/comment/article/{id}
——通过文章ID获取某一篇文章的全部评论信息
③ArticleCategoryDto:
该Dto是封装了文章的一些分类信息,对应/admin/category/{id}
——获取某一篇文章的分类信息
④ArticleWithPictureDto:
该Dto封装了文章用于显示的基本信息,对应所有的获取文章集合的RESful APIs
3|3Service接口开发
Service层其实就是对我们业务的一个封装,所以有了RESTful APIs文档,我们可以很轻易的写出对应的业务模块:
文章Service
分类Service
留言Service
系统Service
4|0Controller 层开发
Controller层简单理解的话,就是用来获取数据的,所以只要Service层开发好了Controller层就很容易,就不多说了,只是我们可以把一些公用的东西放到一个BaseController中,比如引入Service:
然后前后台的控制器只需要继承该类就行了,这样的方式非常值得借鉴的,只是因为这个系统比较简单,所以这个BaseController,我看过一些源码,可以在里面弄一个通用的用于返回数据的方法,比如分页数据/错误信息之类的;
5|0记录坑
5|11)MyBatis中Text类型的坑
按照《阿里手册》(简称)上所规范的那样,我把文章的content单独弄成了一张表并且将这个“可能很长”的字段的类型设置成了text类型,但是MyBatis逆向工程自动生成的时候,却把这个text类型的字段单独给列了出去,即在生成的xml中多出了一个<resultMap>
,标识id为ResultMapWithBLOBs
,MyBatis这样做可能的原因还是怕这个字段太长影响前面的字段查询吧,但是操作这样的LONGVARCHAR
类型的字段MyBatis好像并没有集成很好,所以想要很好的操作还是需要给它弄成VARCHAR类型才行;
在generatorConfig.xml中配置生成字段的时候加上这样一句话就好了:
5|22)拦截器中Service注入为null的坑
在编写前台拦截器的时候,我使用@Autowired
注解自动注入了SysService系统服务Service,但是却报nullpointer的错,发现是没有自动注入上,SysService为空..这是为什么呢?排除掉注解没有识别或者没有给Service添加上注解的可能性之后,我发现好像是拦截器拦截的时候Service并没有创建成功造成的,参考这篇文章:https://blog.csdn.net/slgxmh/article/details/51860278,成功解决问题:
其实就是添加上@Bean
注解让ForeInterceptor提前加载;
5|33)数据库sys_log表中operate_by字段的坑
当时设计表的时候,就只是单纯的想要保存一下用户使用的浏览器是什么,其实当时并不知道应该怎么获取获取到的东西又是什么,只是觉得保存浏览器20个字段够了,但后来发现这是很蠢萌的...所以不得不调整数据库的字段长度,好在只需要单方面调整数据库的字段长度就好了:

5|44)保存文章的方式的坑
因为我想要在数据库中保存的是md源码,而返回前台前端希望的是直接拿到html代码,这样就能很方便的输出了,所以这要怎么做呢?找到一篇参考文章:https://my.oschina.net/u/566591/blog/1535380
我们不要搞那么复杂的封装,只要简单弄一个工具类就可以了,在【util】包下新建一个【Markdown2HtmlUtil】:
使用也很简单,只需要在获取一篇文章的时候把ArticleDto里面的md源码转成html代码再返回给前台就好了:
样式之类的交给前台就好了,搞定...
6|0简单总结
关于统计啊日志类的Controller还没有开发,RESful API也没有设计,这里就先发布文章了,因为好像时间有点紧,后台的页面暂时可能开发不完,准备直接开始前台页面显示的开发(主要是自己对前端不熟悉还要学习..),这里对后台进行一个简单的总结:
其实发现当数据库设计好了,RESful APIs设计好了之后,后台的任务变得非常明确,开发起来也就思路很清晰了,只是自己还是缺少一些必要的经验,如对一些通用方法的抽象/层与层之间数据交互的典型设计之类的东西,特别是一些安全方面的东西,网上的资料也比较少一些,也是自己需要学习的地方;
欢迎转载,转载请注明出处!
简书ID:@我没有三颗心脏
github:wmyskxz
欢迎关注公众微信号:wmyskxz_javaweb
分享自己的Java Web学习之路以及各种Java学习资料
__EOF__

本文链接:https://www.cnblogs.com/wmyskxz/p/9207633.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?