写在最前:b站中博客项目除了这个还有一个三更草堂的博客项目也是不错的,三更草堂会比这个完善些,但是码神这个项目也非常好,看完这个再去看三更的,互相补充。(这两个博客项目应该是目前b站最好的了,而且时间也很新)然后把两者项目好的地方吸收一下,会有很多收获的。地址:SpringBoot前后端分离项目实战-博客项目-Java项目

该项目的部署:利用docker+nginx部署码神之路博客项目
这几天在学习b站码神之路的博客项目,记个笔记。
视频地址:https://www.bilibili.com/video/BV1Gb4y1d7zb?spm_id_from=333.337.search-card.all.click
博客界面实现
在这里插入图片描述
博客后台权限界面实现
在这里插入图片描述 技术栈

  • springboot+vue+springbootSecurity+jwt+redis+ThreaLocal

spring boot 练手实战项目说明
码神之路网站所使用的博客,项目简单,需求明确,容易上手,非常适合.做为练手级项目。 blog.mszlu.com
项目讲解说明:

  1. 提供前端工程,只需要实现后端接口即可
  2. 项目以单体架构入手,先快速开发,不考虑项目优化,降低开发负担
  3. 开发完成后,开始优化项目,提升编程思维能力
  4. 比如页面静态化,缓存,云存储,日志等
  5. docker部署上线
  6. 云服务器购买,域名购买,域名备案等

项目使用技术 :

springboot + mybatisplus+redis+mysql

ps:《写在前面》 up视频挺好,但是copyList()与copy()方法,有关vo转换的方法略显麻烦,这部分知道大概就好。

01

工程搭建

  • 这里并没有直接搭建springboot工程,搭建的是maven工程,先搭建一个blog-parent父工程(别忘了标明pom),再搭建子工程。
    在这里插入图片描述

这里看视频时遇到一点关于dependencyManagement问题

Maven实战(六)— dependencies与dependencyManagement的区别

  • dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)
    dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

配置

  • 进行yaml的相关配置,编写mybatisplus分页与跨域的配置,相关知识

跨域https://blog.csdn.net/weixin_42036952/article/details/88564647
url的组成https://blog.csdn.net/ergouge/article/details/8185219
域名https://jnshu.blog.csdn.net/article/details/84099099
域名、ip之间的关系https://blog.csdn.net/github_38687585/article/details/80943067
dns解析https://blog.csdn.net/yanshuanche3765/article/details/82589210
dns解析https://blog.csdn.net/zzg19950824/article/details/79518678
/、/*、/**的区别https://blog.csdn.net/weixin_49258262/article/details/117756636

首页-文章列表

restful风格https://blog.csdn.net/weixin_46594796/article/details/114673114
https://blog.csdn.net/qq_27026603/article/details/82012277
do与vo的区别https://blog.csdn.net/jslrjb/article/details/86597851

这里出现了copyList()与copy()方法,是为了将从数据库中的查询出来的对象转换为vo对象。

给文章加上标签----》调用了tagService类中的findTagsByArticleId方法----》进行连表查询

BeanUtils.copyProperties的使用(深拷贝,浅拷贝)

java中的DateTime的使用

首页-最热标签

这里8.0的nysql使用groupby语句会出现问题
https://blog.csdn.net/shell_girl/article/details/107997547
可以这么写
SELECT tag_id,COUNT() FROM ms_article_tag GROUP BY tag_id ORDER BY COUNT()DESC

关于mybatis动态排序的问题https://blog.csdn.net/LitongZero/article/details/83753813
Mybatis的循环(foreach)取值详解
这里使用mybatis-plus的selectBatchIds方法会更简便
springboot之mybatis完美一击mybatis-plus

02

统一异常处理

对加了@Controller注解的方法进行拦截校验处理 ,AOP的实现
https://blog.csdn.net/qq_41107231/article/details/115874974
https://blog.csdn.net/wshl1234567/article/details/106564438
在这里插入图片描述

首页-最热文章

queryWrapper.last("limit "+limit);
"limit"要加空格

首页-最新文章

首页-文章归档

时间戳
https://blog.csdn.net/Beautifulcoco/article/details/109645481
https://blog.csdn.net/qq_28483283/article/details/80583197

03

登录jwt

登录逻辑
/**
* 1.检查参数是否合法
* 2.根据用户名和密码去user表中查询是否存在
* 3.如果不存在,登录失败
* 4.如果存在,使用jwt 生成token 返回给前端
* 5.token放入redis当中,redis token:user信息 设置过期时间
* (登录认证的时候,先认证token字符串是否合法,去redis认证是否存在)
*/

java枚举类https://blog.csdn.net/newbie_907486852/article/details/81027512

redis https://blog.csdn.net/weixin_46468474/article/details/109807495

获取用户信息

/**
* 1.token合法性校验
* 是否为空,解析是否成功,redis是否存在
* 2.如果校验失败 返回错误
* 3.如果成功,返回对应的结果 LoginUserVo
*/

退出登录

04

注册

sso单点登录https://blog.csdn.net/qq_38011415/article/details/113695587
sso单点登录https://blog.csdn.net/cnpinpai/article/details/90669587

    /**
     * 1.判断参数是否合法
     * 2.判断账户是否存在,存在,返回账户已经被注册
     * 3.不存在,注册账户
     * 4.生成token
     * 5.存入redis 并返回
     * 6.注意加上事务,一旦中间的任何过程出现问题,注册的账户需要回滚
     */

@Transactional
https://blog.csdn.net/nextyu/article/details/78669997
https://blog.csdn.net/m0_37779570/article/details/81352587

登录拦截器

拦截器与过滤器的区别

    //在执行方法之前执行controller(Handler)之前执行
    /**
     * 1.需要判断,请求的接口路径 是否为HandlerMethod(controller方法)
     * 2.判断token是否为空 如果为空 未登录
     * 3.如果token不为空,登录验证 loginService checkToken
     * 4.如果认证成功
     */

日志占位符@Slf4j

ThreadLocal保存用户信息

preHandle、postHandle与afterCompletion的区别

使用ThreadLocal保存用户登录信息
用户登录信息保存在ThreadLocal中
ThreadLocal
https://blog.csdn.net/u010445301/article/details/111322569
https://blog.csdn.net/Mrs_chens/article/details/90694392
内存泄漏https://blog.csdn.net/qq_36631580/article/details/89375140

05

文章详情

@RequestParam,@PathParam,@PathVariable等注解区别
https://blog.csdn.net/u011410529/article/details/66974974

使用线程池 更新阅读次数

  //查看完文章了,新增阅读数,有没有问题呢?
 //查看完文章之后,本应该直接返回数据了,这时候做了一个更新操作,更新时加写锁,阻塞其他读操作,性能就会比较低
//更新 增加了此次接口的耗时 如果一旦跟新出现了问题,不能影响 查看文章的操作
//线程池    可以把更新操作 扔到线程池中去执行, 和主线程就不相关了

线程池https://blog.csdn.net/u013541140/article/details/95225769
https://blog.csdn.net/qq_43061290/article/details/106911277
CAShttps://blog.csdn.net/wengyupeng/article/details/90239411
https://blog.csdn.net/ls5718/article/details/52563959
乐观锁https://blog.csdn.net/sunwenhao_2017/article/details/81565783

可以把查看文章增加阅读量这个高频操作的数据放到redis,定时从redis更新到数据库
使用redis统计阅读量

小问题:实体类中要用包装类,基本类型有默认初值0,会影响对数据库更新等操作。

06

07

AOP记录日志

https://blog.csdn.net/lchq1995/article/details/80663169
https://blog.csdn.net/qq_35206261/article/details/81945618

总结

  1. jwt+redis
    token令牌的登录方式
  2. threadlocal使用了保存用户信息,请求的线程之内,可以随时获取登录的用户,做了线程隔离
  3. 在使用了threadLocal之后,做了value的删除,防止内存泄漏
  4. 线程的安全-自旋锁
  5. 线程池 7个核心参数(对当前的主业务流程 无影响的操作,放入线程池执行)
  6. 权限系统
  7. 统一日志记录,统一缓存处理
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐