# blog **Repository Path**: aghp/blog ## Basic Information - **Project Name**: blog - **Description**: 博客管理系统 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: https://blog.csdn.net/qq_66345100/article/details/130876158?spm=1001.2014.3001.5502 - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2023-04-25 - **Last Updated**: 2024-11-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目介绍 ## 前言 > - 知识汲取者的博客:[知识汲取者的博客-blog](https://blog.csdn.net/qq_66345100/article/details/130876158?spm=1001.2014.3001.5502) > > - 后端代码仓库:[blog: 博客系统后端代码仓库 (gitee.com)](https://gitee.com/cultivate_your_sky/blog) > - 前端代码仓库: > - 前台:[blog-fe: 博客系统前端代码仓库(前台展示) (gitee.com)](https://gitee.com/cultivate_your_sky/blog-fe) > - 后台:[blog-be: 博客系统前端代码仓库(后台管理) (gitee.com)](https://gitee.com/cultivate_your_sky/blog-be) > > 说明:本项目属于二次开发,我之前是跟着三更老师开发的,后面也就是现在我自己花了一周的时间复盘,重新再次开发一遍。所以在此致谢三更老师💖💖💖三更老师并不是培训机构的,而是利用工作业余时间出的教程,这里也为三更老师做一波宣传 > > 三更老师B站地址:https://space.bilibili.com/663528522?spm_id_from=333.337.0.0 > > 这个项目也是继瑞吉外卖后的一个比较完整的项目了,从项目的 开发 - 部署 - 上线,这段时间(前前后后花了大约两周时间)学到了很多东西,比如SpringSecurity+JWT实现登录流程,项目开发的流程、如何进行模块划分,项目如何上线(这里老师没教,纯自学),数据库表如何设计才更加优雅,三跟老师交给我的,更多的并不是如何使用某某技术,而是为什么要使用这个技术(做到了真正的“授人以鱼,不如授人以渔”),这个技术好在哪些地方。 ## 项目演示 ### 前台演示 - 在线体验:http://知识汲取者.top/ - 项目前台截图: - 首页: ![image-20230508202436400](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613780.png) - 登录页面: ![image-20230508202344010](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613781.png) - 注册页面: ![image-20230508202406808](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613782.png) - 文章简介: ![image-20230508202456937](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613783.png) - 文章详情: ![image-20230508202525266](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613784.png) - 友链展示: ![image-20230508202608053](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613785.png) - 评论: ![image-20230508202621860](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613786.png) - 赞赏: ![image-20230508202638850](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613787.png) - 个人中心: ![image-20230508202650836](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613788.png) - 安全中心: ![image-20230508202703804](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613789.png) ### 后台演示 - 在线体验:暂无 - 项目后台截图: - 首页: ![image-20230508203144437](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613790.png) - 登录: ![image-20230508202324056](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613791.png) - 写博文: ![image-20230509160029803](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613792.png) - 系统管理: - 用户管理: ![image-20230509160041384](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613793.png) - 角色管理: ![image-20230509160049139](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613794.png) - 菜单管理: ![image-20230509160058047](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613795.png) - 内容管理: - 文章管理: ![image-20230509160150259](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613796.png) - 分类管理: ![image-20230509160158700](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613797.png) - 友链管理: ![image-20230509160206916](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613798.png) - 标签管理: ![image-20230509160218331](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613799.png) ## 组织结构 ### 后端组织结构 ```shell blog ├─.idea │ ├─dataSources │ │ └─f902d677-27d9-4dcf-bcf6-2750320cbe2c │ │ └─storage_v2 │ │ └─_src_ │ │ └─schema │ ├─inspectionProfiles │ ├─mybatisx │ └─sonarlint ├─blog-be │ ├─src │ │ ├─main │ │ │ ├─java │ │ │ │ └─com │ │ │ │ └─hhxy │ │ │ │ ├─config │ │ │ │ └─controller │ │ │ └─resources │ │ └─test │ │ └─java │ │ └─com │ │ └─hhxy │ │ ├─mapper │ │ └─service │ └─target │ ├─classes │ │ └─com │ │ └─hhxy │ │ ├─config │ │ └─controller │ ├─generated-sources │ │ └─annotations │ ├─generated-test-sources │ │ └─test-annotations │ ├─maven-archiver │ ├─maven-status │ │ └─maven-compiler-plugin │ │ ├─compile │ │ │ └─default-compile │ │ └─testCompile │ │ └─default-testCompile │ └─test-classes │ └─com │ └─hhxy │ ├─mapper │ └─service ├─blog-fe │ ├─src │ │ ├─main │ │ │ ├─java │ │ │ │ └─com │ │ │ │ └─hhxy │ │ │ │ ├─config │ │ │ │ ├─controller │ │ │ │ ├─job │ │ │ │ └─runner │ │ │ └─resources │ │ └─test │ │ └─java │ │ └─com │ │ └─hhxy │ │ └─utils │ └─target │ ├─classes │ │ └─com │ │ └─hhxy │ │ ├─config │ │ ├─controller │ │ ├─job │ │ └─runner │ ├─generated-sources │ │ └─annotations │ ├─generated-test-sources │ │ └─test-annotations │ ├─maven-archiver │ ├─maven-status │ │ └─maven-compiler-plugin │ │ ├─compile │ │ │ └─default-compile │ │ └─testCompile │ │ └─default-testCompile │ └─test-classes │ └─com │ └─hhxy │ └─utils └─blog-framework ├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─hhxy │ │ │ ├─annotation │ │ │ ├─aspect │ │ │ ├─config │ │ │ ├─constants │ │ │ ├─controller │ │ │ ├─filter │ │ │ ├─handler │ │ │ │ ├─exception │ │ │ │ ├─mybatisplus │ │ │ │ └─security │ │ │ ├─mapper │ │ │ ├─model │ │ │ │ ├─dto │ │ │ │ ├─entity │ │ │ │ └─vo │ │ │ ├─service │ │ │ │ └─impl │ │ │ └─utils │ │ │ ├─convert │ │ │ ├─redis │ │ │ └─response │ │ └─resources │ │ ├─mapper │ │ ├─sql │ │ └─static │ └─test │ └─java └─target ├─classes │ ├─com │ │ └─hhxy │ │ ├─annotation │ │ ├─aspect │ │ ├─config │ │ ├─constants │ │ ├─controller │ │ ├─filter │ │ ├─handler │ │ │ ├─exception │ │ │ ├─mybatisplus │ │ │ └─security │ │ ├─mapper │ │ ├─model │ │ │ ├─dto │ │ │ ├─entity │ │ │ └─vo │ │ ├─service │ │ │ └─impl │ │ └─utils │ │ ├─convert │ │ ├─redis │ │ └─response │ ├─mapper │ ├─META-INF │ └─sql ├─generated-sources │ └─annotations ├─maven-archiver └─maven-status └─maven-compiler-plugin ├─compile │ └─default-compile └─testCompile └─default-testCompile ``` ### 前端组织结构 - **前台项目** ``` blog-admin: ├─api ├─assets │ └─css ├─components ├─pages ├─router ├─store └─utils ``` - **后台项目** ``` blog-vue: ├─public ├─src │ ├─api │ │ ├─content │ │ └─system │ ├─assets │ │ ├─404_images │ │ ├─icons │ │ │ └─svg │ │ └─images │ ├─components │ │ ├─Breadcrumb │ │ ├─Hamburger │ │ ├─ParentView │ │ └─SvgIcon │ ├─directive │ │ └─permission │ ├─layout │ │ ├─components │ │ │ ├─InnerLink │ │ │ └─Sidebar │ │ └─mixin │ ├─plugins │ ├─router │ ├─store │ │ └─modules │ ├─styles │ ├─utils │ └─views │ ├─content │ │ ├─article │ │ │ └─write │ │ ├─category │ │ ├─link │ │ └─tag │ ├─dashboard │ ├─login │ ├─nested │ │ └─menu1 │ │ └─menu1-2 │ └─system │ ├─menu │ ├─role │ └─user ├─static └─tests └─unit ├─components └─utils ``` ## 技术选型 ### 前端技术 | 技术 | 说明 | 文档 | | ----------------- | ---------------- | ------------------------------------------------------------ | | `HTML` | 网页结构 | https://developer.mozilla.org/zh-CN/docs/Web/HTML | | `CSS` | 网页样式 | https://developer.mozilla.org/zh-CN/docs/Learn/CSS | | `Vue2.5.2` | 前端框架 | [https://vuejs.org/](https://gitee.com/link?target=https%3A%2F%2Fvuejs.org%2F) | | `NodeJS16.15.0` | 前端依赖的环境 | https://nodejs.org/en | | `Vue-router3.0.1` | 路由框架 | [https://router.vuejs.org/](https://gitee.com/link?target=https%3A%2F%2Frouter.vuejs.org%2F) | | `Vuex3.0.1` | 全局状态管理框架 | [https://vuex.vuejs.org/](https://gitee.com/link?target=https%3A%2F%2Fvuex.vuejs.org%2F) | | `Element1.4.12` | 前端UI框架 | [https://element.eleme.io](https://gitee.com/link?target=https%3A%2F%2Felement.eleme.io) | | `Axios0.17.0` | 前端HTTP框架 | [https://github.com/axios/axios](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Faxios%2Faxios) | | `Js-cookie2.2.0` | cookie管理工具 | [https://github.com/js-cookie/js-cookie](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Fjs-cookie%2Fjs-cookie) | ### 后端技术 | 技术 | 说明 | 文档 | | ------------------ | ------------------- | ------------------------------------------------------------ | | `JDK1.8` | Java8 | https://www.java.com/zh-CN/ | | `SpringBoot2.5.0` | Web应用开发框架 | [https://spring.io/projects/spring-boot](https://gitee.com/link?target=https%3A%2F%2Fspring.io%2Fprojects%2Fspring-boot) | | `SpringSecurity` | 认证和授权框架 | [https://spring.io/projects/spring-security](https://gitee.com/link?target=https%3A%2F%2Fspring.io%2Fprojects%2Fspring-security) | | `MyBatisPlus3.4.3` | ORM框架 | [http://www.mybatis.org/mybatis-3/zh/index.html](https://gitee.com/link?target=http%3A%2F%2Fwww.mybatis.org%2Fmybatis-3%2Fzh%2Findex.html) | | `MyBatisGenerator` | 数据层代码生成器 | [http://www.mybatis.org/generator/index.html](https://gitee.com/link?target=http%3A%2F%2Fwww.mybatis.org%2Fgenerator%2Findex.html) | | `Redis6.2.6` | 缓存数据 | [https://redis.io/](https://gitee.com/link?target=https%3A%2F%2Fredis.io%2F) | | `MySQL8.0.27` | 持久化存储数据 | https://www.mysql.com | | `Druid1.2.15` | 数据库连接池 | [https://github.com/alibaba/druid](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Falibaba%2Fdruid) | | `OSS` | 对象存储 | [https://github.com/aliyun/aliyun-oss-java-sdk](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Faliyun%2Faliyun-oss-java-sdk) | | `Lombok1.8.24` | Java语言增强库 | [https://github.com/rzwitserloot/lombok](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Frzwitserloot%2Flombok) | | `PageHelper` | MyBatis物理分页插件 | [http://git.oschina.net/free/Mybatis_PageHelper](https://gitee.com/link?target=http%3A%2F%2Fgit.oschina.net%2Ffree%2FMybatis_PageHelper) | | `Swagger-UI2.0.2` | API文档生成工具 | [https://github.com/swagger-api/swagger-ui](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Fswagger-api%2Fswagger-ui) | | `Knife4j3.0.3` | API文档生成工具 | https://doc.xiaominfo.com/ | | `Validation-api` | 参数校验 | https://beanvalidation.org/ | | `FastJson1.2.23` | 序列化反序列化 | https://github.com/alibaba/fastjson/ | | `Jwt0.9.0` | JWT登录支持 | http://jboot.com.cn/docs/jwt.html | | `EasyExcel3.0.5` | 导入导出Excel | https://easyexcel.opensource.alibaba.com | ### 架构图 #### 系统架构图 ![image-20230508171801282](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613800.png) #### 业务架构图 ![image-20230508174627779](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613801.png) ## 模块介绍 > 项目整体采用三层架构的形式进行开发,在此基础上,还进行了模块的划分,让项目整体结构显得更加清晰明了,从而大大提高代码的复用性,系统的可维护性 ### 前端模块 - **前台模块** ![image-20230508194038339](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613802.png) - **后台模块** ![image-20230509160709565](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613803.png) ### 后端模块 ![image-20230509160653287](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613804.png) - **公共模块** ![image-20230509160553786](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613805.png) - **公共模块存哪些东西**? > 主要放置公共的代码,比如:通用的Controller、通用的方法类、以及数据模型对象(Model、Dto、Entity、VO),同时存放将前台模块和后台模块的Service、Mapper层的代码。并且还设置有一个公共的配置文件。 - **为什么要单独配置一个公共模块**? 1. 提高代码的复用性 2. 提高代码的可维护性 …… - **前台模块** ![image-20230509160610022](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613806.png) - **前台模块的作用**:主要用于处理项目博客前台的请求,DDL操作较少、DQL操作较多 - **后台模块** ![image-20230509160623360](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613807.png) - **后台模块的作用**:主要用于处理项目博客后台的请求,DDL和DQL操作都较多 ## 环境搭建 > 手把手教你如何搭建项目环境,并成功运行起来 ### 开发工具 | 工具 | 说明 | | ----------------------- | -------------------------- | | InntelliJ IDEA 2022.2.1 | Java编译器 | | VSCode 2022 | 前端编译器 | | Navicat Premium 12 | 可视化操作数据库 | | Maven 3.6.1 | 用于构建和管理Java项目 | | Git | 版本控制 | | Postman | 接口测试 | | VMware | 用于部署Redis | | FinalShell | Linux终端,远程来连接Linux | | RESP | 可视化操作Redis | | ProcessOn | 流程图绘制工具 | | Snipaste | 屏幕截图工具 | | Typora | Markdown编辑器 | ### 开发环境 - **前端**:使用VueCLI3+Vue2 ```js "dependencies": { "axios": "^0.17.0", "element-ui": "^1.4.12", "js-cookie": "2.2.0", "mavon-editor": "^2.10.4", "vue": "^2.5.2", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "devDependencies": { "@vue/cli-plugin-babel": "4.4.4", "@vue/cli-plugin-eslint": "4.4.4", "@vue/cli-plugin-unit-jest": "4.4.4", "@vue/cli-service": "4.4.4", "@vue/test-utils": "1.0.0-beta.29", "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-loader": "^7.1.1", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", "copy-webpack-plugin": "^4.0.1", "css-loader": "^0.28.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "less": "^2.7.2", "less-loader": "^4.0.5", "html-webpack-plugin": "^2.30.1", "node-notifier": "^5.1.2", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^11.0.0", "postcss-loader": "^2.0.8", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" } ``` - **后端**:SpringBoot2.5.0+JDK1.8 ```xml 4.0.0 com.hhxy blog pom 1.0-SNAPSHOT blog-framework blog-be blog-fe 8 8 UTF-8 1.8 3.1 2.5.0 1.18.24 1.2.15 1.2.33 0.9.0 3.4.3 3.10.2 [7.7.0, 7.7.99] 3.0.5 3.0.3 org.springframework.boot spring-boot-dependencies ${springboot.version} pom import org.projectlombok lombok ${lombok-version} com.alibaba druid-spring-boot-starter ${druid-version} com.alibaba fastjson ${fastjson.version} io.jsonwebtoken jjwt ${jwt.version} com.baomidou mybatis-plus-boot-starter ${mybatisplus.version} com.aliyun.oss aliyun-sdk-oss ${aliyun.sdk.oss} com.qiniu qiniu-java-sdk ${qiniuyun.sdk.version} com.alibaba easyexcel ${easyexcel.version} com.github.xiaoymin knife4j-spring-boot-starter ${knife4j-version} org.apache.maven.plugins maven-compiler-plugin ${maven.plugin.version} ${java.version} ${java.version} ${project.build.sourceEncoding} ``` ### 项目运行 > **温馨提示**: > > - 后端的blog-be模块对应前端的blog-admin模块,后端的blog-fe模块对应前端的blog-vue模块,需要先启动后端模块再启动前端模块,才能够正常访问页面 > - 后端模块运行之前,一定要将项目配置文件`application-common.yml`(位于blog-framework下的resource中)中的MySQL和Redis的账号、密码、主机改成你自己的,SQL文件也位于改目录下,直接使用Navicate运行改目录下的`blog.sql`即可 > - 后端数据库中的密码已通过`PasswordEncoding`采用`MD5`进行了加密,无法直接查看。我设置的初识账号密码是 `admin` `123qwe`,如果想要修改密码,直接可以通过测试类`EncryptionPasswordTest`(双击Shift搜索该测试类)进行加密,然后将加密后的密码复制到数据库,即可修改初识密码 > - 由于本项目没有使用本地上传功能,我使用的七牛云图床,所以如果想要上传图片需要修改一下配置,在`application-common.yml`将`upload`设置为`false`(true-使用七牛云图床,false-使用本地存储) - **前端** - **Step1**:进入项目根目录,在文件路径中输入`cmd` ![image-20230508195348305](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613808.png) - **Step2**:执行`npm i`(或者是 `npm install`,都一样),下载项目所需依赖(前提是先要有node环境,这里不过多介绍node的安装了,不懂的可以自行百度🤭) ![image-20230508195615086](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613809.png) - **Step3**:执行`npm run dev `,启动项目 ![image-20230508201042088](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613810.png) ==注意==:要想成功访问项目,需要先启动后端 - **后端**: - **Step1**:使用IDEA打开项目,刷新Maven,等待依赖加载 ![image-20230508200909130](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613811.png) PS:依赖加载慢,可以配置Maven镜像,这里也不多做解释了,不会的可以自行[百度](https://blog.csdn.net/qq_66345100/article/details/126537091) - **Step2**:开启虚拟机,然后启动Redis,关闭防火墙 ![image-20230508200219372](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613812.png) PS:关于Redis的安装部署,这里也不多做解释了,不会的可以参考这篇文章 [Redis基础篇](https://blog.csdn.net/qq_66345100/article/details/130566275?spm=1001.2014.3001.5502) - **Step3**:右击启动类,然后运行(后者在服务中添加SpringBoot程序,也可以启动) ![image-20230508201016311](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613813.png) ![image-20230508201743985](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613814.png) ## 未完待续 我还想要完善的一些功能: - 点赞功能,包括文章、评论点赞功能(Redis实现) - 文章收藏功能 - 用户关注功能(Redis实现) - 共同关注功能(并查集实现) - 对页面进行美化(加入一些有意思的动画效果,比如主题切换、看板娘) - 对于登录功能 - 添加忘记密码和记住我两个功能 - 接入QQ或者微信的扫码登录接口,实现扫码登录 - 对于注册功能,添加验证码校验,提高系统的安全性,防止恶意注册 - 对于后台管理首页展示区,缺乏动态数据查询功能 ![image-20230511114044059](https://gitee.com/aghp/typora-img/raw/master/blog/202307101613815.png) …… ## 结语 >   本项目历时一周开发完成。本次开发,采用分模块开发,由我设计接口并将接口分发给组员,通过Gitee版本控制工具,最终同理合作完成本项目。其中印象最深的是:对通用代码的抽取(比如查询字段是否存在,删除已有关联关系),SpringSecurity+JWT完成登录功能时拦截器的编写,这两块卡了一段时间,最终在组员的商议下共同合力解决。 > >   本项目在我看来,难点应该是对于权限的控制(SpringSecurity的使用),很多时候稍不注意就控制失败,抛出各种异常,其次就是前端,前端各种组件的设计,也显得有点力不从心,但好在在组员的通力合作下,最终完成了这个博客系统……