├── .gitattributes ├── .gitignore ├── README.md ├── bin └── sens.sh ├── deploy.sh ├── img ├── 1-首页.png ├── 10-文章详情2.png ├── 11-文章评论.png ├── 12-活跃用户.png ├── 13-分类列表.png ├── 14-标签列表.png ├── 15-用户主页-文章列表.png ├── 16-文章搜索.png ├── 17-登录.png ├── 18-文章管理.png ├── 19-文章发布.png ├── 2-推荐文章.png ├── 20-分类管理.png ├── 21-标签管理.png ├── 22-评论管理.png ├── 23-反馈管理.png ├── 24-用户管理.png ├── 25-用户编辑.png ├── 26-普通用户登录后台的文章管理.png ├── 3-热门文章.png ├── 4-我发布的.png ├── 5-我收藏的.png ├── 6-我点赞的.png ├── 7-我的关注.png ├── 8-我的粉丝.png ├── 9-文章详情1.png ├── ChuyunBlog-ER.png ├── ChuyunBlog-idea.png └── ChuyunBlog-navicat.png ├── pom.xml └── src └── main ├── java └── com │ └── example │ └── blog │ ├── Application.java │ ├── common │ ├── base │ │ ├── BaseEntity.java │ │ └── BaseService.java │ └── constant │ │ └── CommonConstant.java │ ├── config │ ├── MvcConfig.java │ ├── mybatisplus │ │ └── MybatisPlusConfig.java │ ├── properties │ │ └── IgnoredUrlsProperties.java │ └── shiro │ │ ├── MyRealm.java │ │ ├── ShiroConfig.java │ │ └── URLPathMatchingFilter.java │ ├── dto │ ├── JsonResult.java │ ├── PostQueryCondition.java │ └── QueryCondition.java │ ├── entity │ ├── BlackWord.java │ ├── Category.java │ ├── Comment.java │ ├── Friend.java │ ├── Link.java │ ├── Permission.java │ ├── Photo.java │ ├── PhotoCategory.java │ ├── Post.java │ ├── PostCategoryRef.java │ ├── PostTagRef.java │ ├── Role.java │ ├── RolePermissionRef.java │ ├── Tag.java │ ├── User.java │ └── UserRoleRef.java │ ├── enums │ ├── CommonParamsEnum.java │ ├── LogTypeEnum.java │ ├── PostIsRecommendEnum.java │ ├── PostIsStickyEnum.java │ ├── PostStatusEnum.java │ ├── PostTypeEnum.java │ ├── ResourceTypeEnum.java │ ├── ResultCodeEnum.java │ ├── TrueFalseEnum.java │ └── UserStatusEnum.java │ ├── exception │ ├── GlobalExceptionHandler.java │ └── MyBusinessException.java │ ├── mapper │ ├── BlackWordMapper.java │ ├── CategoryMapper.java │ ├── CommentMapper.java │ ├── FriendMapper.java │ ├── LinkMapper.java │ ├── PermissionMapper.java │ ├── PhotoCategoryMapper.java │ ├── PhotoMapper.java │ ├── PostCategoryRefMapper.java │ ├── PostMapper.java │ ├── PostTagRefMapper.java │ ├── RoleMapper.java │ ├── RolePermissionRefMapper.java │ ├── TagMapper.java │ ├── UserMapper.java │ └── UserRoleRefMapper.java │ ├── service │ ├── BlackWordService.java │ ├── CategoryService.java │ ├── CommentService.java │ ├── FriendService.java │ ├── LinkService.java │ ├── MailService.java │ ├── PermissionService.java │ ├── PhotoCategoryService.java │ ├── PhotoService.java │ ├── PostService.java │ ├── RolePermissionRefService.java │ ├── RoleService.java │ ├── TagService.java │ ├── UserRoleRefService.java │ ├── UserService.java │ └── impl │ │ ├── BlackWordServiceImpl.java │ │ ├── CategoryServiceImpl.java │ │ ├── CommentServiceImpl.java │ │ ├── FriendServiceImpl.java │ │ ├── LinkServiceImpl.java │ │ ├── MailServiceImpl.java │ │ ├── PermissionServiceImpl.java │ │ ├── PhotoCategoryServiceImpl.java │ │ ├── PhotoServiceImpl.java │ │ ├── PostServiceImpl.java │ │ ├── RolePermissionRefServiceImpl.java │ │ ├── RoleServiceImpl.java │ │ ├── TagServiceImpl.java │ │ ├── UserRoleRefServiceImpl.java │ │ └── UserServiceImpl.java │ ├── vo │ ├── PageVo.java │ └── SearchVo.java │ └── 需要完整代码联系博主.txt └── resources ├── application.yaml ├── mapper ├── CategoryMapper.xml ├── CommentMapper.xml ├── LinkMapper.xml ├── PermissionMapper.xml ├── PostCategoryRefMapper.xml ├── PostMapper.xml ├── PostTagRefMapper.xml ├── RoleMapper.xml ├── RolePermissionRefMapper.xml ├── TagMapper.xml ├── TaskMapper.xml ├── UserMapper.xml └── UserRoleRefMapper.xml └── 前端完整代码联系博主.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=Java 2 | *.css linguist-language=Java 3 | *.html linguist-language=Java 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | logs/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | log/ 20 | 21 | ### NetBeans ### 22 | nbproject/private/ 23 | build/ 24 | nbbuild/ 25 | dist/ 26 | nbdist/ 27 | .nb-gradle/ 28 | 29 | ### Mac 30 | .DS_Store 31 | */.DS_Store 32 | 33 | ### VS Code ### 34 | *.project 35 | *.factorypath 36 | 37 | ### 屏蔽,需要完整代码联系博主:微信847064370 38 | *.html 39 | /templates 40 | /static 41 | /mapper 42 | /mapper 43 | /webapp 44 | .zip 45 | /controller 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 最新消息,博主已开通B站账号:[Java刘哥](https://space.bilibili.com/160340478),欢迎关注,分享自己原创免费Java实战课程、各种框架实战和技巧、以及公司项目经验 2 | 3 | ## 博主开发的其他博客或论坛项目全部在这里 4 | **[https://liuyanzhao.com/shop.html?k=博客](https://liuyanzhao.com/shop.html?k=博客)**
5 | **[https://liuyanzhao.com/shop.html?k=论坛](https://liuyanzhao.com/shop.html?k=论坛)**
6 | - ------------------------------------------------------------------------------- 7 | # SpringBoot博客 8 | 基于 SpringBoot 实现的博客系统,包含用户注册、登录、找回密码、文章管理、分类管理、标签管理、评论管理、相册管理、关注粉丝、点赞、收藏、举报、相册管理、公告管理、用户管理、角色管理和权限管理等功能。
9 | [详细说明](http://liuyanzhao.com/shop/chuyunblog.html)
10 | 预览地址:[http://chuyunblog.liuyanzhao.com](http://chuyunblog.liuyanzhao.com) 11 | 12 | ## 技术组成 13 | 该项目分为 SpringBoot、SpringBoot+Dubbo 和 SSM 多个版本,当前仓库代码属于 SpringBoot 版本
14 | 15 | - [初云博客-SpringBoot博客版本](http://github.com/saysky/ChuyunBlog) 16 | - [初云博客-SSM博客增强版本](http://github.com/saysky/SSMBlogPlus) 17 | - [初云博客-SSM博客普通版本](http://github.com/saysky/ChuyunBlog-SSM) 18 | - [初云博客-Dubbo博客版本](http://github.com/saysky/ChuyunBlog-Dubbo) 19 | - [学车论坛-SpringBoot论坛版本](http://github.com/saysky/forum) 20 | - [动漫平台-SpringBoot动漫版本](http://github.com/saysky/cartoon) 21 | 22 | 三者功能基本一致,技术组织不同,目前SpringBoot版本功能最多。 23 | - SpringBoot 版本:SpringBoot+MyBatis+Shiro+Thymeleaf+BootStrap 24 | - SSM 版本(SSM增强版):Spring+SpringMVC+MyBatis+Thymeleaf+BootStrap 25 | - Dubbo 版本:Dubbo+SpringBoot+MyBatis+Shiro+Thymeleaf+BootStrap 26 | 27 | 该项目最近写了一篇 10000 字的左右论文,作为参考
28 | 29 | ## 项目截图 30 | 目前只截取了部分页面图片,完整功能请前往预览网站体验。
31 | 32 | 1. 代码结构 33 | ![1-ER图.png](img/ChuyunBlog-idea.png) 34 | 35 | 2. 数据库表 36 | ![1-ER图.png](img/ChuyunBlog-navicat.png) 37 | 表名称分别是:
38 | 黑名单表、文章分类表、评论表、好友关系表、友情链接表、权限表、照片表、相册表、文章表、文章分类关联表、文章标签关联表、角色表、角色权限关联表、文章标签表、用户表、用户角色关联表 39 | 40 | 41 | 3. 数据库ER图如下(下载本地放大查看) 42 | ![1-ER图.png](img/ChuyunBlog-ER.png) 43 | 44 | 45 | ## 预览 46 | 1-首页.png 47 | ![1-首页.png](img/1-首页.png) 48 | 2-推荐文章.png 49 | ![2-推荐文章.png](img/2-推荐文章.png) 50 | 3-热门文章.png 51 | ![3-热门文章.png](img/3-热门文章.png) 52 | 4-我发布的.png 53 | ![4-我发布的.png](img/4-我发布的.png) 54 | 5-我收藏的.png 55 | ![5-我收藏的.png](img/5-我收藏的.png) 56 | 6-我点赞的.png 57 | ![6-我点赞的.png](img/6-我点赞的.png) 58 | 7-我的关注.png 59 | ![7-我的关注.png](img/7-我的关注.png) 60 | 8-我的粉丝.png 61 | ![8-我的粉丝.png](img/8-我的粉丝.png) 62 | 9-文章详情1.png 63 | ![9-文章详情1.png](img/9-文章详情1.png) 64 | 10-文章详情2.png 65 | ![10-文章详情2.png](img/10-文章详情2.png) 66 | 11-文章评论.png 67 | ![11-文章评论.png](img/11-文章评论.png) 68 | 12-活跃用户.png 69 | ![12-活跃用户.png](img/12-活跃用户.png) 70 | 13-分类列表.png 71 | ![13-分类列表.png](img/13-分类列表.png) 72 | 14-标签列表.png 73 | ![14-标签列表.png](img/14-标签列表.png) 74 | 15-用户主页-文章列表.png 75 | ![15-用户主页-文章列表.png](img/15-用户主页-文章列表.png) 76 | 16-文章搜索.png 77 | ![16-文章搜索.png](img/16-文章搜索.png) 78 | 17-登录.png 79 | ![17-登录.png](img/17-登录.png) 80 | 18-文章管理.png 81 | ![18-文章管理.png](img/18-文章管理.png) 82 | 19-文章发布.png 83 | ![19-文章发布.png](img/19-文章发布.png) 84 | 20-分类管理.png 85 | ![20-分类管理.png](img/20-分类管理.png) 86 | 21-标签管理.png 87 | ![21-标签管理.png](img/21-标签管理.png) 88 | 22-评论管理.png 89 | ![22-评论管理.png](img/22-评论管理.png) 90 | 23-反馈管理.png 91 | ![23-反馈管理.png](img/23-反馈管理.png) 92 | 24-用户管理.png 93 | ![24-用户管理.png](img/24-用户管理.png) 94 | 25-用户编辑.png 95 | ![25-用户编辑.png](img/25-用户编辑.png) 96 | 26-普通用户登录后台的文章管理.png 97 | ![26-普通用户登录后台的文章管理.png](img/26-普通用户登录后台的文章管理.png) 98 | 99 | 100 | 101 | ## 联系方式 102 | 该项目可用于个人博客使用或者多用户博客使用,毕设等。
103 | 长期更新!大家可以提需求,我可以及时更新!
104 | 支持定制,加功能,减功能
105 | 需要完整代码,联系本人,提供源码,远程部署和问题解答
106 | 微信:847064370
107 | 108 | ## 更新历史 109 | - 2021年4月18日 新增验证码、收藏、反馈、点赞等,优化部分功能 110 | - 2021年03月05日 新增相册管理、照片管理、好友管理、公告管理 111 | - ... 更新若干次,同时开发了SSM版本,Dubbo版本,SSMBlogPlus版本 112 | - 2020年04月11日 首次提交,实现基本功能 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /bin/sens.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP_NAME=ChuyunBlog.jar 3 | port=8080 4 | 5 | usage() { 6 | echo "用法: sh sens.sh [start(启动)|stop(停止)|restart(重启)|status(状态)]" 7 | exit 1 8 | } 9 | 10 | is_exist(){ 11 | pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` 12 | if [ -z "${pid}" ]; then 13 | return 1 14 | else 15 | return 0 16 | fi 17 | } 18 | 19 | start(){ 20 | is_exist 21 | if [ $? -eq "0" ]; then 22 | echo "${APP_NAME} 正在运行。 pid=${pid} ." 23 | else 24 | nohup java -jar $APP_NAME --server.port=${port} & 25 | echo "${APP_NAME}启动成功,请查看日志确保运行正常。" 26 | fi 27 | } 28 | 29 | stop(){ 30 | is_exist 31 | if [ $? -eq "0" ]; then 32 | kill -9 $pid 33 | echo "${pid} 进程已被杀死,程序停止运行" 34 | else 35 | echo "${APP_NAME} 没有运行。" 36 | fi 37 | } 38 | 39 | status(){ 40 | is_exist 41 | if [ $? -eq "0" ]; then 42 | echo "${APP_NAME} 正在运行。Pid is ${pid}" 43 | else 44 | echo "${APP_NAME} 没有运行。" 45 | fi 46 | } 47 | 48 | restart(){ 49 | stop 50 | start 51 | } 52 | 53 | case "$1" in 54 | "start") 55 | start 56 | ;; 57 | "stop") 58 | stop 59 | ;; 60 | "status") 61 | status 62 | ;; 63 | "restart") 64 | restart 65 | ;; 66 | *) 67 | usage 68 | ;; 69 | esac 70 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 指定SENS的根目录,请按实际修改 4 | SENS_DIR="/www/wwwroot/ChuyunBlog" 5 | # 拉取最新的源码 6 | git pull 7 | echo "代码拉取完毕!" 8 | 9 | # 进入SENS根目录 10 | cd $SENS_DIR 11 | 12 | # 停止SENS 13 | sh $SENS_DIR/sens.sh stop 14 | 15 | # 执行打包 16 | mvn clean package -Dmaven.test.skip=true 17 | echo "代码打包完毕!" 18 | 19 | ## 进入打包好的SENS目录 20 | cd $SENS_DIR/target 21 | 22 | # 运行SENS 23 | sh $SENS_DIR/sens.sh start 24 | 25 | -------------------------------------------------------------------------------- /img/1-首页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/1-首页.png -------------------------------------------------------------------------------- /img/10-文章详情2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/10-文章详情2.png -------------------------------------------------------------------------------- /img/11-文章评论.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/11-文章评论.png -------------------------------------------------------------------------------- /img/12-活跃用户.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/12-活跃用户.png -------------------------------------------------------------------------------- /img/13-分类列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/13-分类列表.png -------------------------------------------------------------------------------- /img/14-标签列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/14-标签列表.png -------------------------------------------------------------------------------- /img/15-用户主页-文章列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/15-用户主页-文章列表.png -------------------------------------------------------------------------------- /img/16-文章搜索.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/16-文章搜索.png -------------------------------------------------------------------------------- /img/17-登录.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/17-登录.png -------------------------------------------------------------------------------- /img/18-文章管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/18-文章管理.png -------------------------------------------------------------------------------- /img/19-文章发布.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/19-文章发布.png -------------------------------------------------------------------------------- /img/2-推荐文章.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/2-推荐文章.png -------------------------------------------------------------------------------- /img/20-分类管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/20-分类管理.png -------------------------------------------------------------------------------- /img/21-标签管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/21-标签管理.png -------------------------------------------------------------------------------- /img/22-评论管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/22-评论管理.png -------------------------------------------------------------------------------- /img/23-反馈管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/23-反馈管理.png -------------------------------------------------------------------------------- /img/24-用户管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/24-用户管理.png -------------------------------------------------------------------------------- /img/25-用户编辑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/25-用户编辑.png -------------------------------------------------------------------------------- /img/26-普通用户登录后台的文章管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/26-普通用户登录后台的文章管理.png -------------------------------------------------------------------------------- /img/3-热门文章.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/3-热门文章.png -------------------------------------------------------------------------------- /img/4-我发布的.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/4-我发布的.png -------------------------------------------------------------------------------- /img/5-我收藏的.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/5-我收藏的.png -------------------------------------------------------------------------------- /img/6-我点赞的.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/6-我点赞的.png -------------------------------------------------------------------------------- /img/7-我的关注.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/7-我的关注.png -------------------------------------------------------------------------------- /img/8-我的粉丝.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/8-我的粉丝.png -------------------------------------------------------------------------------- /img/9-文章详情1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/9-文章详情1.png -------------------------------------------------------------------------------- /img/ChuyunBlog-ER.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/ChuyunBlog-ER.png -------------------------------------------------------------------------------- /img/ChuyunBlog-idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/ChuyunBlog-idea.png -------------------------------------------------------------------------------- /img/ChuyunBlog-navicat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saysky/ChuyunBlog/00afe0e7d0938308cae3d8ae139d658d36041969/img/ChuyunBlog-navicat.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.example 6 | ChunyunBlog 7 | 1.0.0 8 | ChunyunBlog 9 | 10 | 11 | 12 | 基于SpringBoot的博客系统 13 | 14 | 15 | 16 | 17 | saysky 18 | 言曌 19 | admin@example.com 20 | https://example.com 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-parent 27 | 2.1.7.RELEASE 28 | 29 | 30 | 31 | 32 | UTF-8 33 | UTF-8 34 | 1.8 35 | 1.1.10 36 | 1.18.2 37 | 3.8 38 | 4.1.13 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-web 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-tomcat 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-test 57 | test 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-aop 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-undertow 69 | 70 | 71 | 72 | 73 | com.baomidou 74 | mybatis-plus-boot-starter 75 | 3.1.2 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-starter-jdbc 80 | 81 | 82 | 83 | 84 | 85 | mysql 86 | mysql-connector-java 87 | runtime 88 | 89 | 90 | 91 | 92 | 93 | com.alibaba 94 | druid-spring-boot-starter 95 | ${druid.version} 96 | 97 | 98 | 99 | 100 | org.springframework.boot 101 | spring-boot-starter-thymeleaf 102 | 103 | 104 | 105 | 106 | 107 | org.projectlombok 108 | lombok 109 | ${lombok.version} 110 | provided 111 | 112 | 113 | 114 | 115 | 116 | org.apache.commons 117 | commons-lang3 118 | ${commons-lang3.version} 119 | 120 | 121 | 122 | 123 | cn.hutool 124 | hutool-all 125 | ${hutool-all.version} 126 | 127 | 128 | 129 | org.springframework.boot 130 | spring-boot-devtools 131 | true 132 | 133 | 134 | 135 | 136 | com.alibaba 137 | fastjson 138 | 1.2.47 139 | 140 | 141 | 142 | com.google.guava 143 | guava 144 | 26.0-jre 145 | 146 | 147 | 148 | redis.clients 149 | jedis 150 | 2.9.0 151 | 152 | 153 | 154 | 155 | 156 | org.apache.shiro 157 | shiro-spring 158 | 1.4.0 159 | 160 | 161 | 162 | 163 | com.github.theborakompanioni 164 | thymeleaf-extras-shiro 165 | 2.0.0 166 | 167 | 168 | com.google.code.gson 169 | gson 170 | 2.8.5 171 | 172 | 173 | 174 | 175 | io.github.biezhi 176 | oh-my-email 177 | 0.0.3 178 | 179 | 180 | 181 | 182 | org.json 183 | json 184 | 20160810 185 | 186 | 187 | 188 | 189 | net.coobird 190 | thumbnailator 191 | 0.4.8 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | aliyun 200 | http://maven.aliyun.com/nexus/content/groups/public 201 | 202 | 203 | 204 | 205 | 206 | aliyun 207 | http://maven.aliyun.com/nexus/content/groups/public 208 | 209 | 210 | 211 | 212 | ChuyunBlog 213 | 214 | 215 | org.springframework.boot 216 | spring-boot-maven-plugin 217 | 218 | true 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/Application.java: -------------------------------------------------------------------------------- 1 | package com.example.blog; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cache.annotation.EnableCaching; 8 | import org.springframework.context.ApplicationContext; 9 | 10 | /** 11 | *
12 |  *     SENS run!
13 |  * 
14 | * 15 | * @author : saysky 16 | * @date : 2017/11/14 17 | */ 18 | @Slf4j 19 | @SpringBootApplication 20 | @EnableCaching 21 | @MapperScan("com.example.blog.mapper*") 22 | public class Application { 23 | 24 | 25 | public static void main(String[] args) { 26 | ApplicationContext context = SpringApplication.run(Application.class, args); 27 | String serverPort = context.getEnvironment().getProperty("server.port"); 28 | log.info("SENS started at http://localhost:" + serverPort); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/common/base/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.common.base; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableLogic; 7 | import com.example.blog.common.constant.CommonConstant; 8 | import lombok.Data; 9 | 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | /** 14 | * @author 言曌 15 | * @date 2019-08-07 00:28 16 | */ 17 | @Data 18 | public class BaseEntity implements Serializable { 19 | 20 | /** 21 | * ID,自动生成 22 | */ 23 | @TableId(type = IdType.AUTO) 24 | private Long id; 25 | 26 | /** 27 | * 删除状态:1删除,0未删除 28 | */ 29 | @TableField(value = "del_flag") 30 | @TableLogic 31 | private Integer delFlag = CommonConstant.STATUS_NORMAL; 32 | 33 | /** 34 | * 创建人用户名 35 | */ 36 | private String createBy; 37 | 38 | /** 39 | * 创建时间 40 | */ 41 | private Date createTime; 42 | 43 | /** 44 | * 更新人 45 | */ 46 | private String updateBy; 47 | 48 | /** 49 | * 更新时间 50 | */ 51 | private Date updateTime; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/common/base/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.common.base; 2 | 3 | import cn.hutool.core.date.DateUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.example.blog.vo.SearchVo; 9 | import com.example.blog.dto.QueryCondition; 10 | 11 | import java.io.Serializable; 12 | import java.lang.reflect.InvocationTargetException; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * @author 言曌 18 | * @date 2019-09-04 22:47 19 | */ 20 | // JDK8函数式接口注解 仅能包含一个抽象方法 21 | public interface BaseService { 22 | 23 | /** 24 | * @return 25 | */ 26 | BaseMapper getRepository(); 27 | 28 | /** 29 | * 根据ID获取 30 | * 31 | * @param id 32 | * @return 33 | */ 34 | default E get(ID id) { 35 | return getRepository().selectById(id); 36 | } 37 | 38 | /** 39 | * 获取所有列表 40 | * 41 | * @return 42 | */ 43 | default List getAll() { 44 | return getRepository().selectList(null); 45 | } 46 | 47 | /** 48 | * 获取总数 49 | * 50 | * @return 51 | */ 52 | default Integer getTotalCount() { 53 | return getRepository().selectCount(null); 54 | } 55 | 56 | /** 57 | * 添加 58 | * 59 | * @param entity 60 | * @return 61 | */ 62 | default E insert(E entity) { 63 | getRepository().insert(entity); 64 | return entity; 65 | } 66 | 67 | /** 68 | * 修改 69 | * 70 | * @param entity 71 | * @return 72 | */ 73 | default E update(E entity) { 74 | getRepository().updateById(entity); 75 | return entity; 76 | } 77 | 78 | /** 79 | * 保存或者更新 80 | * @param entity 81 | * @return 82 | */ 83 | default E insertOrUpdate(E entity) { 84 | try { 85 | Object id = entity.getClass().getMethod("getId").invoke(entity); 86 | if (id != null) { 87 | update(entity); 88 | } else { 89 | insert(entity); 90 | } 91 | } catch (IllegalAccessException e) { 92 | e.printStackTrace(); 93 | } catch (InvocationTargetException e) { 94 | e.printStackTrace(); 95 | } catch (NoSuchMethodException e) { 96 | e.printStackTrace(); 97 | } 98 | return entity; 99 | } 100 | 101 | /** 102 | * 批量保存与修改 103 | * 104 | * @param list 105 | * @return 106 | */ 107 | default List batchInsert(List list) { 108 | for (E e : list) { 109 | getRepository().insert(e); 110 | } 111 | return list; 112 | } 113 | 114 | 115 | /** 116 | * 根据Id删除 117 | * 118 | * @param id 119 | */ 120 | default void delete(ID id) { 121 | getRepository().deleteById(id); 122 | } 123 | 124 | /** 125 | * 批量删除 126 | * 127 | * @param ids 128 | */ 129 | default void batchDelete(List ids) { 130 | getRepository().deleteBatchIds(ids); 131 | } 132 | 133 | 134 | /** 135 | * 根据id批量查询 136 | * @param ids 137 | * @return 138 | */ 139 | default List findByBatchIds(List ids) { 140 | return getRepository().selectBatchIds(ids); 141 | } 142 | 143 | /** 144 | * 获取所有 145 | * 146 | * @return 147 | */ 148 | default List findAll() { 149 | return getRepository().selectList(null); 150 | } 151 | 152 | /** 153 | * 根据条件查询获取 154 | * 155 | * @param queryWrapper 156 | * @return 157 | */ 158 | default List findAll(QueryWrapper queryWrapper) { 159 | return getRepository().selectList(queryWrapper); 160 | } 161 | 162 | /** 163 | * 根据查询条件不分页获取 164 | * 165 | * @param condition 166 | * @return 167 | */ 168 | default List findAll(QueryCondition condition) { 169 | E e = condition.getData(); 170 | 171 | //对指定字段查询 172 | QueryWrapper queryWrapper = getQueryWrapper(e); 173 | 174 | return getRepository().selectList(queryWrapper); 175 | } 176 | 177 | /** 178 | * 分页获取 179 | * 180 | * @param page 181 | * @return 182 | */ 183 | default Page findAll(Page page) { 184 | return (Page) getRepository().selectPage(page, null); 185 | } 186 | 187 | /** 188 | * 获得查询器 189 | * 190 | * @param e 191 | * @return 192 | */ 193 | QueryWrapper getQueryWrapper(E e); 194 | 195 | /** 196 | * 根据查询条件分页获取 197 | * 198 | * @param page 199 | * @param condition 200 | * @return 201 | */ 202 | default Page findAll(Page page, QueryCondition condition) { 203 | E e = condition.getData(); 204 | SearchVo searchVo = condition.getSearchVo(); 205 | 206 | //对指定字段查询 207 | QueryWrapper queryWrapper = getQueryWrapper(e); 208 | 209 | //查询日期范围 210 | if (searchVo != null) { 211 | String startDate = searchVo.getStartDate(); 212 | String endDate = searchVo.getEndDate(); 213 | if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) { 214 | Date start = DateUtil.parse(startDate); 215 | Date end = DateUtil.parse(endDate); 216 | queryWrapper.between("create_time", start, end); 217 | } 218 | } 219 | return (Page) getRepository().selectPage(page, queryWrapper); 220 | } 221 | 222 | /** 223 | * 获取查询条件的结果数 224 | * 225 | * @param queryWrapper 226 | * @return 227 | */ 228 | default long count(QueryWrapper queryWrapper) { 229 | return getRepository().selectCount(queryWrapper); 230 | } 231 | 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/common/constant/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.common.constant; 2 | 3 | /** 4 | * 常量 5 | * @author 言曌 6 | */ 7 | public interface CommonConstant { 8 | 9 | /** 10 | * 正常状态 11 | */ 12 | Integer STATUS_NORMAL = 0; 13 | 14 | /** 15 | * 用户密码加盐的盐 16 | */ 17 | String PASSWORD_SALT = "sens"; 18 | 19 | /** 20 | * none 21 | */ 22 | String NONE = "none"; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/MvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config; 2 | 3 | import com.google.common.collect.Maps; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.EnvironmentAware; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.PropertySource; 10 | import org.springframework.core.env.Environment; 11 | import org.springframework.web.servlet.config.annotation.*; 12 | import org.thymeleaf.spring5.view.ThymeleafViewResolver; 13 | 14 | import java.util.Map; 15 | 16 | /** 17 | * 拦截器,资源路径配置 18 | */ 19 | @Slf4j 20 | @Configuration 21 | @EnableWebMvc 22 | @ComponentScan(basePackages = "com.example.blog") 23 | @PropertySource(value = "classpath:application.yaml", encoding = "UTF-8") 24 | public class MvcConfig implements EnvironmentAware, WebMvcConfigurer { 25 | 26 | private Environment env; 27 | @Override 28 | public void setEnvironment(Environment environment) { 29 | this.env=environment; 30 | } 31 | 32 | 33 | @Autowired 34 | private ThymeleafViewResolver viewResolver; 35 | 36 | 37 | /** 38 | * 配置静态资源路径 39 | * 40 | * @param registry registry 41 | */ 42 | @Override 43 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 44 | registry.addResourceHandler("/static/**") 45 | .addResourceLocations("classpath:/static/"); 46 | registry.addResourceHandler("/**") 47 | .addResourceLocations("classpath:/templates/themes/") 48 | .addResourceLocations("classpath:/robots.txt"); 49 | registry.addResourceHandler("/upload/**") 50 | .addResourceLocations("file:///" + System.getProperties().getProperty("user.home") + "/sens/upload/"); 51 | registry.addResourceHandler("/favicon.ico") 52 | .addResourceLocations("classpath:/static/images/favicon.ico"); 53 | 54 | configureThymeleafStaticVars(viewResolver); 55 | } 56 | 57 | @Override 58 | public void addCorsMappings(CorsRegistry registry) { 59 | registry.addMapping("/**") 60 | .allowCredentials(true) 61 | .allowedHeaders("*") 62 | .allowedOrigins("*") 63 | .allowedMethods("*"); 64 | } 65 | 66 | 67 | 68 | 69 | private void configureThymeleafStaticVars(ThymeleafViewResolver viewResolver) { 70 | if (viewResolver != null) { 71 | Map vars = Maps.newHashMap(); 72 | vars.put("staticCdnUrl", env.getProperty("application.staticCdnUrl")); 73 | vars.put("version", env.getProperty("application.version")); 74 | viewResolver.setStaticVariables(vars); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/mybatisplus/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | 9 | /** 10 | * @author 言曌 11 | * @date 2018/12/22 下午1:49 12 | */ 13 | 14 | @Configuration 15 | public class MybatisPlusConfig { 16 | 17 | /*** 18 | * plus 的性能优化 19 | * @return 20 | */ 21 | @Bean 22 | public PerformanceInterceptor performanceInterceptor() { 23 | PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); 24 | /**/ 25 | performanceInterceptor.setMaxTime(1000); 26 | /**/ 27 | performanceInterceptor.setFormat(true); 28 | return performanceInterceptor; 29 | } 30 | 31 | /** 32 | * mybatis-plus分页插件 33 | */ 34 | @Bean 35 | public PaginationInterceptor paginationInterceptor() { 36 | return new PaginationInterceptor(); 37 | } 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/properties/IgnoredUrlsProperties.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config.properties; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * @author example 12 | */ 13 | @Data 14 | @Configuration 15 | @ConfigurationProperties(prefix = "ignored") 16 | public class IgnoredUrlsProperties { 17 | 18 | private List urls = new ArrayList<>(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/shiro/MyRealm.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config.shiro; 2 | 3 | import cn.hutool.core.date.DateUnit; 4 | import cn.hutool.core.date.DateUtil; 5 | import cn.hutool.core.lang.Validator; 6 | import com.example.blog.common.constant.CommonConstant; 7 | import com.example.blog.entity.Permission; 8 | import com.example.blog.entity.Role; 9 | import com.example.blog.service.PermissionService; 10 | import com.example.blog.service.RoleService; 11 | import com.example.blog.service.UserService; 12 | import com.example.blog.entity.User; 13 | import com.example.blog.enums.CommonParamsEnum; 14 | import com.example.blog.enums.TrueFalseEnum; 15 | import com.example.blog.enums.UserStatusEnum; 16 | import lombok.extern.slf4j.Slf4j; 17 | import org.apache.commons.lang3.StringUtils; 18 | import org.apache.shiro.authc.*; 19 | import org.apache.shiro.authz.AuthorizationInfo; 20 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 21 | import org.apache.shiro.realm.AuthorizingRealm; 22 | import org.apache.shiro.subject.PrincipalCollection; 23 | import org.apache.shiro.util.ByteSource; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.context.annotation.Lazy; 26 | 27 | import java.util.Date; 28 | import java.util.List; 29 | import java.util.Objects; 30 | import java.util.Set; 31 | import java.util.stream.Collectors; 32 | 33 | @Slf4j 34 | public class MyRealm extends AuthorizingRealm { 35 | 36 | @Autowired 37 | @Lazy 38 | private UserService userService; 39 | 40 | @Autowired 41 | @Lazy 42 | private RoleService roleService; 43 | 44 | @Autowired 45 | @Lazy 46 | private PermissionService permissionService; 47 | 48 | 49 | /** 50 | * 认证信息(身份验证) Authentication 是用来验证用户身份 51 | */ 52 | @Override 53 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 54 | log.info("认证-->MyShiroRealm.doGetAuthenticationInfo()"); 55 | //1.验证用户名 56 | User user; 57 | String account = (String) token.getPrincipal(); 58 | if (Validator.isEmail(account)) { 59 | user = userService.findByEmail(account); 60 | } else { 61 | user = userService.findByUserName(account); 62 | } 63 | if (user == null) { 64 | //用户不存在 65 | log.info("用户不存在! 登录名:{}, 密码:{}", account, token.getCredentials()); 66 | return null; 67 | } 68 | Role role = roleService.findByUserId(user.getId()); 69 | if (role != null) { 70 | user.setRole(role.getRole()); 71 | } 72 | 73 | 74 | //2.判断账号是否被封号 75 | if (!Objects.equals(user.getStatus(), UserStatusEnum.NORMAL.getCode())) { 76 | throw new LockedAccountException("账号被封禁"); 77 | } 78 | 79 | //3.首先判断是否已经被禁用已经是否已经过了10分钟 80 | Date loginLast = DateUtil.date(); 81 | if (null != user.getLoginLast()) { 82 | loginLast = user.getLoginLast(); 83 | } 84 | Long between = DateUtil.between(loginLast, DateUtil.date(), DateUnit.MINUTE); 85 | if (StringUtils.equals(user.getLoginEnable(), TrueFalseEnum.FALSE.getValue()) && (between < CommonParamsEnum.TEN.getValue())) { 86 | log.info("账号已锁定! 登录名:{}, 密码:{}", account, token.getCredentials()); 87 | throw new LockedAccountException("账号被锁定,请10分钟后再试"); 88 | } 89 | //4.封装authenticationInfo,准备验证密码 90 | SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( 91 | user, // 用户名 92 | user.getUserPass(), // 密码 93 | ByteSource.Util.bytes(CommonConstant.PASSWORD_SALT), // 盐 94 | getName() // realm name 95 | ); 96 | System.out.println("realName:" + getName()); 97 | return authenticationInfo; 98 | } 99 | 100 | 101 | @Override 102 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 103 | 104 | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 105 | User user = (User) principals.getPrimaryPrincipal(); 106 | 107 | Role role = roleService.findByUserId(user.getId()); 108 | 109 | authorizationInfo.addRole(role.getRole()); 110 | List permissions = permissionService.listPermissionsByRoleId(role.getId()); 111 | //把权限的URL全部放到authorizationInfo中去 112 | Set urls = permissions.stream().map(p -> p.getUrl()).collect(Collectors.toSet()); 113 | authorizationInfo.addStringPermissions(urls); 114 | 115 | return authorizationInfo; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/shiro/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config.shiro; 2 | 3 | import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 4 | import com.example.blog.config.properties.IgnoredUrlsProperties; 5 | import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher; 6 | import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 7 | import org.apache.shiro.mgt.SecurityManager; 8 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 9 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | import javax.servlet.Filter; 14 | import java.util.LinkedHashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | 19 | @Configuration 20 | public class ShiroConfig { 21 | 22 | @Bean 23 | public ShiroDialect shiroDialect() { 24 | return new ShiroDialect(); 25 | } 26 | 27 | @Bean 28 | IgnoredUrlsProperties getIgnoredUrlsProperties() { 29 | return new IgnoredUrlsProperties(); 30 | } 31 | 32 | @Bean 33 | public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { 34 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 35 | shiroFilterFactoryBean.setSecurityManager(securityManager); 36 | //自定义拦截器 37 | Map filtersMap = new LinkedHashMap(); 38 | //访问权限配置 39 | filtersMap.put("requestURL", getURLPathMatchingFilter()); 40 | shiroFilterFactoryBean.setFilters(filtersMap); 41 | 42 | //拦截器. 43 | Map filterChainDefinitionMap = new LinkedHashMap(); 44 | // 配置不会被拦截的链接 顺序判断 45 | List urls = getIgnoredUrlsProperties().getUrls(); 46 | for (String url : urls) { 47 | filterChainDefinitionMap.put(url, "anon"); 48 | } 49 | filterChainDefinitionMap.put("/admin", "authc"); 50 | filterChainDefinitionMap.put("/admin/**", "requestURL"); 51 | filterChainDefinitionMap.put("/**", "anon"); 52 | 53 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 54 | 55 | 56 | // 如果不设置默认会自动寻找Web工程根目录下的"/login"页面 57 | shiroFilterFactoryBean.setLoginUrl("/login"); 58 | // 登录成功后要跳转的链接 59 | shiroFilterFactoryBean.setSuccessUrl("/"); 60 | //未授权界面; 61 | shiroFilterFactoryBean.setUnauthorizedUrl("/403"); 62 | 63 | return shiroFilterFactoryBean; 64 | 65 | } 66 | 67 | @Bean 68 | public SecurityManager securityManager() { 69 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 70 | securityManager.setRealm(myRealm()); 71 | return securityManager; 72 | } 73 | 74 | 75 | @Bean 76 | public MyRealm myRealm() { 77 | MyRealm normalRealm = new MyRealm(); 78 | normalRealm.setCredentialsMatcher(hashedCredentialsMatcher()); 79 | return normalRealm; 80 | } 81 | 82 | /** 83 | * 访问 权限 拦截器 84 | * 85 | * @return 86 | */ 87 | public URLPathMatchingFilter getURLPathMatchingFilter() { 88 | return new URLPathMatchingFilter(); 89 | } 90 | 91 | /** 92 | * MD5加盐加密十次 93 | * 94 | * @return 95 | */ 96 | @Bean 97 | public HashedCredentialsMatcher hashedCredentialsMatcher() { 98 | HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 99 | //散列算法:这里使用MD5算法; 100 | hashedCredentialsMatcher.setHashAlgorithmName("md5"); 101 | //散列的次数,md5("") 102 | hashedCredentialsMatcher.setHashIterations(10); 103 | return hashedCredentialsMatcher; 104 | } 105 | 106 | @Bean 107 | public AllowAllCredentialsMatcher allowAllCredentialsMatcher() { 108 | return new AllowAllCredentialsMatcher(); 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/config/shiro/URLPathMatchingFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.config.shiro; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.example.blog.service.PermissionService; 5 | import com.example.blog.util.SpringUtil; 6 | import org.apache.shiro.SecurityUtils; 7 | import org.apache.shiro.subject.Subject; 8 | import org.apache.shiro.web.filter.PathMatchingFilter; 9 | import org.apache.shiro.web.util.WebUtils; 10 | 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.PrintWriter; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | /** 20 | * URL拦截器 21 | */ 22 | public class URLPathMatchingFilter extends PathMatchingFilter { 23 | 24 | 25 | PermissionService permissionService = null; 26 | private PermissionService permissionService() { 27 | if (permissionService == null) { 28 | permissionService = (PermissionService) SpringUtil.getBean("permissionServiceImpl"); 29 | } 30 | return permissionService; 31 | } 32 | 33 | @Override 34 | protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { 35 | //请求的url 36 | String requestURL = getPathWithinApplication(request); 37 | System.out.println("请求的url :" + requestURL); 38 | Subject subject = SecurityUtils.getSubject(); 39 | if (!subject.isAuthenticated()) { 40 | // 如果没有登录, 进入登录流程 41 | WebUtils.issueRedirect(request, response, "/login"); 42 | return false; 43 | } 44 | 45 | //从session里读取当前用户的权限URL列表 46 | Set urls = (Set) subject.getSession().getAttribute("permissionUrls"); 47 | if (urls.contains(requestURL)) { 48 | return true; 49 | } 50 | 51 | //没有权限 52 | if (isAjax((HttpServletRequest) request)) { 53 | response.setCharacterEncoding("utf-8"); 54 | response.setContentType("application/json; charset=utf-8"); 55 | PrintWriter writer = response.getWriter(); 56 | Map map = new HashMap<>(); 57 | map.put("code", 0); 58 | map.put("msg", "没有权限访问"); 59 | writer.write(JSONObject.toJSONString(map)); 60 | } else { 61 | WebUtils.issueRedirect(request, response, "/403"); 62 | } 63 | 64 | return false; 65 | } 66 | 67 | 68 | public static boolean isAjax(HttpServletRequest httpRequest) { 69 | return (httpRequest.getHeader("X-Requested-With") != null 70 | && "XMLHttpRequest" 71 | .equals(httpRequest.getHeader("X-Requested-With").toString())); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/dto/JsonResult.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *
 7 |  *     Json格式
 8 |  * 
9 | * 10 | * @author : saysky 11 | * @date : 2018/5/24 12 | */ 13 | @Data 14 | public class JsonResult { 15 | 16 | /** 17 | * 返回的状态码,0:失败,1:成功 18 | */ 19 | private Integer code; 20 | 21 | /** 22 | * 返回信息 23 | */ 24 | private String msg; 25 | 26 | /** 27 | * 返回的数据 28 | */ 29 | private Object result; 30 | 31 | /** 32 | * 不返回数据的构造方法 33 | * 34 | * @param code 状态码 35 | * @param msg 信息 36 | */ 37 | public JsonResult(Integer code, String msg) { 38 | this.code = code; 39 | this.msg = msg; 40 | } 41 | 42 | /** 43 | * 返回数据的构造方法 44 | * 45 | * @param code 状态码 46 | * @param msg 信息 47 | * @param result 数据 48 | */ 49 | public JsonResult(Integer code, String msg, Object result) { 50 | this.code = code; 51 | this.msg = msg; 52 | this.result = result; 53 | } 54 | 55 | /** 56 | * 返回状态码和数据 57 | * 58 | * @param code 状态码 59 | * @param result 数据 60 | */ 61 | public JsonResult(Integer code, Object result) { 62 | this.code = code; 63 | this.result = result; 64 | } 65 | 66 | public static JsonResult error(String msg) { 67 | return new JsonResult(0, msg); 68 | } 69 | public static JsonResult error(String msg, Object data) { 70 | return new JsonResult(0, msg, data); 71 | } 72 | public static JsonResult success() { 73 | return new JsonResult(1, "操作成功"); 74 | } 75 | 76 | public static JsonResult success(String msg) { 77 | return new JsonResult(1, msg); 78 | } 79 | 80 | public static JsonResult success(String msg, Object result) { 81 | return new JsonResult(1, msg, result); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/dto/PostQueryCondition.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author 言曌 7 | * @date 2020/3/12 4:53 下午 8 | */ 9 | @Data 10 | public class PostQueryCondition { 11 | 12 | /** 13 | * 用户ID 14 | */ 15 | private Long userId; 16 | 17 | /** 18 | * 标签ID 19 | */ 20 | private Long tagId; 21 | 22 | /** 23 | * 分类ID 24 | */ 25 | private Long cateId; 26 | 27 | /** 28 | * 关键字 29 | */ 30 | private String keywords; 31 | 32 | /** 33 | * 类型 34 | */ 35 | private String postType; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/dto/QueryCondition.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.dto; 2 | 3 | import com.example.blog.vo.SearchVo; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 查询封装类 10 | * @author 言曌 11 | * @date 2019-08-16 13:45 12 | */ 13 | @Data 14 | public class QueryCondition implements Serializable { 15 | 16 | /** 17 | * 根据字段筛选 18 | */ 19 | private T data; 20 | 21 | /** 22 | * 一般筛选 23 | */ 24 | private SearchVo searchVo; 25 | 26 | 27 | public QueryCondition() { 28 | } 29 | 30 | public QueryCondition(T data) { 31 | this.data = data; 32 | } 33 | 34 | public QueryCondition(T data, SearchVo searchVo) { 35 | this.data = data; 36 | this.searchVo = searchVo; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/BlackWord.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | * 黑名单词语 9 | * @author 言曌 10 | * @date 2020/4/4 10:02 上午 11 | */ 12 | @Data 13 | @TableName("black_word") 14 | public class BlackWord extends BaseEntity { 15 | 16 | /** 17 | * 内容 18 | */ 19 | private String content; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Category.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | *
 9 |  *     文章分类
10 |  * 
11 | * 12 | * @author : saysky 13 | * @date : 2017/11/30 14 | */ 15 | @Data 16 | @TableName("category") 17 | public class Category extends BaseEntity { 18 | 19 | /** 20 | * 分类名称 21 | */ 22 | private String cateName; 23 | 24 | /** 25 | * 分类排序号 26 | */ 27 | private Integer cateSort; 28 | 29 | /** 30 | * 分类描述 31 | */ 32 | private String cateDesc; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Comment.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import com.example.blog.util.RelativeDateFormat; 7 | import lombok.Data; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 回复 13 | */ 14 | @Data 15 | @TableName("comment") 16 | public class Comment extends BaseEntity { 17 | 18 | /** 19 | * 文章ID 20 | */ 21 | private Long postId; 22 | 23 | /** 24 | * 用户ID 25 | */ 26 | private Long userId; 27 | 28 | /** 29 | * 回复内容 30 | */ 31 | private String commentContent; 32 | 33 | /** 34 | * 上一级 35 | */ 36 | private Long commentParent = 0L; 37 | 38 | /** 39 | * 关系路径 40 | */ 41 | private String pathTrace; 42 | 43 | /** 44 | * 接受者用户Id 45 | */ 46 | private Long acceptUserId; 47 | 48 | /** 49 | * 点赞数 50 | */ 51 | private Long likeCount; 52 | 53 | /** 54 | * 点踩数 55 | */ 56 | private Long dislikeCount; 57 | 58 | /** 59 | * 回复文章 60 | */ 61 | @TableField(exist = false) 62 | private Post post; 63 | 64 | 65 | /** 66 | * 回复人 67 | */ 68 | @TableField(exist = false) 69 | private User user; 70 | 71 | 72 | /** 73 | * 当前回复下的所有子回复 74 | */ 75 | @TableField(exist = false) 76 | private List childComments; 77 | 78 | /** 79 | * 创建时间 80 | */ 81 | @TableField(exist = false) 82 | private String createTimeStr; 83 | 84 | 85 | public String getCreateTimeStr() { 86 | return RelativeDateFormat.format(getCreateTime()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Friend.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import lombok.Data; 7 | 8 | /** 9 | * 好友 10 | * @author 言曌 11 | * @date 2021/3/5 2:34 下午 12 | */ 13 | @Data 14 | @TableName("friend") 15 | public class Friend extends BaseEntity { 16 | 17 | /** 18 | * 用户ID 19 | */ 20 | private Long userId; 21 | 22 | /** 23 | * 好友ID 24 | */ 25 | private Long friendId; 26 | 27 | /** 28 | * 好友 29 | */ 30 | @TableField(exist = false) 31 | private User friendUser; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Link.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | *
 9 |  *     友情链接
10 |  * 
11 | */ 12 | @Data 13 | @TableName("link") 14 | public class Link extends BaseEntity { 15 | 16 | /** 17 | * 友情链接名称 18 | */ 19 | private String linkName; 20 | 21 | /** 22 | * 友情链接地址 23 | */ 24 | private String linkUrl; 25 | 26 | /** 27 | * 友情链接头像 28 | */ 29 | private String linkPic; 30 | 31 | /** 32 | * 友情链接描述 33 | */ 34 | private String linkDesc; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Permission.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import lombok.Data; 7 | 8 | import java.util.List; 9 | 10 | 11 | /** 12 | * 13 | * 权限,后台的菜单 14 | * @author example 15 | */ 16 | @Data 17 | @TableName("permission") 18 | public class Permission extends BaseEntity { 19 | 20 | /** 21 | * 权限名称 22 | */ 23 | private String name; 24 | 25 | /** 26 | * pid 27 | */ 28 | private Long pid; 29 | 30 | /** 31 | * 资源类型 32 | */ 33 | private String resourceType; 34 | 35 | /** 36 | * 请求URL 37 | */ 38 | private String url; 39 | 40 | /** 41 | * 图标 42 | */ 43 | private String icon; 44 | 45 | /** 46 | * 序号(越小越靠前) 47 | */ 48 | private Double sort; 49 | 50 | /** 51 | * 级别 52 | */ 53 | @TableField(exist = false) 54 | private Integer level; 55 | 56 | /** 57 | * 子权限列表 58 | */ 59 | @TableField(exist = false) 60 | private List childPermissions; 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Photo.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | * 相册 9 | * 10 | * @author 言曌 11 | * @date 2021/3/2 2:00 下午 12 | */ 13 | @Data 14 | @TableName("photo") 15 | public class Photo extends BaseEntity { 16 | 17 | /** 18 | * 用户ID 19 | */ 20 | private Long userId; 21 | 22 | /** 23 | * 照片分类 24 | */ 25 | private Long categoryId; 26 | 27 | /** 28 | * 照片名称 29 | */ 30 | private String fileName; 31 | /** 32 | * 照片路径 33 | */ 34 | private String filePath; 35 | /** 36 | * 缩略图路径 37 | */ 38 | private String fileSmallPath; 39 | /** 40 | * 41 | */ 42 | private String fileSuffix; 43 | /** 44 | * 45 | */ 46 | private String fileSize; 47 | /** 48 | * 照片宽高 49 | */ 50 | private String fileWh; 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/PhotoCategory.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | * 相册 9 | * 10 | * @author 言曌 11 | * @date 2021/3/2 2:02 下午 12 | */ 13 | @Data 14 | @TableName("photo_category") 15 | public class PhotoCategory extends BaseEntity { 16 | 17 | /** 18 | * 用户ID 19 | */ 20 | private Long userId; 21 | 22 | /** 23 | * 分类名称 24 | */ 25 | private String cateName; 26 | 27 | /** 28 | * 分类排序号 29 | */ 30 | private Integer cateSort; 31 | 32 | /** 33 | * 分类描述 34 | */ 35 | private String cateDesc; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Post.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import com.example.blog.util.RelativeDateFormat; 7 | import lombok.Data; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * @author example 14 | */ 15 | @Data 16 | @TableName("post") 17 | public class Post extends BaseEntity { 18 | 19 | /** 20 | * 用户ID 21 | */ 22 | private Long userId; 23 | /** 24 | * 文章标题 25 | */ 26 | private String postType; 27 | 28 | /** 29 | * 文章标题 30 | */ 31 | private String postTitle; 32 | 33 | /** 34 | * 文章内容 html格式 35 | */ 36 | private String postContent; 37 | 38 | /** 39 | * 文章摘要 40 | */ 41 | private String postSummary; 42 | 43 | /** 44 | * 缩略图 45 | */ 46 | private String postThumbnail; 47 | 48 | /** 49 | * 0 已发布 50 | * 1 草稿 51 | * 2 回收站 52 | */ 53 | private Integer postStatus; 54 | 55 | /** 56 | * 文章访问量 57 | */ 58 | private Long postViews; 59 | 60 | /** 61 | * 点赞访问量 62 | */ 63 | private Long postLikes; 64 | 65 | /** 66 | * 回复数量(冗余字段,加快查询速度) 67 | */ 68 | private Long commentSize; 69 | 70 | /** 71 | * 是否置顶 72 | */ 73 | private Integer isSticky; 74 | 75 | /** 76 | * 是否推荐 77 | */ 78 | private Integer isRecommend; 79 | 80 | 81 | /** 82 | * 发表用户 多对一 83 | */ 84 | @TableField(exist = false) 85 | private User user; 86 | 87 | /** 88 | * 文章所属分类 89 | */ 90 | @TableField(exist = false) 91 | private Category category; 92 | 93 | /** 94 | * 文章所属标签 95 | */ 96 | @TableField(exist = false) 97 | private List tagList = new ArrayList<>(); 98 | 99 | /** 100 | * 文章的回复 101 | */ 102 | @TableField(exist = false) 103 | private List comments = new ArrayList<>(); 104 | 105 | /** 106 | * 更新时间 107 | */ 108 | @TableField(exist = false) 109 | private String createTimeStr; 110 | 111 | public String getCreateTimeStr() { 112 | return RelativeDateFormat.format(getCreateTime()); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/PostCategoryRef.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | * 文章分类关联表 9 | * 10 | * @author 言曌 11 | * @date 2018/12/24 下午4:16 12 | */ 13 | 14 | @Data 15 | @TableName("post_category_ref") 16 | public class PostCategoryRef extends BaseEntity { 17 | 18 | private static final long serialVersionUID = 1989776329130364722L; 19 | /** 20 | * 文章Id 21 | */ 22 | private Long postId; 23 | 24 | /** 25 | * 分类Id 26 | */ 27 | private Long cateId; 28 | 29 | public PostCategoryRef(Long postId, Long cateId) { 30 | this.postId = postId; 31 | this.cateId = cateId; 32 | } 33 | 34 | public PostCategoryRef() { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/PostTagRef.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | /** 8 | * 文章标签关联表 9 | * 10 | * @author 言曌 11 | * @date 2018/12/24 下午4:16 12 | */ 13 | 14 | @Data 15 | @TableName("post_tag_ref") 16 | public class PostTagRef extends BaseEntity { 17 | 18 | private static final long serialVersionUID = 1989776329130364722L; 19 | /** 20 | * 文章Id 21 | */ 22 | private Long postId; 23 | 24 | /** 25 | * 标签Id 26 | */ 27 | private Long tagId; 28 | 29 | public PostTagRef(Long postId, Long tagId) { 30 | this.postId = postId; 31 | this.tagId = tagId; 32 | } 33 | 34 | public PostTagRef() { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import lombok.Data; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author example 12 | */ 13 | @Data 14 | @TableName("role") 15 | public class Role extends BaseEntity { 16 | 17 | /** 18 | * 角色名称:admin,author,subscriber 19 | */ 20 | private String role; 21 | 22 | /** 23 | * 描述:管理员,作者,订阅者 24 | */ 25 | private String description; 26 | 27 | /** 28 | * 级别 29 | */ 30 | private Integer level; 31 | 32 | /** 33 | * 用户注册默认角色 34 | */ 35 | private Integer isRegisterDefault; 36 | 37 | /** 38 | * 该角色对应的用户数量,非数据库字段 39 | */ 40 | @TableField(exist = false) 41 | private Integer count; 42 | 43 | /** 44 | * 当前角色的权限列表 45 | */ 46 | @TableField(exist = false) 47 | private List permissions; 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/RolePermissionRef.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | @Data 8 | @TableName("role_permission_ref") 9 | public class RolePermissionRef extends BaseEntity { 10 | 11 | /** 12 | * 角色Id 13 | */ 14 | private Long roleId; 15 | 16 | /** 17 | * 权限Id 18 | */ 19 | private Long permissionId; 20 | 21 | public RolePermissionRef() { 22 | } 23 | 24 | public RolePermissionRef(Long roleId, Long permissionId) { 25 | this.roleId = roleId; 26 | this.permissionId = permissionId; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/Tag.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import lombok.Data; 7 | 8 | 9 | /** 10 | *
11 |  *     文章标签
12 |  * 
13 | * 14 | * @author : saysky 15 | * @date : 2018/1/12 16 | */ 17 | @Data 18 | @TableName("tag") 19 | public class Tag extends BaseEntity { 20 | 21 | /** 22 | * 标签名称 23 | */ 24 | private String tagName; 25 | 26 | 27 | /** 28 | * 数量 29 | */ 30 | @TableField(exist = false) 31 | private Integer count; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.example.blog.common.base.BaseEntity; 6 | import com.fasterxml.jackson.annotation.JsonIgnore; 7 | import lombok.Data; 8 | 9 | import javax.validation.constraints.Email; 10 | import javax.validation.constraints.NotBlank; 11 | import java.util.Date; 12 | 13 | /** 14 | * 用户信息 15 | */ 16 | @Data 17 | @TableName("user") 18 | public class User extends BaseEntity { 19 | 20 | /** 21 | * 用户名 22 | */ 23 | @NotBlank(message = "用户名不能为空") 24 | private String userName; 25 | 26 | /** 27 | * 显示名称 28 | */ 29 | private String userDisplayName; 30 | 31 | /** 32 | * 密码 33 | */ 34 | @JsonIgnore 35 | private String userPass; 36 | 37 | /** 38 | * 邮箱 39 | */ 40 | @Email(message = "邮箱格式不正确") 41 | private String userEmail; 42 | 43 | /** 44 | * 头像 45 | */ 46 | private String userAvatar; 47 | 48 | /** 49 | * 说明 50 | */ 51 | private String userDesc; 52 | 53 | /** 54 | * 是否禁用登录 55 | */ 56 | // @JsonIgnore 57 | private String loginEnable = "true"; 58 | 59 | 60 | /** 61 | * 登录错误次数记录 62 | */ 63 | private Integer loginError = 0; 64 | 65 | /** 66 | * 最后一次登录时间 67 | */ 68 | private Date loginLast; 69 | 70 | /** 71 | * 0 正常 72 | * 1 禁用 73 | * 2 已删除 74 | */ 75 | private Integer status = 0; 76 | 77 | /** 78 | * 创建时间 79 | */ 80 | private Date createTime; 81 | 82 | /** 83 | * 角色名称 84 | */ 85 | @TableField(exist = false) 86 | private String role; 87 | 88 | /** 89 | * 文章数 90 | */ 91 | @TableField(exist = false) 92 | private Integer postCount; 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/entity/UserRoleRef.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.example.blog.common.base.BaseEntity; 5 | import lombok.Data; 6 | 7 | 8 | /** 9 | * 用户和角色关联 10 | * @author example 11 | */ 12 | @Data 13 | @TableName("user_role_ref") 14 | public class UserRoleRef extends BaseEntity { 15 | 16 | 17 | /** 18 | * 用户Id 19 | */ 20 | private Long userId; 21 | 22 | /** 23 | * 角色Id 24 | */ 25 | private Long roleId; 26 | 27 | public UserRoleRef(Long userId, Long roleId) { 28 | this.userId = userId; 29 | this.roleId = roleId; 30 | } 31 | 32 | public UserRoleRef() { 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/CommonParamsEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 常用数字 5 | */ 6 | public enum CommonParamsEnum { 7 | 8 | /** 9 | * 数字10 10 | */ 11 | TEN(10), 12 | 13 | /** 14 | * 数字5 15 | */ 16 | FIVE(5), 17 | 18 | /** 19 | * 数字404 20 | */ 21 | NOT_FOUND(404), 22 | 23 | /** 24 | * 数字1024 25 | */ 26 | BYTE(1024); 27 | 28 | private Integer value; 29 | 30 | CommonParamsEnum(Integer value) { 31 | this.value = value; 32 | } 33 | 34 | public Integer getValue() { 35 | return value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/LogTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * @author example 5 | */ 6 | public enum LogTypeEnum { 7 | 8 | /** 9 | * 操作 10 | */ 11 | OPERATION("operation"), 12 | 13 | /** 14 | * 登录 15 | */ 16 | LOGIN("login"), 17 | 18 | /** 19 | * 违规记录 20 | */ 21 | BAN("ban"); 22 | 23 | private String value; 24 | 25 | LogTypeEnum(String value) { 26 | this.value = value; 27 | } 28 | 29 | public String getValue() { 30 | return value; 31 | } 32 | 33 | public void setValue(String value) { 34 | this.value = value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/PostIsRecommendEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 文章推荐枚举 5 | */ 6 | public enum PostIsRecommendEnum { 7 | 8 | /** 9 | * 真 10 | */ 11 | TRUE(1), 12 | 13 | /** 14 | * 假 15 | */ 16 | FALSE(0); 17 | 18 | private Integer value; 19 | 20 | PostIsRecommendEnum(Integer value) { 21 | this.value = value; 22 | } 23 | 24 | public Integer getValue() { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/PostIsStickyEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 文章置顶枚举 5 | */ 6 | public enum PostIsStickyEnum { 7 | 8 | /** 9 | * 真 10 | */ 11 | TRUE(1), 12 | 13 | /** 14 | * 假 15 | */ 16 | FALSE(0); 17 | 18 | private Integer value; 19 | 20 | PostIsStickyEnum(Integer value) { 21 | this.value = value; 22 | } 23 | 24 | public Integer getValue() { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/PostStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | *
 5 |  *     文章状态enum
 6 |  * 
7 | * 8 | * @author : saysky 9 | * @date : 2018/7/1 10 | */ 11 | public enum PostStatusEnum { 12 | 13 | /** 14 | * 已发布 15 | */ 16 | PUBLISHED(0), 17 | 18 | /** 19 | * 草稿 20 | */ 21 | DRAFT(1), 22 | 23 | /** 24 | * 回收站 25 | */ 26 | RECYCLE(2), 27 | 28 | /** 29 | * 待审核 30 | */ 31 | CHECKING(3); 32 | 33 | private Integer code; 34 | 35 | PostStatusEnum(Integer code) { 36 | this.code = code; 37 | } 38 | 39 | public Integer getCode() { 40 | return code; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/PostTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | *
 5 |  *     文章类型enum
 6 |  * 
7 | * 8 | * @author : saysky 9 | * @date : 2018/7/1 10 | */ 11 | public enum PostTypeEnum { 12 | 13 | /** 14 | * 文章 15 | */ 16 | POST_TYPE_POST("post"), 17 | 18 | /** 19 | * 页面 20 | */ 21 | POST_TYPE_PAGE("page"), 22 | 23 | /** 24 | * 公告 25 | */ 26 | POST_TYPE_NOTICE("notice"); 27 | 28 | private String value; 29 | 30 | PostTypeEnum(String value) { 31 | this.value = value; 32 | } 33 | 34 | public String getValue() { 35 | return value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/ResourceTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 资源类型 5 | */ 6 | public enum ResourceTypeEnum { 7 | 8 | /** 9 | * 菜单 10 | */ 11 | MENU("menu", "菜单"), 12 | 13 | /** 14 | * 接口 15 | */ 16 | BUTTON("button", "接口"), 17 | 18 | /** 19 | * 菜单 20 | */ 21 | PAGE("page", "页面"); 22 | 23 | 24 | private String code; 25 | 26 | private String description; 27 | 28 | ResourceTypeEnum(String code, String description) { 29 | this.code = code; 30 | this.description = description; 31 | } 32 | 33 | public String getCode() { 34 | return code; 35 | } 36 | 37 | public void setCode(String code) { 38 | this.code = code; 39 | } 40 | 41 | public String getDescription() { 42 | return description; 43 | } 44 | 45 | public void setDescription(String description) { 46 | this.description = description; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/ResultCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 返回结果enum 5 | */ 6 | public enum ResultCodeEnum { 7 | 8 | /** 9 | * 成功 10 | */ 11 | SUCCESS(1), 12 | 13 | /** 14 | * 失败 15 | */ 16 | FAIL(0); 17 | 18 | Integer code; 19 | 20 | ResultCodeEnum(Integer code) { 21 | this.code = code; 22 | } 23 | 24 | public Integer getCode() { 25 | return code; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/TrueFalseEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * true or false enum 5 | */ 6 | public enum TrueFalseEnum { 7 | 8 | /** 9 | * 真 10 | */ 11 | TRUE("true"), 12 | 13 | /** 14 | * 假 15 | */ 16 | FALSE("false"); 17 | 18 | private String value; 19 | 20 | TrueFalseEnum(String value) { 21 | this.value = value; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/enums/UserStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.enums; 2 | 3 | /** 4 | * 用户状态enum 5 | */ 6 | public enum UserStatusEnum { 7 | 8 | /** 9 | * 正常 10 | */ 11 | NORMAL(0), 12 | 13 | /** 14 | * 禁止登录 15 | */ 16 | BAN(1); 17 | 18 | 19 | private Integer code; 20 | 21 | UserStatusEnum(Integer code) { 22 | this.code = code; 23 | } 24 | 25 | public Integer getCode() { 26 | return code; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.exception; 2 | 3 | import com.example.blog.dto.JsonResult; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.shiro.authz.UnauthorizedException; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.converter.HttpMessageNotReadableException; 8 | import org.springframework.ui.Model; 9 | import org.springframework.validation.BindException; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.validation.FieldError; 12 | import org.springframework.web.HttpMediaTypeNotSupportedException; 13 | import org.springframework.web.HttpRequestMethodNotSupportedException; 14 | import org.springframework.web.bind.MethodArgumentNotValidException; 15 | import org.springframework.web.bind.MissingServletRequestParameterException; 16 | import org.springframework.web.bind.annotation.ControllerAdvice; 17 | import org.springframework.web.bind.annotation.ExceptionHandler; 18 | import org.springframework.web.bind.annotation.ResponseBody; 19 | import org.springframework.web.bind.annotation.ResponseStatus; 20 | import org.springframework.web.servlet.ModelAndView; 21 | import org.springframework.web.servlet.NoHandlerFoundException; 22 | import org.springframework.web.servlet.view.json.MappingJackson2JsonView; 23 | 24 | import javax.servlet.http.HttpServletRequest; 25 | import javax.servlet.http.HttpServletResponse; 26 | import javax.validation.ConstraintViolation; 27 | import javax.validation.ConstraintViolationException; 28 | import javax.validation.ValidationException; 29 | import java.io.IOException; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | import java.util.Set; 33 | 34 | /** 35 | * 全局异常捕获 36 | */ 37 | 38 | @ControllerAdvice 39 | @Slf4j 40 | public class GlobalExceptionHandler { 41 | 42 | //错误显示页面 43 | public static final String viewName = "common/error/error"; 44 | 45 | /** 46 | * 是否是ajax请求 47 | */ 48 | public static boolean isAjax(HttpServletRequest httpRequest) { 49 | return (httpRequest.getHeader("X-Requested-With") != null 50 | && "XMLHttpRequest" 51 | .equals(httpRequest.getHeader("X-Requested-With").toString())); 52 | } 53 | 54 | 55 | /** 56 | * 400 - Bad Request 57 | */ 58 | @ResponseStatus(HttpStatus.BAD_REQUEST) 59 | @ExceptionHandler(MissingServletRequestParameterException.class) 60 | public String handleMissingServletRequestParameterException(MissingServletRequestParameterException e, Model model) { 61 | log.error("缺少请求参数", e); 62 | String message = "【缺少请求参数】" + e.getMessage(); 63 | model.addAttribute("message", message); 64 | model.addAttribute("code", 400); 65 | return viewName; 66 | } 67 | 68 | /** 69 | * 400 - Bad Request 70 | */ 71 | @ResponseStatus(HttpStatus.BAD_REQUEST) 72 | @ExceptionHandler(HttpMessageNotReadableException.class) 73 | public String handleHttpMessageNotReadableException(HttpMessageNotReadableException e, Model model) { 74 | log.error("参数解析失败", e); 75 | String message = "【参数解析失败】" + e.getMessage(); 76 | model.addAttribute("message", message); 77 | model.addAttribute("code", 400); 78 | return viewName; 79 | } 80 | 81 | /** 82 | * 400 - Bad Request 83 | */ 84 | @ResponseStatus(HttpStatus.BAD_REQUEST) 85 | @ExceptionHandler(MethodArgumentNotValidException.class) 86 | public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e, Model model) { 87 | log.error("参数验证失败", e); 88 | BindingResult result = e.getBindingResult(); 89 | FieldError error = result.getFieldError(); 90 | String field = error.getField(); 91 | String code = error.getDefaultMessage(); 92 | String message = "【参数验证失败】" + String.format("%s:%s", field, code); 93 | model.addAttribute("message", message); 94 | model.addAttribute("code", 400); 95 | return viewName; 96 | } 97 | 98 | /** 99 | * 400 - Bad Request 100 | */ 101 | @ResponseStatus(HttpStatus.BAD_REQUEST) 102 | @ExceptionHandler(BindException.class) 103 | public String handleBindException(BindException e, Model model) { 104 | log.error("参数绑定失败", e); 105 | BindingResult result = e.getBindingResult(); 106 | FieldError error = result.getFieldError(); 107 | String field = error.getField(); 108 | String code = error.getDefaultMessage(); 109 | String message = "【参数绑定失败】" + String.format("%s:%s", field, code); 110 | 111 | model.addAttribute("message", message); 112 | model.addAttribute("code", 400); 113 | return viewName; 114 | } 115 | 116 | 117 | /** 118 | * 400 - Bad Request 119 | */ 120 | @ResponseStatus(HttpStatus.BAD_REQUEST) 121 | @ExceptionHandler(ConstraintViolationException.class) 122 | public String handleServiceException(ConstraintViolationException e, Model model) { 123 | log.error("参数验证失败", e); 124 | Set> violations = e.getConstraintViolations(); 125 | ConstraintViolation violation = violations.iterator().next(); 126 | String message = "【参数验证失败】" + violation.getMessage(); 127 | model.addAttribute("message", message); 128 | model.addAttribute("code", 400); 129 | return viewName; 130 | } 131 | 132 | /** 133 | * 400 - Bad Request 134 | */ 135 | @ResponseStatus(HttpStatus.BAD_REQUEST) 136 | @ExceptionHandler(ValidationException.class) 137 | public String handleValidationException(ValidationException e, Model model) { 138 | log.error("参数验证失败", e); 139 | String message = "【参数验证失败】" + e.getMessage(); 140 | model.addAttribute("message", message); 141 | model.addAttribute("code", 400); 142 | return viewName; 143 | } 144 | 145 | /** 146 | * 404 - Not Found 147 | */ 148 | @ResponseStatus(HttpStatus.NOT_FOUND) 149 | @ExceptionHandler(NoHandlerFoundException.class) 150 | public String noHandlerFoundException(NoHandlerFoundException e, Model model) { 151 | log.error("Not Found", e); 152 | String message = "【页面不存在】" + e.getMessage(); 153 | model.addAttribute("message", message); 154 | model.addAttribute("code", 404); 155 | return viewName; 156 | } 157 | 158 | 159 | /** 160 | * 405 - Method Not Allowed 161 | */ 162 | @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) 163 | @ExceptionHandler(HttpRequestMethodNotSupportedException.class) 164 | public String handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, Model model) { 165 | log.error("不支持当前请求方法", e); 166 | String message = "【不支持当前请求方法】" + e.getMessage(); 167 | model.addAttribute("message", message); 168 | model.addAttribute("code", 405); 169 | return viewName; 170 | } 171 | 172 | /** 173 | * 415 - Unsupported Media Type 174 | */ 175 | @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 176 | @ExceptionHandler(HttpMediaTypeNotSupportedException.class) 177 | public String handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, Model model) { 178 | log.error("不支持当前媒体类型", e); 179 | String message = "【不支持当前媒体类型】" + e.getMessage(); 180 | model.addAttribute("message", message); 181 | model.addAttribute("code", 415); 182 | return viewName; 183 | } 184 | 185 | /** 186 | * 统一异常处理 187 | * 188 | * @param response 189 | * @param e 190 | * @return 191 | */ 192 | @ExceptionHandler(MyBusinessException.class) 193 | @ResponseBody 194 | public JsonResult processApiException(HttpServletResponse response, 195 | MyBusinessException e) { 196 | JsonResult result = new JsonResult(0, e.getMessage()); 197 | response.setStatus(200); 198 | response.setContentType("application/json;charset=UTF-8"); 199 | log.error("业务异常,提示前端操作不合法", e.getMessage(), e); 200 | return result; 201 | } 202 | 203 | /** 204 | * 获取其它异常。包括500 205 | * 206 | * @param e 207 | * @return 208 | * @throws Exception 209 | */ 210 | @ExceptionHandler(value = Exception.class) 211 | public ModelAndView defaultErrorHandler(HttpServletRequest request, 212 | HttpServletResponse response, 213 | Exception e, Model model) throws IOException { 214 | e.printStackTrace(); 215 | 216 | if (isAjax(request)) { 217 | ModelAndView mav = new ModelAndView(); 218 | MappingJackson2JsonView view = new MappingJackson2JsonView(); 219 | Map attributes = new HashMap(); 220 | if (e instanceof UnauthorizedException) { 221 | attributes.put("msg", "没有权限"); 222 | } else { 223 | attributes.put("msg", e.getMessage()); 224 | } 225 | attributes.put("code", "0"); 226 | view.setAttributesMap(attributes); 227 | mav.setView(view); 228 | return mav; 229 | } 230 | 231 | if (e instanceof UnauthorizedException) { 232 | //请登录 233 | log.error("无权访问", e); 234 | return new ModelAndView("common/error/403"); 235 | } 236 | //其他异常 237 | String message = e.getMessage(); 238 | model.addAttribute("code", 500); 239 | model.addAttribute("message", message); 240 | return new ModelAndView("common/error/500"); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/exception/MyBusinessException.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.exception; 2 | 3 | /** 4 | * @author 言曌 5 | * @date 2019-08-09 16:47 6 | */ 7 | 8 | public class MyBusinessException extends RuntimeException { 9 | 10 | private Integer code; 11 | 12 | private String message; 13 | 14 | 15 | public MyBusinessException() { 16 | super(); 17 | } 18 | 19 | public MyBusinessException(String message) { 20 | this.code = 500; 21 | this.message = message; 22 | } 23 | 24 | public MyBusinessException(Integer code, String message) { 25 | this.code = code; 26 | this.message = message; 27 | } 28 | 29 | public Integer getCode() { 30 | return code; 31 | } 32 | 33 | public void setCode(Integer code) { 34 | this.code = code; 35 | } 36 | 37 | @Override 38 | public String getMessage() { 39 | return message; 40 | } 41 | 42 | public void setMessage(String message) { 43 | this.message = message; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/BlackWordMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.BlackWord; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author liuyanzhao 9 | */ 10 | @Mapper 11 | public interface BlackWordMapper extends BaseMapper { 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Category; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author liuyanzhao 12 | */ 13 | @Mapper 14 | public interface CategoryMapper extends BaseMapper { 15 | 16 | /** 17 | * 获得某篇文章的分类列表 18 | * 19 | * @param postId 文章Id 20 | * @return List 21 | */ 22 | Category findByPostId(Long postId); 23 | 24 | 25 | /** 26 | * 获得子分类Id列表 27 | * 28 | * @param pathTrace /138/ 这种格式 29 | * @return 子分类Id列表 30 | */ 31 | List selectChildCateIds(@Param("pathTrace") String pathTrace); 32 | 33 | /** 34 | * 根据用户ID删除 35 | * @param userId 36 | * @return 37 | */ 38 | Integer deleteByUserId(Long userId); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/CommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Comment; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author liuyanzhao 12 | */ 13 | @Mapper 14 | public interface CommentMapper extends BaseMapper { 15 | 16 | /** 17 | * 查询前limit条回复 18 | * 19 | * @param limit 查询数量 20 | * @return 回复列表 21 | */ 22 | List findLatestCommentByLimit(Integer limit); 23 | 24 | /** 25 | * 根据用户Id删除 26 | * 27 | * @param userId 用户Id 28 | * @return 影响行数 29 | */ 30 | Integer deleteByUserId(Long userId); 31 | 32 | /** 33 | * 根据用户Id删除 34 | * 35 | * @param userId 用户Id 36 | * @return 影响行数 37 | */ 38 | Integer deleteByAcceptUserId(Long userId); 39 | 40 | /** 41 | * 获得某个ip用户最新的回复 42 | * 43 | * @param ip IP地址 44 | * @return 回复 45 | */ 46 | Comment getLatestCommentByIP(String ip); 47 | 48 | /** 49 | * 获得子回复Id列表 50 | * 51 | * @param pathTrace 回复pathTrace封装 52 | * @return 回复Id列表 53 | */ 54 | List selectChildCommentIds(@Param("pathTrace") String pathTrace); 55 | 56 | /** 57 | * 获得某个用户最新收到的回复 58 | * 59 | * @param userId 收到回复的用户 60 | * @param limit 查询数量 61 | * @return 62 | */ 63 | List getLatestCommentByAcceptUser(@Param("userId") Long userId, 64 | @Param("limit") Integer limit); 65 | 66 | /** 67 | * 根据文章ID获得评论列表 68 | * @param postId 69 | * @return 70 | */ 71 | List findByPostId(Long postId); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/FriendMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Friend; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author 言曌 9 | * @date 2021/3/5 2:40 下午 10 | */ 11 | @Mapper 12 | public interface FriendMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/LinkMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Link; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author liuyanzhao 9 | */ 10 | @Mapper 11 | public interface LinkMapper extends BaseMapper { 12 | 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Permission; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | 11 | /** 12 | * @author example 13 | */ 14 | @Mapper 15 | public interface PermissionMapper extends BaseMapper { 16 | 17 | /** 18 | * 根据角色Id获得权限列表 19 | * 20 | * @param roleId 角色Id 21 | * @return 权限列表 22 | */ 23 | List findByRoleId(Long roleId); 24 | 25 | /** 26 | * 获得某个用户的权限列表 27 | * 28 | * @param userId 29 | * @return 30 | */ 31 | List findPermissionByUserId(Long userId); 32 | 33 | /** 34 | * 获得某个用户的权限列表 35 | * 36 | * @param userId 37 | * @param resourceType 38 | * @return 39 | */ 40 | List findPermissionByUserIdAndResourceType(@Param("userId") Long userId, 41 | @Param("resourceType") String resourceType); 42 | 43 | 44 | /** 45 | * 获得权限列表 46 | * 47 | * @param resourceType 48 | * @return 49 | */ 50 | List findPermissionByResourceType(Integer resourceType); 51 | 52 | /** 53 | * 根据角色ID获得权限列表 54 | * @param roleId 55 | * @return 56 | */ 57 | List findPermissionByRoleId(Long roleId); 58 | 59 | /** 60 | * 统计子节点数量 61 | * @param id 62 | * @return 63 | */ 64 | Integer countChildPermission(Long id); 65 | 66 | /** 67 | * 根据URL获得权限 68 | * @param url 69 | * @return 70 | */ 71 | Permission findByUrl(String url); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PhotoCategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.PhotoCategory; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author 言曌 9 | * @date 2021/3/2 5:39 下午 10 | */ 11 | @Mapper 12 | public interface PhotoCategoryMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PhotoMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Photo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author 言曌 9 | * @date 2021/3/2 5:39 下午 10 | */ 11 | @Mapper 12 | public interface PhotoMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PostCategoryRefMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.PostCategoryRef; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * @author liuyanzhao 12 | */ 13 | @Mapper 14 | public interface PostCategoryRefMapper extends BaseMapper { 15 | 16 | /** 17 | * 根据文章Id删除记录 18 | * 19 | * @param postId 文章Id 20 | * @return 影响行数 21 | */ 22 | Integer deleteByPostId(Long postId); 23 | 24 | /** 25 | * 根据文章Id删除记录 26 | * 27 | * @param postIds 文章Id集合 28 | * @return 影响行数 29 | */ 30 | Integer deleteByPostIds(List postIds); 31 | 32 | /** 33 | * 根据分类Id删除记录 34 | * 35 | * @param cateId 分类Id 36 | * @return 影响行数 37 | */ 38 | Integer deleteByCateId(Long cateId); 39 | 40 | /** 41 | * 根据分类Id查询文章Id 42 | * 43 | * @param cateId 分类Id 44 | * @return 文章Id列表 45 | */ 46 | List selectPostIdByCateId(Long cateId); 47 | 48 | /** 49 | * 根据文章Id查询分类Id 50 | * 51 | * @param postId 文章Id 52 | * @return 分类Id列表 53 | */ 54 | List selectCateIdByPostId(Long postId); 55 | 56 | /** 57 | * 统计某篇分类的文章数 58 | * 59 | * @param cateId 分类Id 60 | * @return 文章Id列表 61 | */ 62 | Integer countPostByCateId(Long cateId); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PostMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.example.blog.dto.PostQueryCondition; 6 | import com.example.blog.entity.Post; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author liuyanzhao 14 | */ 15 | @Mapper 16 | public interface PostMapper extends BaseMapper { 17 | 18 | /** 19 | * 获取所有文章阅读量总和 20 | * 21 | * @return Long 22 | */ 23 | Long getPostViewsSum(); 24 | 25 | /** 26 | * 重置回复数量 27 | * 28 | * @return 数量 29 | */ 30 | Integer resetCommentSize(Long postId); 31 | 32 | /** 33 | * 根据用户Id删除 34 | * 35 | * @return 影响行数 36 | */ 37 | Integer deleteByUserId(Long userId); 38 | 39 | /** 40 | * 文章点赞量+1 41 | * 42 | * @param postId 43 | * @return 44 | */ 45 | Integer incrPostLikes(Long postId); 46 | 47 | /** 48 | * 文章访问量+1 49 | * 50 | * @param postId 51 | * @return 52 | */ 53 | Integer incrPostViews(Long postId); 54 | 55 | 56 | /** 57 | * 获得今日新增数量 58 | * 59 | * @return 60 | */ 61 | Integer getTodayCount(); 62 | 63 | /** 64 | * 根据标签ID查询文章 65 | * 66 | * @param condition 67 | * @param page 68 | * @return 69 | */ 70 | List findPostByCondition(@Param("condition") PostQueryCondition condition, Page page); 71 | 72 | 73 | /** 74 | * 获取某个用户的文章列表 75 | * @param userId 76 | * @return 77 | */ 78 | List selectIdByUserId(Long userId); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/PostTagRefMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.PostTagRef; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author liuyanzhao 11 | */ 12 | @Mapper 13 | public interface PostTagRefMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据文章Id删除记录 17 | * 18 | * @param postId 文章Id 19 | * @return 影响行数 20 | */ 21 | Integer deleteByPostId(Long postId); 22 | 23 | /** 24 | * 根据文章Id删除记录 25 | * 26 | * @param postIds 文章Id集合 27 | * @return 影响行数 28 | */ 29 | Integer deleteByPostIds(List postIds); 30 | 31 | /** 32 | * 根据标签Id删除记录 33 | * 34 | * @param tagId 标签Id 35 | * @return 影响行数 36 | */ 37 | Integer deleteByTagId(Long tagId); 38 | 39 | /** 40 | * 根据标签Id查询文章Id 41 | * 42 | * @param tagId 标签Id 43 | * @return 文章Id列表 44 | */ 45 | List selectPostIdByTagId(Long tagId); 46 | 47 | /** 48 | * 根据文章Id查询标签Id 49 | * @param postId 文章Id 50 | * @return 标签Id列表 51 | */ 52 | List selectTagIdByPostId(Long postId); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Role; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * @author example 12 | */ 13 | @Mapper 14 | public interface RoleMapper extends BaseMapper { 15 | 16 | 17 | /** 18 | * 根据用户Id获得角色 19 | * 20 | * @param userId 用户Id 21 | * @return 角色列表 22 | */ 23 | Role findByUserId(Long userId); 24 | 25 | 26 | /** 27 | * 删除用户和角色管理 28 | * 29 | * @param userId 用户ID 30 | * @return 影响行数 31 | */ 32 | Integer deleteByUserId(Long userId); 33 | 34 | /** 35 | * 统计某个角色的用户数 36 | * 37 | * @param roleId 角色Id 38 | * @return 用户数 39 | */ 40 | Integer countUserByRoleId(Long roleId); 41 | 42 | 43 | /** 44 | * 获得所有角色和对应用户数量 45 | * @return 46 | */ 47 | List findAllWithCount(); 48 | 49 | /** 50 | * 查询小于等于该等级的角色 51 | * @param level 52 | * @return 53 | */ 54 | List findByLessThanLevel(Integer level); 55 | 56 | /** 57 | * 查询某个用户最大的角色等级 58 | * @param userId 59 | * @return 60 | */ 61 | Integer findMaxLevelByUserId(Long userId); 62 | 63 | /** 64 | * 获得用户注册默认角色 65 | * @return 66 | */ 67 | Role findDefaultRole(); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/RolePermissionRefMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.RolePermissionRef; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * @author example 12 | */ 13 | @Mapper 14 | public interface RolePermissionRefMapper extends BaseMapper { 15 | 16 | 17 | /** 18 | * 根据角色Id删除 19 | * 20 | * @param roleId 角色Id 21 | * @return 影响行数 22 | */ 23 | Integer deleteByRoleId(Long roleId); 24 | 25 | /** 26 | * 根据权限Id删除 27 | * 28 | * @param permissionId 权限Id 29 | * @return 影响行数 30 | */ 31 | Integer deleteByPermissionId(Long permissionId); 32 | /** 33 | * 批量添加 34 | * 35 | * @param rolePermissionRefList 列表 36 | * @return 影响喊你高数 37 | */ 38 | Integer batchInsert(List rolePermissionRefList); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/TagMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.Tag; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author liuyanzhao 12 | */ 13 | @Mapper 14 | public interface TagMapper extends BaseMapper { 15 | 16 | /** 17 | * 获得某篇文章的标签列表 18 | * 19 | * @param postId 文章Id 20 | * @return List 21 | */ 22 | List findByPostId(Long postId); 23 | 24 | /** 25 | * 获得所有包括统计文章数 26 | * 27 | * @return 标签列表 28 | */ 29 | List findAllWithCount(Integer limit); 30 | 31 | /** 32 | * 查询没有用过的标签 33 | * 34 | * @return 标签列表 35 | */ 36 | List findTagNotUse(); 37 | 38 | /** 39 | * 根据用户ID删除 40 | * @param userId 41 | * @return 42 | */ 43 | Integer deleteByUserId(Long userId); 44 | 45 | /** 46 | * 热门标签 47 | * @param keywords 48 | * @param limit 49 | * @return 50 | */ 51 | List getHotTags(@Param("keywords") String keywords, 52 | @Param("limit") Integer limit); 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.example.blog.entity.User; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author example 13 | */ 14 | @Mapper 15 | public interface UserMapper extends BaseMapper { 16 | 17 | /** 18 | * 根据角色Id获得用户 19 | * 20 | * @param roleId 角色Id 21 | * @param page 分页信息 22 | * @return 用户列表 23 | */ 24 | List findByRoleId(@Param("roleId") Long roleId, Page page); 25 | 26 | /** 27 | * 根据角色Id和条件获得用户 28 | * 29 | * @param roleId 角色Id 30 | * @param user 条件 31 | * @param page 分页信息 32 | * @return 用户列表 33 | */ 34 | List findByRoleIdAndCondition(@Param("roleId") Long roleId, 35 | @Param("user") User user, Page page); 36 | 37 | /** 38 | * 根据条件查询 39 | * 40 | * @param user 用户 41 | * @param page 分页 42 | * @return 用户列表 43 | */ 44 | List findByCondition(@Param("user") User user, Page page); 45 | 46 | /** 47 | * 获得今日新增数量 48 | * 49 | * @return 50 | */ 51 | Integer getTodayCount(); 52 | 53 | /** 54 | * 获得用户文章数排名 55 | * 56 | * @param limit 查询数量 57 | * @return 58 | */ 59 | List getUserPostRanking(Integer limit); 60 | 61 | /** 62 | * 获得最新注册用户 63 | * 64 | * @param limit 65 | * @return 66 | */ 67 | List getLatestUser(Integer limit); 68 | 69 | /** 70 | * 获得热门用户 71 | * 72 | * @param limit 用户数量 73 | * @return 74 | */ 75 | List getHotUsers(Integer limit); 76 | 77 | /** 78 | * 搜索用户 79 | * 80 | * @param keywords 81 | * @return 82 | */ 83 | List searchUser(String keywords); 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/mapper/UserRoleRefMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.blog.entity.UserRoleRef; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author example 9 | */ 10 | @Mapper 11 | public interface UserRoleRefMapper extends BaseMapper { 12 | 13 | /** 14 | * 根据用户Id删除 15 | * 16 | * @param userId 用户Id 17 | * @return 影响行数 18 | */ 19 | Integer deleteByUserId(Long userId); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/BlackWordService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.common.base.BaseService; 4 | import com.example.blog.entity.BlackWord; 5 | 6 | /** 7 | * @author 言曌 8 | * @date 2020/4/4 10:46 上午 9 | */ 10 | public interface BlackWordService extends BaseService { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | 4 | import com.example.blog.common.base.BaseService; 5 | import com.example.blog.entity.Category; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | *
11 |  *     分类业务逻辑接口
12 |  * 
13 | * 14 | * @author : saysky 15 | * @date : 2017/11/30 16 | */ 17 | public interface CategoryService extends BaseService { 18 | 19 | /** 20 | * 查询所有分类目录,带count和根据level封装name 21 | * 22 | * @return 返回List集合 23 | */ 24 | List findByUserId(Long userId); 25 | 26 | /** 27 | * 根据文章Id获得分类列表 28 | * 29 | * @param postId 文章id 30 | * @return 分类列表 31 | */ 32 | Category findByPostId(Long postId); 33 | 34 | /** 35 | * 获得某个分类的所有文章数 36 | * 37 | * @param cateId 分类Id 38 | * @return 文章数 39 | */ 40 | Integer countPostByCateId(Long cateId); 41 | 42 | /** 43 | * 根据用户ID删除 44 | * 45 | * @param userId 46 | * @return 47 | */ 48 | Integer deleteByUserId(Long userId); 49 | 50 | /** 51 | * 将分类ID列表转成分类 52 | * 53 | * @param cateIds 54 | * @param userId 55 | * @return 56 | */ 57 | List cateIdsToCateList(List cateIds, Long userId); 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | 4 | import com.example.blog.common.base.BaseService; 5 | import com.example.blog.entity.Comment; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | *
11 |  *     回复业务逻辑接口
12 |  * 
13 | * 14 | * @author : saysky 15 | * @date : 2018/1/22 16 | */ 17 | public interface CommentService extends BaseService { 18 | 19 | /** 20 | * 根据用户Id删除回复 21 | * 22 | * @param userId 用户Id 23 | */ 24 | Integer deleteByUserId(Long userId); 25 | 26 | /** 27 | * 根据回复接受人Id删除回复 28 | * 29 | * @param acceptId 用户Id 30 | */ 31 | Integer deleteByAcceptUserId(Long acceptId); 32 | 33 | /** 34 | * 根据文章ID获得评论列表 35 | * @param postId 36 | * @return 37 | */ 38 | List findByPostId(Long postId); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/FriendService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.common.base.BaseService; 4 | import com.example.blog.entity.Friend; 5 | 6 | /** 7 | * @author 言曌 8 | * @date 2021/3/5 2:40 下午 9 | */ 10 | 11 | public interface FriendService extends BaseService { 12 | 13 | /** 14 | * 根据用户ID和被添加的ID查询 15 | * 16 | * @param userId 17 | * @param friendId 18 | * @return 19 | */ 20 | Friend findByUserIdAndFriendId(Long userId, Long friendId); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/LinkService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | 4 | import com.example.blog.common.base.BaseService; 5 | import com.example.blog.entity.Link; 6 | 7 | /** 8 | *
 9 |  *     友情链接业务逻辑接口
10 |  * 
11 | * 12 | * @author : saysky 13 | * @date : 2017/11/14 14 | */ 15 | public interface LinkService extends BaseService { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/MailService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | 4 | import javax.mail.MessagingException; 5 | 6 | /** 7 | *
 8 |  *     邮件发送业务逻辑接口
 9 |  * 
10 | */ 11 | public interface MailService { 12 | 13 | /** 14 | * 发送邮件 15 | * 16 | * @param to 接收者 17 | * @param title 标题 18 | * @param content 内容 19 | */ 20 | void sendMail(String to, String title, String content) throws MessagingException; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/PermissionService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.entity.Permission; 4 | import com.example.blog.common.base.BaseService; 5 | 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | /** 10 | * 权限逻辑接口 11 | */ 12 | public interface PermissionService extends BaseService { 13 | 14 | /** 15 | * 根据角色Id获得权限列表 16 | * 17 | * @param roleId 角色Id 18 | * @return 权限列表 19 | */ 20 | List listPermissionsByRoleId(Long roleId); 21 | 22 | /** 23 | * 获得某个用户的权限URL列表 24 | * 25 | * @param userId 26 | * @return 27 | */ 28 | Set findPermissionUrlsByUserId(Long userId); 29 | 30 | /** 31 | * 获得某个用户的用户ID和资源类型 32 | * 33 | * @param userId 34 | * @param resourceType 35 | * @return 36 | */ 37 | List findPermissionTreeByUserIdAndResourceType(Long userId, String resourceType); 38 | 39 | /** 40 | * 根据角色ID获得权限列表 41 | * @param roleId 42 | * @return 43 | */ 44 | List findPermissionByRoleId(Long roleId); 45 | 46 | /** 47 | * 获得所有权限,带有等级 48 | * @return 49 | */ 50 | List findPermissionListWithLevel(); 51 | 52 | /** 53 | * 统计子节点数量 54 | * @param id 55 | * @return 56 | */ 57 | Integer countChildPermission(Long id); 58 | 59 | /** 60 | * 根据URL获得权限 61 | * @param url 62 | * @return 63 | */ 64 | Permission findByUrl(String url); 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/PhotoCategoryService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.common.base.BaseService; 4 | import com.example.blog.entity.PhotoCategory; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author 言曌 10 | * @date 2021/3/2 5:40 下午 11 | */ 12 | public interface PhotoCategoryService extends BaseService { 13 | 14 | /** 15 | * 根据用户ID查询 16 | * 17 | * @param userId 18 | * @return 19 | */ 20 | List findByUserId(Long userId); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/PhotoService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.common.base.BaseService; 4 | import com.example.blog.entity.Photo; 5 | 6 | /** 7 | * @author 言曌 8 | * @date 2021/3/2 5:40 下午 9 | */ 10 | public interface PhotoService extends BaseService { 11 | 12 | /** 13 | * 根据分类ID查询照片数量 14 | * 15 | * @param categoryId 16 | * @return 17 | */ 18 | Integer countByCategoryId(Long categoryId); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/PostService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.example.blog.common.base.BaseService; 5 | import com.example.blog.dto.PostQueryCondition; 6 | import com.example.blog.entity.Post; 7 | 8 | /** 9 | *
10 |  *     记录/页面业务逻辑接口
11 |  * 
12 | */ 13 | public interface PostService extends BaseService { 14 | 15 | /** 16 | * 修改记录阅读量 17 | * 18 | * @param postId 记录Id 19 | * @return 记录访问量 20 | */ 21 | void updatePostView(Long postId); 22 | 23 | /** 24 | * 获取所有记录的阅读量 25 | * 26 | * @return Long 27 | */ 28 | Long getTotalPostViews(); 29 | 30 | /** 31 | * 更新记录回复数 32 | * 33 | * @param postId 记录Id 34 | */ 35 | void resetCommentSize(Long postId); 36 | 37 | /** 38 | * 删除用户的记录 39 | * 40 | * @param userId 用户Id 41 | */ 42 | void deleteByUserId(Long userId); 43 | 44 | /** 45 | * 根据条件获得列表 46 | * @param condition 47 | * @return 48 | */ 49 | Page findPostByCondition(PostQueryCondition condition, Page page); 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/RolePermissionRefService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.entity.RolePermissionRef; 4 | 5 | import java.util.List; 6 | 7 | 8 | public interface RolePermissionRefService { 9 | 10 | /** 11 | * 删除某个角色的所有关联 12 | * 13 | * @param roleId 角色Id 14 | */ 15 | void deleteRefByRoleId(Long roleId); 16 | 17 | /** 18 | * 添加角色和权限关联 19 | * 20 | * @param rolePermissionRef RolePermissionRef 21 | * @return UserRoleRef 22 | */ 23 | void saveByRolePermissionRef(RolePermissionRef rolePermissionRef); 24 | 25 | /** 26 | * 批量添加 27 | * 28 | * @param rolePermissionRefs 列表 29 | */ 30 | void batchSaveByRolePermissionRef(List rolePermissionRefs); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/RoleService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.entity.Role; 4 | import com.example.blog.common.base.BaseService; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 角色逻辑接口 10 | */ 11 | public interface RoleService extends BaseService { 12 | 13 | /** 14 | * 删除某个用户的所有关联 15 | * 16 | * @param userId 用户Id 17 | */ 18 | void deleteByUserId(Long userId); 19 | 20 | /** 21 | * 根据编号查询单个权限 22 | * 23 | * @param roleId roleId 24 | * @return Role 25 | */ 26 | Role findByRoleId(Long roleId); 27 | 28 | /** 29 | * 根据编号查询单个权限 30 | * 31 | * @param roleName roleName 32 | * @return Role 33 | */ 34 | Role findByRoleName(String roleName); 35 | 36 | /** 37 | * 根据用户Id获得角色 38 | * 39 | * @param userId 用户Id 40 | * @return 角色列表 41 | */ 42 | Role findByUserId(Long userId); 43 | 44 | /** 45 | * 统计这个角色的用户数 46 | * 47 | * @param roleId 角色Id 48 | */ 49 | Integer countUserByRoleId(Long roleId); 50 | 51 | /** 52 | * 查询某个用户最大的角色等级 53 | * @param userId 54 | * @return 55 | */ 56 | Integer findMaxLevelByUserId(Long userId); 57 | 58 | /** 59 | * 查询小于等于该等级的角色 60 | * @param level 61 | * @return 62 | */ 63 | List findByLessThanLevel(Integer level); 64 | 65 | /** 66 | * 获得用户注册默认角色 67 | * @return 68 | */ 69 | Role findDefaultRole(); 70 | 71 | /** 72 | * 获得用户注册默认角色 73 | * @return 74 | */ 75 | Role getMaxRoleByUserId(Long userId); 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/TagService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.common.base.BaseService; 4 | import com.example.blog.entity.Tag; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | *
10 |  *     标签业务逻辑接口
11 |  * 
12 | * 13 | */ 14 | public interface TagService extends BaseService { 15 | 16 | 17 | /** 18 | * 热门标签 19 | * 20 | * @return 标签列表 21 | */ 22 | List findHotTags(Integer limit); 23 | 24 | /** 25 | * 根据标签名称查询 26 | * 27 | * @param tagName tagName 28 | * @return Tag 29 | */ 30 | Tag findTagByTagName(String tagName); 31 | 32 | /** 33 | * 转换标签字符串为实体集合 34 | * 35 | * @param tagList tagList 36 | * @return List 37 | */ 38 | List strListToTagList(String tagList); 39 | 40 | /** 41 | * 标签列表转成字符串 42 | * @param tagList 43 | * @return 44 | */ 45 | String tagListToStr(List tagList); 46 | /** 47 | * 根据文章Id获得标签列表 48 | * 49 | * @param postId 文章id 50 | * @return 分类列表 51 | */ 52 | List findByPostId(Long postId); 53 | 54 | /** 55 | * 根据用户ID删除 56 | * @param userId 57 | * @return 58 | */ 59 | Integer deleteByUserId(Long userId); 60 | 61 | /** 62 | * 热门标签 63 | * @param keywords 64 | * @return 65 | */ 66 | List getHotTags(String keywords, Integer limit); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/UserRoleRefService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.example.blog.entity.UserRoleRef; 4 | import com.example.blog.common.base.BaseService; 5 | 6 | 7 | public interface UserRoleRefService extends BaseService { 8 | 9 | /** 10 | * 根据用户Id删除 11 | * 12 | * @param userId 用户Id 13 | */ 14 | void deleteByUserId(Long userId); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.example.blog.common.base.BaseService; 5 | import com.example.blog.entity.User; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 用户业务逻辑接口 11 | */ 12 | public interface UserService extends BaseService { 13 | 14 | /** 15 | * 根据用户名获得用户 16 | * 17 | * @param userName 用户名 18 | * @return 用户 19 | */ 20 | User findByUserName(String userName); 21 | 22 | 23 | /** 24 | * 根据邮箱查找用户 25 | * 26 | * @param userEmail 邮箱 27 | * @return User 28 | */ 29 | User findByEmail(String userEmail); 30 | 31 | /** 32 | * 更新密码 33 | * 34 | * @param userId 用户Id 35 | * @param password 密码 36 | */ 37 | void updatePassword(Long userId, String password); 38 | 39 | /** 40 | * 分页获取所有用户 41 | * 42 | * @param roleName 角色名称 43 | * @param condition 查询条件 44 | * @param page 分页信息 45 | * @return 用户列表 46 | */ 47 | Page findByRoleAndCondition(String roleName, User condition, Page page); 48 | 49 | 50 | /** 51 | * 修改禁用状态 52 | * 53 | * @param enable enable 54 | */ 55 | void updateUserLoginEnable(User user, String enable); 56 | 57 | /** 58 | * 增加登录错误次数 59 | * 60 | * @return 登录错误次数 61 | */ 62 | Integer updateUserLoginError(User user); 63 | 64 | /** 65 | * 修改用户的登录状态为正常 66 | * 67 | * @return User 68 | */ 69 | User updateUserLoginNormal(User user); 70 | 71 | 72 | /** 73 | * 获得热门用户 74 | * 75 | * @param limit 用户数量 76 | * @return 77 | */ 78 | List getHotUsers(Integer limit); 79 | 80 | /** 81 | * 搜索用户 82 | * 83 | * @param keywords 84 | * @return 85 | */ 86 | List searchUser(String keywords); 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/BlackWordServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.BlackWord; 7 | import com.example.blog.mapper.BlackWordMapper; 8 | import com.example.blog.service.BlackWordService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | /** 13 | * @author 言曌 14 | * @date 2020/4/4 10:47 上午 15 | */ 16 | @Service 17 | public class BlackWordServiceImpl implements BlackWordService { 18 | 19 | @Autowired 20 | private BlackWordMapper blackWordMapper; 21 | 22 | @Override 23 | public BaseMapper getRepository() { 24 | return blackWordMapper; 25 | } 26 | 27 | @Override 28 | public QueryWrapper getQueryWrapper(BlackWord blackWord) { 29 | //对指定字段查询 30 | QueryWrapper queryWrapper = new QueryWrapper<>(); 31 | if (blackWord != null) { 32 | if (StrUtil.isNotBlank(blackWord.getContent())) { 33 | queryWrapper.eq("content", blackWord.getContent()); 34 | } 35 | } 36 | return queryWrapper; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/CategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Category; 7 | import com.example.blog.mapper.CategoryMapper; 8 | import com.example.blog.mapper.PostCategoryRefMapper; 9 | import com.example.blog.service.CategoryService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.stream.Collectors; 16 | 17 | /** 18 | *
 19 |  *     分类业务逻辑实现类
 20 |  * 
21 | * 22 | */ 23 | @Service 24 | public class CategoryServiceImpl implements CategoryService { 25 | 26 | @Autowired 27 | private CategoryMapper categoryMapper; 28 | 29 | @Autowired 30 | private PostCategoryRefMapper postCategoryRefMapper; 31 | 32 | @Override 33 | public BaseMapper getRepository() { 34 | return categoryMapper; 35 | } 36 | 37 | @Override 38 | public QueryWrapper getQueryWrapper(Category category) { 39 | //对指定字段查询 40 | QueryWrapper queryWrapper = new QueryWrapper<>(); 41 | if (category != null) { 42 | if (StrUtil.isNotBlank(category.getCateName())) { 43 | queryWrapper.like("cate_name", category.getCateName()); 44 | } 45 | } 46 | return queryWrapper; 47 | } 48 | 49 | @Override 50 | public Category insert(Category category) { 51 | categoryMapper.insert(category); 52 | return category; 53 | } 54 | 55 | @Override 56 | public Category update(Category category) { 57 | categoryMapper.updateById(category); 58 | return category; 59 | } 60 | 61 | @Override 62 | public void delete(Long id) { 63 | //1.删除分类和文章的关联 64 | postCategoryRefMapper.deleteByCateId(id); 65 | //2.删除分类 66 | categoryMapper.deleteById(id); 67 | } 68 | 69 | 70 | @Override 71 | public List findByUserId(Long userId) { 72 | QueryWrapper queryWrapper = new QueryWrapper(); 73 | queryWrapper.eq("user_id", userId); 74 | return categoryMapper.selectList(queryWrapper); 75 | } 76 | 77 | 78 | 79 | @Override 80 | public Category findByPostId(Long postId) { 81 | Category category = categoryMapper.findByPostId(postId); 82 | return category; 83 | } 84 | 85 | @Override 86 | public Integer countPostByCateId(Long cateId) { 87 | return postCategoryRefMapper.countPostByCateId(cateId); 88 | } 89 | 90 | @Override 91 | public Category insertOrUpdate(Category entity) { 92 | if (entity.getId() == null) { 93 | insert(entity); 94 | } else { 95 | update(entity); 96 | } 97 | return entity; 98 | } 99 | 100 | @Override 101 | public Integer deleteByUserId(Long userId) { 102 | return categoryMapper.deleteByUserId(userId); 103 | } 104 | 105 | @Override 106 | public List cateIdsToCateList(List cateIds, Long userId) { 107 | List categoryList = this.findByUserId(userId); 108 | List allCateIds = categoryList.stream().map(Category::getId).collect(Collectors.toList()); 109 | List result = new ArrayList<>(); 110 | for(Long id : cateIds) { 111 | if(allCateIds.contains(id)) { 112 | Category category = new Category(); 113 | category.setId(id); 114 | result.add(category); 115 | } 116 | } 117 | return result; 118 | } 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/CommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Comment; 7 | import com.example.blog.mapper.CommentMapper; 8 | import com.example.blog.service.CommentService; 9 | import com.example.blog.service.PostService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | *
 17 |  *     回复业务逻辑实现类
 18 |  * 
19 | * 20 | * @author : saysky 21 | * @date : 2018/1/22 22 | */ 23 | @Service 24 | public class CommentServiceImpl implements CommentService { 25 | 26 | @Autowired 27 | private CommentMapper commentMapper; 28 | 29 | @Autowired 30 | private PostService postService; 31 | 32 | 33 | @Override 34 | public BaseMapper getRepository() { 35 | return commentMapper; 36 | } 37 | 38 | @Override 39 | public QueryWrapper getQueryWrapper(Comment comment) { 40 | //对指定字段查询 41 | QueryWrapper queryWrapper = new QueryWrapper<>(); 42 | if (comment != null) { 43 | if (comment.getUserId() != null && comment.getUserId() != -1) { 44 | queryWrapper.eq("user_id", comment.getUserId()); 45 | } 46 | if (comment.getAcceptUserId() != null && comment.getAcceptUserId() != -1) { 47 | queryWrapper.eq("accept_user_id", comment.getAcceptUserId()); 48 | } 49 | if (StrUtil.isNotBlank(comment.getCommentContent())) { 50 | queryWrapper.like("comment_content", comment.getCommentContent()); 51 | } 52 | if (comment.getPostId() != null && comment.getPostId() != -1) { 53 | queryWrapper.eq("post_id", comment.getPostId()); 54 | } 55 | } 56 | return queryWrapper; 57 | } 58 | 59 | @Override 60 | public Integer deleteByUserId(Long userId) { 61 | return commentMapper.deleteByUserId(userId); 62 | } 63 | 64 | @Override 65 | public Integer deleteByAcceptUserId(Long acceptId) { 66 | return commentMapper.deleteByAcceptUserId(acceptId); 67 | } 68 | 69 | @Override 70 | public List findByPostId(Long postId) { 71 | return commentMapper.findByPostId(postId); 72 | } 73 | 74 | 75 | @Override 76 | public Comment insert(Comment comment) { 77 | commentMapper.insert(comment); 78 | //修改文章回复数 79 | postService.resetCommentSize(comment.getPostId()); 80 | return comment; 81 | } 82 | 83 | @Override 84 | public Comment update(Comment comment) { 85 | commentMapper.updateById(comment); 86 | //修改文章回复数 87 | postService.resetCommentSize(comment.getPostId()); 88 | return comment; 89 | } 90 | 91 | @Override 92 | public void delete(Long commentId) { 93 | Comment comment = this.get(commentId); 94 | if (comment != null) { 95 | //1.删除回复 96 | commentMapper.deleteById(commentId); 97 | //2.修改文章的回复数量 98 | postService.resetCommentSize(comment.getPostId()); 99 | } 100 | } 101 | 102 | @Override 103 | public Comment insertOrUpdate(Comment comment) { 104 | if(comment.getId() == null) { 105 | insert(comment); 106 | } else { 107 | update(comment); 108 | } 109 | return comment; 110 | } 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/FriendServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.example.blog.entity.Friend; 6 | import com.example.blog.mapper.FriendMapper; 7 | import com.example.blog.service.FriendService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author 言曌 15 | * @date 2021/3/5 2:41 下午 16 | */ 17 | @Service 18 | public class FriendServiceImpl implements FriendService { 19 | 20 | @Autowired 21 | private FriendMapper friendMapper; 22 | 23 | @Override 24 | public BaseMapper getRepository() { 25 | return friendMapper; 26 | } 27 | 28 | @Override 29 | public QueryWrapper getQueryWrapper(Friend friend) { 30 | //对指定字段查询 31 | QueryWrapper queryWrapper = new QueryWrapper<>(); 32 | if (friend != null) { 33 | if (friend.getUserId() != null && friend.getUserId() != -1) { 34 | queryWrapper.eq("user_id", friend.getUserId()); 35 | } 36 | if (friend.getFriendId() != null && friend.getFriendId() != -1) { 37 | queryWrapper.eq("friend_id", friend.getFriendId()); 38 | } 39 | } 40 | return queryWrapper; 41 | } 42 | 43 | @Override 44 | public Friend findByUserIdAndFriendId(Long userId, Long friendId) { 45 | QueryWrapper queryWrapper = new QueryWrapper<>(); 46 | queryWrapper.eq("user_id", userId); 47 | queryWrapper.eq("friend_id", friendId); 48 | List friends = friendMapper.selectList(queryWrapper); 49 | if (friends != null && friends.size() > 0) { 50 | return friends.get(0); 51 | } 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/LinkServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Link; 7 | import com.example.blog.mapper.LinkMapper; 8 | import com.example.blog.service.LinkService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | *
16 |  *     友情链接业务逻辑实现类
17 |  * 
18 | * 19 | */ 20 | @Service 21 | public class LinkServiceImpl implements LinkService { 22 | 23 | 24 | @Autowired 25 | private LinkMapper linkMapper; 26 | 27 | @Override 28 | public BaseMapper getRepository() { 29 | return linkMapper; 30 | } 31 | 32 | @Override 33 | public QueryWrapper getQueryWrapper(Link link) { 34 | //对指定字段查询 35 | QueryWrapper queryWrapper = new QueryWrapper<>(); 36 | if (link != null) { 37 | if (StrUtil.isNotBlank(link.getLinkName())) { 38 | queryWrapper.like("link_name", link.getLinkName()); 39 | } 40 | if (StrUtil.isNotBlank(link.getLinkUrl())) { 41 | queryWrapper.like("link_url", link.getLinkUrl()); 42 | } 43 | } 44 | return queryWrapper; 45 | } 46 | 47 | @Override 48 | public Link insertOrUpdate(Link entity) { 49 | if (entity.getId() == null) { 50 | insert(entity); 51 | } else { 52 | update(entity); 53 | } 54 | return entity; 55 | } 56 | 57 | @Override 58 | public void delete(Long id) { 59 | linkMapper.deleteById(id); 60 | } 61 | 62 | @Override 63 | public List findAll() { 64 | List linkList = linkMapper.selectList(null); 65 | return linkList; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/MailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.example.blog.service.MailService; 4 | import com.example.blog.util.SensUtils; 5 | import io.github.biezhi.ome.OhMyEmail; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.mail.MessagingException; 10 | 11 | /** 12 | *
13 |  *     邮件发送业务逻辑实现类
14 |  * 
15 | * 16 | * @author : saysky 17 | * @date : 2018/1/23 18 | */ 19 | @Service 20 | public class MailServiceImpl implements MailService { 21 | 22 | @Value("${mail.smtp.host}") 23 | private String host; 24 | 25 | @Value("${mail.smtp.username}") 26 | private String username; 27 | 28 | @Value("${mail.smtp.password}") 29 | private String password; 30 | 31 | @Value("${mail.from.name}") 32 | private String fromName; 33 | 34 | /** 35 | * 发送邮件 36 | * 37 | * @param to to 接收者 38 | * @param title subject 标题 39 | * @param content content 内容 40 | */ 41 | @Override 42 | public void sendMail(String to, String title, String content) throws MessagingException { 43 | //配置邮件服务器 44 | SensUtils.configMail(host, username, password); 45 | OhMyEmail.subject(title) 46 | .from(fromName) 47 | .to(to) 48 | .text(content) 49 | .send(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/PermissionServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Permission; 7 | import com.example.blog.mapper.PermissionMapper; 8 | import com.example.blog.mapper.RolePermissionRefMapper; 9 | import com.example.blog.service.PermissionService; 10 | import com.example.blog.util.PermissionUtil; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import java.util.List; 16 | import java.util.Set; 17 | import java.util.stream.Collectors; 18 | 19 | /** 20 | * 角色业务逻辑实现类 21 | */ 22 | @Service 23 | public class PermissionServiceImpl implements PermissionService { 24 | 25 | @Autowired 26 | private PermissionMapper permissionMapper; 27 | 28 | @Autowired 29 | private RolePermissionRefMapper rolePermissionRefMapper; 30 | 31 | 32 | @Override 33 | public List listPermissionsByRoleId(Long roleId) { 34 | return permissionMapper.findByRoleId(roleId); 35 | } 36 | 37 | @Override 38 | public Set findPermissionUrlsByUserId(Long userId) { 39 | List permissions = permissionMapper.findPermissionByUserId(userId); 40 | Set urls = permissions.stream().map(p -> p.getUrl()).collect(Collectors.toSet()); 41 | return urls; 42 | } 43 | 44 | @Override 45 | public List findPermissionTreeByUserIdAndResourceType(Long userId, String resourceType) { 46 | List permissions = permissionMapper.findPermissionByUserIdAndResourceType(userId, resourceType); 47 | return PermissionUtil.getPermissionTree(permissions); 48 | } 49 | 50 | @Override 51 | public List findPermissionByRoleId(Long roleId) { 52 | return permissionMapper.findPermissionByRoleId(roleId); 53 | } 54 | 55 | 56 | @Override 57 | public BaseMapper getRepository() { 58 | return permissionMapper; 59 | } 60 | 61 | @Override 62 | public QueryWrapper getQueryWrapper(Permission permission) { 63 | //对指定字段查询 64 | QueryWrapper queryWrapper = new QueryWrapper<>(); 65 | if (permission != null) { 66 | if (StrUtil.isNotBlank(permission.getResourceType())) { 67 | queryWrapper.eq("resource_type", permission.getResourceType()); 68 | } 69 | if (StrUtil.isNotBlank(permission.getResourceType())) { 70 | queryWrapper.eq("resource_type", permission.getResourceType()); 71 | } 72 | if (StrUtil.isNotBlank(permission.getUrl())) { 73 | queryWrapper.eq("url", permission.getUrl()); 74 | } 75 | if (StrUtil.isNotBlank(permission.getName())) { 76 | queryWrapper.eq("name", permission.getName()); 77 | } 78 | } 79 | return queryWrapper; 80 | } 81 | 82 | @Override 83 | public Permission insertOrUpdate(Permission entity) { 84 | if (entity.getId() == null) { 85 | insert(entity); 86 | } else { 87 | update(entity); 88 | } 89 | return entity; 90 | } 91 | 92 | @Override 93 | @Transactional(rollbackFor = Exception.class) 94 | public void delete(Long id) { 95 | permissionMapper.deleteById(id); 96 | rolePermissionRefMapper.deleteByPermissionId(id); 97 | } 98 | 99 | @Override 100 | public List findPermissionListWithLevel() { 101 | List permissionList = permissionMapper.selectList(null); 102 | permissionList = PermissionUtil.getPermissionList(permissionList); 103 | 104 | // 加空格以展示等级 105 | for (Permission permission : permissionList) { 106 | for (int i = 1; i < permission.getLevel(); i++) { 107 | permission.setName("    "+permission.getName()); 108 | } 109 | } 110 | return permissionList; 111 | 112 | } 113 | 114 | @Override 115 | public Integer countChildPermission(Long id) { 116 | return permissionMapper.countChildPermission(id); 117 | } 118 | 119 | @Override 120 | public Permission findByUrl(String url) { 121 | return permissionMapper.findByUrl(url); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/PhotoCategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.example.blog.entity.PhotoCategory; 6 | import com.example.blog.mapper.PhotoCategoryMapper; 7 | import com.example.blog.service.PhotoCategoryService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author 言曌 15 | * @date 2021/3/2 5:42 下午 16 | */ 17 | 18 | @Service 19 | public class PhotoCategoryServiceImpl implements PhotoCategoryService { 20 | 21 | @Autowired 22 | private PhotoCategoryMapper photoCategoryMapper; 23 | 24 | @Override 25 | public BaseMapper getRepository() { 26 | return photoCategoryMapper; 27 | } 28 | 29 | @Override 30 | public QueryWrapper getQueryWrapper(PhotoCategory photoCategory) { 31 | QueryWrapper queryWrapper = new QueryWrapper(); 32 | if (photoCategory.getUserId() != null) { 33 | queryWrapper.eq("user_id", photoCategory.getUserId()); 34 | } 35 | return queryWrapper; 36 | } 37 | 38 | @Override 39 | public List findByUserId(Long userId) { 40 | QueryWrapper queryWrapper = new QueryWrapper(); 41 | queryWrapper.eq("user_id", userId); 42 | queryWrapper.orderByDesc("cate_sort"); 43 | return photoCategoryMapper.selectList(queryWrapper); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/PhotoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.example.blog.entity.Photo; 6 | import com.example.blog.mapper.PhotoMapper; 7 | import com.example.blog.service.PhotoService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * @author 言曌 13 | * @date 2021/3/2 5:42 下午 14 | */ 15 | 16 | @Service 17 | public class PhotoServiceImpl implements PhotoService { 18 | 19 | @Autowired 20 | private PhotoMapper photoMapper; 21 | 22 | @Override 23 | public BaseMapper getRepository() { 24 | return photoMapper; 25 | } 26 | 27 | @Override 28 | public QueryWrapper getQueryWrapper(Photo photo) { 29 | QueryWrapper queryWrapper = new QueryWrapper(); 30 | if (photo.getUserId() != null) { 31 | queryWrapper.eq("user_id", photo.getUserId()); 32 | } 33 | if (photo.getCategoryId() != null) { 34 | queryWrapper.eq("category_id", photo.getCategoryId()); 35 | } 36 | return queryWrapper; 37 | } 38 | 39 | @Override 40 | public Integer countByCategoryId(Long categoryId) { 41 | QueryWrapper queryWrapper = new QueryWrapper(); 42 | queryWrapper.eq("category_id", categoryId); 43 | return photoMapper.selectCount(queryWrapper); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/PostServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.example.blog.dto.PostQueryCondition; 8 | import com.example.blog.entity.*; 9 | import com.example.blog.mapper.*; 10 | import com.example.blog.service.*; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.scheduling.annotation.Async; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | 19 | 20 | /** 21 | *
 22 |  *     文章业务逻辑实现类
 23 |  * 
24 | */ 25 | @Service 26 | @Slf4j 27 | public class PostServiceImpl implements PostService { 28 | 29 | 30 | @Autowired 31 | private PostMapper postMapper; 32 | 33 | @Autowired 34 | private PostCategoryRefMapper postCategoryRefMapper; 35 | 36 | @Autowired 37 | private PostTagRefMapper postTagRefMapper; 38 | 39 | @Autowired 40 | private TagMapper tagMapper; 41 | 42 | @Override 43 | @Async 44 | public void updatePostView(Long postId) { 45 | postMapper.incrPostViews(postId); 46 | } 47 | 48 | 49 | @Override 50 | public Long getTotalPostViews() { 51 | return postMapper.getPostViewsSum(); 52 | } 53 | 54 | @Override 55 | public void resetCommentSize(Long postId) { 56 | postMapper.resetCommentSize(postId); 57 | } 58 | 59 | 60 | @Override 61 | @Transactional(rollbackFor = Exception.class) 62 | public void deleteByUserId(Long userId) { 63 | List postIds = postMapper.selectIdByUserId(userId); 64 | if (postIds != null && postIds.size() > 0) { 65 | postTagRefMapper.deleteByPostIds(postIds); 66 | postCategoryRefMapper.deleteByPostIds(postIds); 67 | } 68 | postMapper.deleteByUserId(userId); 69 | } 70 | 71 | @Override 72 | public Page findPostByCondition(PostQueryCondition condition, Page page) { 73 | List postList = postMapper.findPostByCondition(condition, page); 74 | for (Post post : postList) { 75 | List tagList = tagMapper.findByPostId(post.getId()); 76 | post.setTagList(tagList); 77 | } 78 | return page.setRecords(postList); 79 | } 80 | 81 | @Override 82 | public BaseMapper getRepository() { 83 | return postMapper; 84 | } 85 | 86 | @Override 87 | public Post insert(Post post) { 88 | post.setPostViews(0L); 89 | post.setCommentSize(0L); 90 | post.setPostLikes(0L); 91 | postMapper.insert(post); 92 | //添加记录分类关系 93 | if (post.getCategory() != null) { 94 | postCategoryRefMapper.insert(new PostCategoryRef(post.getId(), post.getCategory().getId())); 95 | } 96 | //添加记录标签关系 97 | if (post.getTagList() != null) { 98 | for (int i = 0; i < post.getTagList().size(); i++) { 99 | postTagRefMapper.insert(new PostTagRef(post.getId(), post.getTagList().get(i).getId())); 100 | } 101 | } 102 | return post; 103 | } 104 | 105 | @Override 106 | public Post update(Post post) { 107 | postMapper.updateById(post); 108 | if (post.getCategory() != null) { 109 | //添加分类和记录关联 110 | postCategoryRefMapper.deleteByPostId(post.getId()); 111 | //删除分类和记录关联 112 | PostCategoryRef postCategoryRef = new PostCategoryRef(post.getId(), post.getCategory().getId()); 113 | postCategoryRefMapper.insert(postCategoryRef); 114 | } 115 | if (post.getTagList() != null && post.getTagList().size() != 0) { 116 | //删除标签和记录关联 117 | postTagRefMapper.deleteByPostId(post.getId()); 118 | //添加标签和记录关联 119 | for (int i = 0; i < post.getTagList().size(); i++) { 120 | PostTagRef postTagRef = new PostTagRef(post.getId(), post.getTagList().get(i).getId()); 121 | postTagRefMapper.insert(postTagRef); 122 | } 123 | } 124 | return post; 125 | } 126 | 127 | @Override 128 | @Transactional(rollbackFor = Exception.class) 129 | public void delete(Long postId) { 130 | Post post = this.get(postId); 131 | if (post != null) { 132 | postTagRefMapper.deleteByPostId(postId); 133 | postCategoryRefMapper.deleteByPostId(postId); 134 | postMapper.deleteById(post.getId()); 135 | } 136 | } 137 | 138 | @Override 139 | public QueryWrapper getQueryWrapper(Post post) { 140 | //对指定字段查询 141 | QueryWrapper queryWrapper = new QueryWrapper<>(); 142 | if (post != null) { 143 | if (StrUtil.isNotBlank(post.getPostTitle())) { 144 | queryWrapper.like("post_title", post.getPostTitle()); 145 | } 146 | if (StrUtil.isNotBlank(post.getPostContent())) { 147 | queryWrapper.like("post_content", post.getPostContent()); 148 | } 149 | if (post.getUserId() != null && post.getUserId() != -1) { 150 | queryWrapper.eq("user_id", post.getUserId()); 151 | } 152 | if (post.getPostStatus() != null && post.getPostStatus() != -1) { 153 | queryWrapper.eq("post_status", post.getPostStatus()); 154 | } 155 | if (StrUtil.isNotBlank(post.getPostType() )) { 156 | queryWrapper.eq("post_type", post.getPostType()); 157 | } 158 | } 159 | return queryWrapper; 160 | } 161 | 162 | @Override 163 | public Post insertOrUpdate(Post post) { 164 | if (post.getId() == null) { 165 | insert(post); 166 | } else { 167 | update(post); 168 | } 169 | return post; 170 | } 171 | 172 | } 173 | 174 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/RolePermissionRefServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.example.blog.entity.RolePermissionRef; 4 | import com.example.blog.mapper.RolePermissionRefMapper; 5 | import com.example.blog.service.RolePermissionRefService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class RolePermissionRefServiceImpl implements RolePermissionRefService { 13 | 14 | @Autowired 15 | private RolePermissionRefMapper rolePermissionRefMapper; 16 | 17 | @Override 18 | public void deleteRefByRoleId(Long roleId) { 19 | rolePermissionRefMapper.deleteByRoleId(roleId); 20 | } 21 | 22 | @Override 23 | public void saveByRolePermissionRef(RolePermissionRef rolePermissionRef) { 24 | rolePermissionRefMapper.insert(rolePermissionRef); 25 | } 26 | 27 | @Override 28 | public void batchSaveByRolePermissionRef(List rolePermissionRefs) { 29 | rolePermissionRefMapper.batchInsert(rolePermissionRefs); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/RoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Permission; 7 | import com.example.blog.entity.Role; 8 | import com.example.blog.entity.RolePermissionRef; 9 | import com.example.blog.mapper.RoleMapper; 10 | import com.example.blog.service.RolePermissionRefService; 11 | import com.example.blog.service.RoleService; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * 角色业务逻辑实现类 21 | */ 22 | @Service 23 | public class RoleServiceImpl implements RoleService { 24 | 25 | @Autowired 26 | private RoleMapper roleMapper; 27 | 28 | @Autowired 29 | private RolePermissionRefService rolePermissionRefService; 30 | 31 | @Override 32 | public BaseMapper getRepository() { 33 | return roleMapper; 34 | } 35 | 36 | @Override 37 | public QueryWrapper getQueryWrapper(Role role) { 38 | //对指定字段查询 39 | QueryWrapper queryWrapper = new QueryWrapper<>(); 40 | if (role != null) { 41 | if (StrUtil.isNotBlank(role.getRole())) { 42 | queryWrapper.eq("role", role.getRole()); 43 | } 44 | if (StrUtil.isNotBlank(role.getDescription())) { 45 | queryWrapper.eq("description", role.getDescription()); 46 | } 47 | } 48 | return queryWrapper; 49 | } 50 | 51 | @Override 52 | public void deleteByUserId(Long userId) { 53 | roleMapper.deleteByUserId(userId); 54 | } 55 | 56 | @Override 57 | public Role findByRoleId(Long roleId) { 58 | return roleMapper.selectById(roleId); 59 | } 60 | 61 | @Override 62 | public Role findByRoleName(String roleName) { 63 | QueryWrapper queryWrapper = new QueryWrapper(); 64 | queryWrapper.eq("role", roleName); 65 | return roleMapper.selectOne(queryWrapper); 66 | } 67 | 68 | @Override 69 | public Role findByUserId(Long userId) { 70 | return roleMapper.findByUserId(userId); 71 | } 72 | 73 | @Override 74 | public Integer countUserByRoleId(Long roleId) { 75 | return roleMapper.countUserByRoleId(roleId); 76 | } 77 | 78 | @Override 79 | public Integer findMaxLevelByUserId(Long userId) { 80 | return roleMapper.findMaxLevelByUserId(userId); 81 | } 82 | 83 | @Override 84 | public List findByLessThanLevel(Integer level) { 85 | return roleMapper.findByLessThanLevel(level); 86 | } 87 | 88 | @Override 89 | public Role findDefaultRole() { 90 | return roleMapper.findDefaultRole(); 91 | } 92 | 93 | @Override 94 | public Role getMaxRoleByUserId(Long userId) { 95 | return null; 96 | } 97 | 98 | @Override 99 | @Transactional(rollbackFor = Exception.class) 100 | public Role insert(Role role) { 101 | roleMapper.insert(role); 102 | if (role.getPermissions() != null && role.getPermissions().size() > 0) { 103 | List rolePermissionRefs = new ArrayList<>(role.getPermissions().size()); 104 | for (Permission permission : role.getPermissions()) { 105 | rolePermissionRefs.add(new RolePermissionRef(role.getId(), permission.getId())); 106 | } 107 | rolePermissionRefService.batchSaveByRolePermissionRef(rolePermissionRefs); 108 | } 109 | return role; 110 | } 111 | 112 | @Override 113 | @Transactional(rollbackFor = Exception.class) 114 | public Role update(Role role) { 115 | roleMapper.updateById(role); 116 | if (role.getPermissions() != null && role.getPermissions().size() > 0) { 117 | // 删除关联 118 | rolePermissionRefService.deleteRefByRoleId(role.getId()); 119 | // 添加关联 120 | List rolePermissionRefs = new ArrayList<>(role.getPermissions().size()); 121 | for (Permission permission : role.getPermissions()) { 122 | rolePermissionRefs.add(new RolePermissionRef(role.getId(), permission.getId())); 123 | } 124 | rolePermissionRefService.batchSaveByRolePermissionRef(rolePermissionRefs); 125 | } 126 | return role; 127 | } 128 | 129 | @Override 130 | public Role insertOrUpdate(Role entity) { 131 | if (entity.getId() == null) { 132 | insert(entity); 133 | } else { 134 | update(entity); 135 | } 136 | return entity; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/TagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.example.blog.entity.Tag; 7 | import com.example.blog.mapper.PostTagRefMapper; 8 | import com.example.blog.mapper.TagMapper; 9 | import com.example.blog.service.TagService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Objects; 17 | 18 | /** 19 | *
 20 |  *     标签业务逻辑实现类
 21 |  * 
22 | * 23 | * @author : saysky 24 | * @date : 2018/1/12 25 | */ 26 | @Service 27 | public class TagServiceImpl implements TagService { 28 | 29 | @Autowired 30 | private TagMapper tagMapper; 31 | 32 | @Autowired 33 | private PostTagRefMapper postTagRefMapper; 34 | 35 | @Override 36 | public BaseMapper getRepository() { 37 | return tagMapper; 38 | } 39 | 40 | 41 | @Override 42 | public QueryWrapper getQueryWrapper(Tag tag) { 43 | //对指定字段查询 44 | QueryWrapper queryWrapper = new QueryWrapper<>(); 45 | if (tag != null) { 46 | if (StrUtil.isNotBlank(tag.getTagName())) { 47 | queryWrapper.eq("tag_name", tag.getTagName()); 48 | } 49 | } 50 | return queryWrapper; 51 | } 52 | 53 | @Override 54 | public List findHotTags(Integer limit) { 55 | return tagMapper.findAllWithCount(limit); 56 | } 57 | 58 | @Override 59 | public Tag findTagByTagName(String tagName) { 60 | QueryWrapper queryWrapper = new QueryWrapper(); 61 | queryWrapper.eq("tag_name", tagName); 62 | return tagMapper.selectOne(queryWrapper); 63 | } 64 | 65 | 66 | @Override 67 | public List strListToTagList(String tagList) { 68 | String[] tags = tagList.split(","); 69 | List tagsList = new ArrayList<>(); 70 | for (String tag : tags) { 71 | Tag t = findTagByTagName(tag); 72 | Tag nt = null; 73 | if (null != t) { 74 | tagsList.add(t); 75 | } else { 76 | nt = new Tag(); 77 | nt.setTagName(tag); 78 | tagsList.add(insert(nt)); 79 | } 80 | } 81 | return tagsList; 82 | } 83 | 84 | @Override 85 | public String tagListToStr(List tagList) { 86 | StringBuilder sb = new StringBuilder(); 87 | for (int i = 0; i < tagList.size(); i++) { 88 | sb.append(tagList.get(i).getTagName()).append(","); 89 | } 90 | String result = sb.toString(); 91 | if (result.endsWith(",")) { 92 | return result.substring(0, result.length() - 1); 93 | } 94 | return result; 95 | } 96 | 97 | 98 | @Override 99 | public List findByPostId(Long postId) { 100 | List tagList = tagMapper.findByPostId(postId); 101 | return tagList; 102 | } 103 | 104 | @Override 105 | public Tag insert(Tag entity) { 106 | Tag isExist = findTagByTagName(entity.getTagName()); 107 | if (isExist != null) { 108 | return isExist; 109 | } 110 | tagMapper.insert(entity); 111 | return entity; 112 | } 113 | 114 | @Override 115 | public Tag update(Tag entity) { 116 | Tag isExist = findTagByTagName(entity.getTagName()); 117 | if (isExist != null && !Objects.equals(isExist.getId(), entity.getId())) { 118 | return isExist; 119 | } 120 | tagMapper.updateById(entity); 121 | return entity; 122 | } 123 | 124 | @Override 125 | @Transactional(rollbackFor = Exception.class) 126 | public void delete(Long id) { 127 | Tag tag = this.get(id); 128 | if (tag != null) { 129 | //1.删除标签和文章的关联 130 | postTagRefMapper.deleteByTagId(id); 131 | //2.删除标签 132 | tagMapper.deleteById(id); 133 | } 134 | } 135 | 136 | 137 | @Override 138 | public Tag insertOrUpdate(Tag entity) { 139 | if (entity.getId() == null) { 140 | insert(entity); 141 | } else { 142 | update(entity); 143 | } 144 | return entity; 145 | } 146 | 147 | @Override 148 | public Integer deleteByUserId(Long userId) { 149 | return tagMapper.deleteByUserId(userId); 150 | } 151 | 152 | @Override 153 | public List getHotTags(String keywords, Integer limit) { 154 | return tagMapper.getHotTags(keywords, limit); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/UserRoleRefServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.example.blog.entity.UserRoleRef; 6 | import com.example.blog.mapper.UserRoleRefMapper; 7 | import com.example.blog.service.UserRoleRefService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | 12 | @Service 13 | public class UserRoleRefServiceImpl implements UserRoleRefService { 14 | 15 | @Autowired 16 | private UserRoleRefMapper roleRefMapper; 17 | 18 | 19 | @Override 20 | public void deleteByUserId(Long userId) { 21 | roleRefMapper.deleteByUserId(userId); 22 | } 23 | 24 | @Override 25 | public BaseMapper getRepository() { 26 | return roleRefMapper; 27 | } 28 | 29 | @Override 30 | public QueryWrapper getQueryWrapper(UserRoleRef userRoleRef) { 31 | //对指定字段查询 32 | QueryWrapper queryWrapper = new QueryWrapper<>(); 33 | if (userRoleRef != null) { 34 | if (userRoleRef.getUserId() != null) { 35 | queryWrapper.eq("user_id", userRoleRef.getUserId()); 36 | } 37 | if (userRoleRef.getRoleId() != null) { 38 | queryWrapper.eq("role_id", userRoleRef.getRoleId()); 39 | } 40 | } 41 | return queryWrapper; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.service.impl; 2 | 3 | import cn.hutool.core.lang.Validator; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.example.blog.exception.MyBusinessException; 9 | import com.example.blog.common.constant.CommonConstant; 10 | import com.example.blog.entity.Role; 11 | import com.example.blog.mapper.UserMapper; 12 | import com.example.blog.entity.User; 13 | import com.example.blog.enums.TrueFalseEnum; 14 | import com.example.blog.service.CommentService; 15 | import com.example.blog.service.PostService; 16 | import com.example.blog.service.RoleService; 17 | import com.example.blog.service.UserService; 18 | import com.example.blog.util.Md5Util; 19 | import org.apache.commons.lang3.RandomUtils; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.stereotype.Service; 22 | import org.springframework.transaction.annotation.Transactional; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Date; 26 | import java.util.List; 27 | import java.util.Objects; 28 | 29 | /** 30 | * 用户业务逻辑实现类 31 | */ 32 | @Service 33 | public class UserServiceImpl implements UserService { 34 | 35 | @Autowired 36 | private UserMapper userMapper; 37 | 38 | @Autowired 39 | private RoleService roleService; 40 | 41 | @Autowired 42 | private CommentService commentService; 43 | 44 | @Autowired 45 | private PostService postService; 46 | 47 | @Override 48 | public User findByUserName(String userName) { 49 | QueryWrapper queryWrapper = new QueryWrapper(); 50 | queryWrapper.eq("user_name", userName); 51 | return userMapper.selectOne(queryWrapper); 52 | } 53 | 54 | @Override 55 | public User findByEmail(String userEmail) { 56 | QueryWrapper queryWrapper = new QueryWrapper(); 57 | queryWrapper.eq("user_email", userEmail); 58 | return userMapper.selectOne(queryWrapper); 59 | } 60 | 61 | @Override 62 | public void updatePassword(Long userId, String password) { 63 | User user = new User(); 64 | user.setId(userId); 65 | user.setUserPass(Md5Util.toMd5(password, CommonConstant.PASSWORD_SALT, 10)); 66 | userMapper.updateById(user); 67 | } 68 | 69 | @Override 70 | public Page findByRoleAndCondition(String roleName, User condition, Page page) { 71 | List users = new ArrayList<>(); 72 | if (Objects.equals(roleName, CommonConstant.NONE)) { 73 | users = userMapper.findByCondition(condition, page); 74 | } else { 75 | Role role = roleService.findByRoleName(roleName); 76 | if (role != null) { 77 | users = userMapper.findByRoleIdAndCondition(role.getId(), condition, page); 78 | } 79 | } 80 | return page.setRecords(users); 81 | } 82 | 83 | /** 84 | * 修改禁用状态 85 | * 86 | * @param enable enable 87 | */ 88 | @Override 89 | public void updateUserLoginEnable(User user, String enable) { 90 | //如果是修改为正常, 重置错误次数 91 | if (Objects.equals(TrueFalseEnum.TRUE.getValue(), enable)) { 92 | user.setLoginError(0); 93 | } 94 | user.setLoginEnable(enable); 95 | user.setLoginLast(new Date()); 96 | userMapper.updateById(user); 97 | } 98 | 99 | 100 | /** 101 | * 增加登录错误次数 102 | * 103 | * @return 登录错误次数 104 | */ 105 | @Override 106 | public Integer updateUserLoginError(User user) { 107 | user.setLoginError((user.getLoginError() == null ? 0 : user.getLoginError()) + 1); 108 | userMapper.updateById(user); 109 | return user.getLoginError(); 110 | } 111 | 112 | /** 113 | * 修改用户的状态为正常 114 | * 115 | * @return User 116 | */ 117 | @Override 118 | public User updateUserLoginNormal(User user) { 119 | user.setLoginEnable(TrueFalseEnum.TRUE.getValue()); 120 | user.setLoginError(0); 121 | user.setLoginLast(new Date()); 122 | userMapper.updateById(user); 123 | return user; 124 | } 125 | 126 | @Override 127 | public List getHotUsers(Integer limit) { 128 | return userMapper.getHotUsers(limit); 129 | } 130 | 131 | @Override 132 | public List searchUser(String keywords) { 133 | return userMapper.searchUser(keywords); 134 | } 135 | 136 | @Override 137 | public BaseMapper getRepository() { 138 | return userMapper; 139 | } 140 | 141 | @Override 142 | public QueryWrapper getQueryWrapper(User user) { 143 | //对指定字段查询 144 | QueryWrapper queryWrapper = new QueryWrapper<>(); 145 | if (user != null) { 146 | if (StrUtil.isNotBlank(user.getUserName())) { 147 | queryWrapper.eq("user_name", user.getUserName()); 148 | } 149 | if (StrUtil.isNotBlank(user.getUserEmail())) { 150 | queryWrapper.eq("user_email", user.getUserEmail()); 151 | } 152 | } 153 | return queryWrapper; 154 | } 155 | 156 | @Override 157 | public User insert(User user) { 158 | //1.验证表单数据是否合法 159 | basicUserCheck(user); 160 | //2.验证用户名和邮箱是否存在 161 | checkUserNameAndEmail(user); 162 | userMapper.insert(user); 163 | return user; 164 | } 165 | 166 | @Override 167 | public User update(User user) { 168 | //1.验证表单数据是否合法 169 | basicUserCheck(user); 170 | //2.验证用户名和邮箱是否存在 171 | checkUserNameAndEmail(user); 172 | userMapper.updateById(user); 173 | return user; 174 | } 175 | 176 | 177 | private void basicUserCheck(User user) { 178 | if (user.getUserName() == null || user.getUserEmail() == null || user.getUserDisplayName() == null) { 179 | throw new MyBusinessException("请输入完整信息!"); 180 | } 181 | String userName = user.getUserName(); 182 | userName = userName.trim().replaceAll(" ", "-"); 183 | if (userName.length() < 4 || userName.length() > 20) { 184 | throw new MyBusinessException("用户名长度为4-20位!"); 185 | } 186 | if (!Validator.isEmail(user.getUserEmail())) { 187 | throw new MyBusinessException("电子邮箱格式不合法!"); 188 | } 189 | if (user.getUserDisplayName().length() < 1 || user.getUserDisplayName().length() > 20) { 190 | throw new MyBusinessException("昵称为2-20位"); 191 | } 192 | } 193 | 194 | private void checkUserNameAndEmail(User user) { 195 | //验证用户名和邮箱是否存在 196 | if (user.getUserName() != null) { 197 | User nameCheck = findByUserName(user.getUserName()); 198 | Boolean isExist = (user.getId() == null && nameCheck != null) || 199 | (user.getId() != null && nameCheck != null && !Objects.equals(nameCheck.getId(), user.getId())); 200 | if (isExist) { 201 | throw new MyBusinessException("用户名已经存在"); 202 | } 203 | } 204 | if (user.getUserEmail() != null) { 205 | User emailCheck = findByEmail(user.getUserEmail()); 206 | Boolean isExist = (user.getId() == null && emailCheck != null) || 207 | (user.getId() != null && emailCheck != null && !Objects.equals(emailCheck.getId(), user.getId())); 208 | if (isExist) { 209 | throw new MyBusinessException("电子邮箱已经存在"); 210 | } 211 | } 212 | } 213 | 214 | @Override 215 | @Transactional(rollbackFor = Exception.class) 216 | public void delete(Long userId) { 217 | //删除用户 218 | User user = get(userId); 219 | if (user != null) { 220 | //1.修改用户状态为已删除 221 | userMapper.deleteById(userId); 222 | //2.修改用户和角色关联 223 | roleService.deleteByUserId(userId); 224 | //3.删除其他 225 | postService.deleteByUserId(userId); 226 | commentService.deleteByUserId(userId); 227 | } 228 | } 229 | 230 | @Override 231 | public User insertOrUpdate(User user) { 232 | if (user.getId() == null) { 233 | user.setUserAvatar("/static/images/avatar/" + RandomUtils.nextInt(1, 41) + ".jpeg"); 234 | insert(user); 235 | } else { 236 | update(user); 237 | } 238 | return user; 239 | } 240 | 241 | @Override 242 | public User get(Long id) { 243 | User user = userMapper.selectById(id); 244 | return user; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/vo/PageVo.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | 8 | /** 9 | * @author example 10 | */ 11 | @Data 12 | public class PageVo implements Serializable { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | /** 17 | * 页号 18 | */ 19 | private long page = 1; 20 | 21 | /** 22 | * 页大小 23 | */ 24 | private long size = 10; 25 | 26 | /** 27 | * 排序字段 28 | */ 29 | private String sort = "create_time"; 30 | 31 | /** 32 | * 排序方式 asc/desc 33 | */ 34 | private String order = "desc"; 35 | 36 | /** 37 | * 当前页码 38 | */ 39 | private long current; 40 | 41 | /** 42 | * 总数 43 | */ 44 | private long total; 45 | 46 | /** 47 | * 页数 48 | */ 49 | private long pages; 50 | 51 | 52 | public PageVo() { 53 | } 54 | 55 | public PageVo(int page, int size) { 56 | this.page = page; 57 | this.size = size; 58 | } 59 | 60 | public PageVo(int page, int size, String sort, String order) { 61 | this.page = page; 62 | this.size = size; 63 | this.sort = sort; 64 | this.order = order; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/vo/SearchVo.java: -------------------------------------------------------------------------------- 1 | package com.example.blog.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author example 9 | */ 10 | @Data 11 | public class SearchVo implements Serializable { 12 | 13 | /** 14 | * 起始日期 15 | */ 16 | private String startDate; 17 | 18 | /** 19 | * 结束日期 20 | */ 21 | private String endDate; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/blog/需要完整代码联系博主.txt: -------------------------------------------------------------------------------- 1 | 需要完整代码联系博主 2 | 847064370 3 | -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | forward-headers-strategy: true 4 | undertow: 5 | io-threads: 2 6 | worker-threads: 36 7 | buffer-size: 1024 8 | directBuffers: true 9 | servlet: 10 | session: 11 | timeout: 86400 12 | 13 | spring: 14 | transaction: 15 | rollback-on-commit-failure: true 16 | datasource: 17 | type: com.alibaba.druid.pool.DruidDataSource 18 | #MySql配置 19 | driver-class-name: com.mysql.cj.jdbc.Driver 20 | url: jdbc:mysql://127.0.0.1:3306/chuyun_blog?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowMultiQueries=true 21 | username: root 22 | password: 123456 23 | thymeleaf: 24 | mode: HTML5 25 | cache: false 26 | prefix: classpath:/templates/ 27 | encoding: UTF-8 28 | suffix: .html 29 | check-template-location: false 30 | servlet: 31 | multipart: 32 | max-file-size: 2MB 33 | max-request-size: 20MB 34 | devtools: 35 | restart: 36 | enabled: true 37 | additional-paths: src/main/java 38 | 39 | mybatis-plus: 40 | mapper-locations: classpath*:/mapper/**Mapper.xml 41 | #实体扫描,多个package用逗号或者分号分隔 42 | typeAliasesPackage: com.example.sens.entity 43 | global-config: 44 | #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; 45 | id-type: 0 46 | #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" 47 | field-strategy: 2 48 | #驼峰下划线转换 49 | db-column-underline: true 50 | #刷新mapper 调试神器 51 | refresh-mapper: true 52 | #逻辑删除配置(下面3个配置) 53 | logic-delete-value: 1 54 | logic-not-delete-value: 0 55 | configuration: 56 | map-underscore-to-camel-case: true 57 | cache-enabled: true 58 | 59 | logging: 60 | file: ./logs/log.log 61 | level: 62 | org: 63 | springframework: 64 | boot: 65 | autoconfigure: error 66 | # web: 67 | # trace 68 | 69 | 70 | shiro: 71 | userNativeSessionManager: true 72 | 73 | # 邮箱账号 74 | mail: 75 | smtp: 76 | host: smtp.qq.com 77 | username: 847064370@qq.com 78 | password: vtvhcjsacnuubdaj 79 | from: 80 | name: Easy Java 81 | 82 | application: 83 | version: 1.0.2 84 | staticCdnUrl: 85 | -------------------------------------------------------------------------------- /src/main/resources/mapper/CategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DELETE 7 | FROM 8 | category 9 | WHERE 10 | user_id = #{value} 11 | 12 | 13 | 30 | 31 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/resources/mapper/CommentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 45 | 46 | 47 | DELETE 48 | FROM 49 | comment 50 | WHERE 51 | user_id = #{value} 52 | AND del_flag = 0 53 | 54 | 55 | 56 | DELETE 57 | FROM 58 | comment 59 | WHERE 60 | accept_user_id = #{value} 61 | AND del_flag = 0 62 | 63 | 64 | 83 | 84 | 85 | 94 | 95 | 109 | 110 | 111 | 130 | -------------------------------------------------------------------------------- /src/main/resources/mapper/LinkMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PermissionMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 24 | 25 | 53 | 54 | 55 | 84 | 85 | 105 | 106 | 122 | 123 | 132 | 133 | 142 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PostCategoryRefMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DELETE 8 | FROM 9 | post_category_ref 10 | WHERE 11 | post_id = #{value} 12 | AND del_flag = 0 13 | 14 | 15 | 16 | DELETE 17 | FROM 18 | post_category_ref 19 | WHERE 20 | post_id IN 21 | 22 | #{item} 23 | 24 | AND del_flag = 0 25 | 26 | 27 | 28 | DELETE 29 | FROM 30 | post_category_ref 31 | WHERE 32 | cate_id = #{value} 33 | AND del_flag = 0 34 | 35 | 36 | 45 | 46 | 55 | 56 | 65 | 66 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PostMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0 6 | 1 7 | 2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 46 | 47 | 48 | 49 | UPDATE post t 50 | SET t.comment_size = ( SELECT COUNT( * ) FROM comment c WHERE c.post_id = #{value} AND c.del_flag = 0 ) 51 | WHERE 52 | t.id = #{value} 53 | AND del_flag = 0 54 | 55 | 56 | 57 | UPDATE post 58 | SET post_likes = post_likes + 1 59 | WHERE 60 | id = #{value} 61 | AND del_flag = 0 62 | 63 | 64 | 65 | UPDATE post 66 | SET post_views = post_views + 1 67 | WHERE 68 | id = #{value} 69 | AND del_flag = 0 70 | 71 | 72 | 73 | 74 | DELETE 75 | FROM 76 | post 77 | WHERE 78 | user_id = #{value} 79 | AND del_flag = 0 80 | 81 | 82 | 83 | 92 | 93 | 94 | 150 | 151 | 154 | 155 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PostTagRefMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | DELETE 11 | FROM 12 | post_tag_ref 13 | WHERE 14 | post_id = #{value} 15 | AND del_flag = 0 16 | 17 | 18 | 19 | DELETE 20 | FROM 21 | post_tag_ref 22 | WHERE 23 | post_id IN 24 | 25 | #{item} 26 | 27 | AND del_flag = 0 28 | 29 | 30 | 31 | DELETE 32 | FROM 33 | post_tag_ref 34 | WHERE 35 | tag_id = #{value} 36 | AND del_flag = 0 37 | 38 | 39 | 48 | 49 | 58 | -------------------------------------------------------------------------------- /src/main/resources/mapper/RoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 24 | 25 | 26 | DELETE 27 | FROM 28 | user_role_ref 29 | WHERE 30 | user_id = #{value} 31 | AND del_flag = 0 32 | 33 | 34 | 46 | 47 | 66 | 67 | 80 | 81 | 91 | 92 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/main/resources/mapper/RolePermissionRefMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DELETE 7 | FROM 8 | role_permission_ref 9 | WHERE 10 | role_id = #{value} 11 | AND del_flag = 0 12 | 13 | 14 | 15 | DELETE 16 | FROM 17 | role_permission_ref 18 | WHERE 19 | permission_id = #{value} 20 | AND del_flag = 0 21 | 22 | 23 | 24 | INSERT INTO 25 | role_permission_ref 26 | ( role_id, permission_id ) 27 | VALUES 28 | 29 | ( 30 | #{item.roleId}, #{item.permissionId} 31 | ) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/resources/mapper/TagMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DELETE 7 | FROM 8 | tag 9 | WHERE 10 | user_id = #{value} 11 | 12 | 13 | 27 | 28 | 47 | 48 | 49 | 61 | 62 | 77 | 78 | -------------------------------------------------------------------------------- /src/main/resources/mapper/TaskMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0 6 | 1 7 | 2 8 | 9 | 34 | 35 | 72 | 73 | 74 | 107 | 108 | 109 | 118 | 119 | 141 | 142 | 157 | 158 | 172 | 173 | 186 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserRoleRefMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | DELETE 11 | FROM `user_role_ref` 12 | WHERE user_id = #{value} 13 | AND del_flag = 0 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/前端完整代码联系博主.txt: -------------------------------------------------------------------------------- 1 | 前端完整代码联系博主 2 | --------------------------------------------------------------------------------