首页 / 资讯中心 / 文章详情

SpringBoot+Vue知识管理系统:从数据库设计到部署避坑全解析

SpringBoot+Vue知识管理系统:从数据库设计到部署避坑全解析 ★ FEATURED ARTICLE
每年毕设季市面上最不缺的就是XX管理系统这类题目而知识管理系统又是其中辨识度最高的一种。它不像商城秒杀系统那样堆砌高并发概念也不像企业官网那样停留在一堆静态页面它正好踩在需求可讲清、功能可演示、技术可深挖这条线上用户登录注册、权限控制、知识的分类与发布、全文检索、评论收藏、数据统计基本把 Java Web 方向的常见考点一网打尽。哪怕你拿到的是一套完整源码如果只知道mvn spring-boot:run和npm run dev能跑起来答辩时被问一句JWT 存在哪、过期了怎么办就会露馅。这篇文章我就以这套 SpringBootVue 的知识管理系统平台为例把技术选型、SQL 脚本、接口设计、前后端联调、部署避坑全部拆开讲。这套源码的完整链路是SpringBoot 提供 RESTful 接口MyBatis-Plus 操作 MySQLRedis 扛住验证码和热点数据JWT 做无状态登录前端用 Vue 全家桶构建管理后台和知识展示页Axios 统一请求Vue Router 管理页面跳转两者通过一套接口文档衔接。全文大概有 20 张表、40 个接口本地启动后可以直接跑通注册登录、分类管理、知识发布、全文检索、评论、收藏、用户管理、日志监控这条主线。无论你是做毕设、课程设计还是第一次完整接触前后端分离项目这篇文章都值得花十分钟读完然后照着思路把每一环讲明白。1. 为什么知识管理系统是Java Web毕设的黄金选题选毕设题目这件事本质上是在找一个边界清晰的完整项目。知识管理系统最大的优势在于它的业务边界非常朴素用户可以发布知识、管理知识、检索知识管理员可以审核、分类、看统计。这个边界内全是 Java Web 的核心考点边界外又不会让你陷入太偏门的领域。1.1 选题逻辑这个名字背后藏着哪些必考技术点先说知识两个字。一篇知识文档必然有标题、摘要、内容、分类、标签、作者、发布时间、阅读量、点赞数。这直接对应了后端的增删改查、分页查询、多表联查。然后是管理两个字。要管理就得有用户体系有用户体系就躲不开注册登录、密码加密、会话保持、登录鉴权要管理分类和文档状态就躲不开事务、逻辑删除、状态机。系统两个字又把它拉高一层一个像样的系统必须有统一返回格式、全局异常处理、日志记录、权限校验、数据统计。把这些串起来你会发现它就是教科书里 SpringBoot、MyBatis-Plus、Redis、JWT 这几大件的标准练习场。难度正好卡在每样都有、每样都不深的位置特别适合本科生在半年内一步步吃透。1.2 它和其他管理系统的本质差异在哪里同样叫管理系统图书管理系统、学生管理系统、仓库管理系统和知识管理系统的侧重点完全不同。图书管理的核心是库存流水学生管理的核心是信息维护而知识管理系统的核心是内容生产与检索。内容意味着富文本、Markdown 渲染、图片上传、字数统计检索意味着你要考虑关键词匹配、热度排序、多字段权重。这套源码在处理这些差异点的时候做得很聪明文档内容采用mediumtext存储前端用 Markdown 编辑器编辑、渲染组件展示后端提供单独的全文检索入口。这样既避开了 Elasticsearch 部署带来的额外成本又在答辩时能说清楚我为什么选 MySQL 的全文索引而不是 ES整条链路是自洽的。1.3 这套源码适合谁又不适合乱改成什么如果你是毕设选题选了知识管理/内容管理/文档管理等方向这套源码可以直接作为骨架。你只需要把知识换成你题目里的具体对象比如健康食谱旅游攻略课程资料然后把字段表和接口做好对应调整即可。但我不建议把它硬改成秒杀系统电商订单系统。因为它的数据库设计是按知识内容维度建模的没有一个强事务的订单链路你如果为了凑题目把订单、库存、支付硬塞进来反而会把原本清晰的架构改得不伦不类。说实话答辩老师一眼就能看出哪里是原生设计、哪里是临时拼接。2. 项目全貌与技术选型这套源码为什么这么组合技术选型不是越新越好而是刚好够用、别人能懂、你讲得清。这套源码的选型思路在 Java Web 毕设里属于非常经典的组合SpringBoot MyBatis-Plus MySQL Redis JWT前端 Vue Element UI Axios。下面把这套组合的每一环都展开讲。2.1 技术栈全景一张表看清前后端分工层级技术选型用途说明推荐版本偏好后端框架Spring Boot提供 RESTful API 服务2.7.x 系列稳定、JDK8 友好持久层MyBatis-Plus单表 CRUD 免写 SQL、自带分页插件3.5.x数据库MySQL业务数据主存储5.7 或 8.0 均可缓存Redis验证码、Token 黑名单、热点文章缓存6.x 即可鉴权JWT无状态登录态jjwt 0.9.x / 0.11.x前端框架VueSPA 单页应用Vue2 Element UI 或 Vue3 Element PlusHTTP 客户端Axios统一请求、响应拦截1.x接口文档Springfox / Knife4j 或 OpenAPI3自动生成在线文档与 SpringBoot 版本匹配这里要特别说一句 Vue2 和 Vue3 的选择。如果你是在校生很多课程和参考资料还停留在 Vue2 Element UI社区里搜问题的结果也更多但如果你对前端有一定基础我建议直接上 Vue3 Vite Element Plus。这套源码做到前后端分离前端选 Vue2 主要是为了兼容大量教学模板和旧组件库实际开发体验上 Vue3 的组合更顺。2.2 后端选型理由为什么用 MyBatis-Plus 而不是 JPA、为什么用 JWT 而不是 Session很多同学纠结过 MyBatis-Plus 和 JPA 到底选哪个。我的建议是毕设项目无脑 MyBatis-Plus。原因是JPA 的自动建表和懒加载代理概念对新手极不友好出了问题你连 SQL 日志都看不懂而 MyBatis-Plus 的逻辑删除、分页插件、代码生成器都是纯增量帮助核心依然是你熟悉的 MyBatis 思想答辩时也更好解释我写的 SQL 是怎么把数据查出来的。JWT 取代 Session 是这套源码一个很关键的亮点。传统 Session 方案要在服务器内存或 Redis 里维护会话记录分布式环境下要额外处理会话共享JWT 方案把用户信息签名进一个字符串 token 里服务端不保存状态天然适合前后端分离架构。代价是 token 在过期之前无法主动失效所以这套源码在 Redis 里维护了注销 token 黑名单也算是对这个经典问题的补充方案。2.3 前端选型理由Vue Element UI 如何撑起一个管理后台管理后台类页面的核心诉求是表格、表单、弹窗、菜单、权限。Element UI 把这五件的组件全部内置了Table 组件自带多选、排序、分页Form 组件自带校验规则Tree 组件直接渲染分类树。前端开发量因此大幅下降你只需要关注页面业务逻辑而不是从零搓一套组件。Vue Router 负责页面跳转Vuex 或 Pinia 负责全局状态比如登录用户信息、侧边栏折叠状态。这套源码里有一个比较关键的设计菜单不是写死的而是根据后端返回的用户角色动态生成。这样普通用户登录看不到用户管理管理员登录才有完整菜单前端权限和后端接口权限形成双重校验。2.4 模块划分一个完整知识管理平台包含哪些子系统从功能模块上看这套源码可以拆成六个横向模块认证与用户模块注册、登录、验证码、个人信息维护、密码修改。知识内容模块文档的发布、草稿、编辑、回收站、版本记录、Markdown 渲染。分类与标签模块无限层级分类树、标签关联、分类排序与禁用。互动模块评论、点赞、收藏我的收藏和我的发布两个个人中心页面。检索与统计模块标题/内容/摘要的关键词搜索热词排行后台仪表盘统计用户数、文章数、访问趋势。系统管理模块用户管理、角色分配、操作日志、数据字典。管理员核心就是看住用户和内容。这六个模块在代码里对应的就是controller/service/mapper/entity这四层结构。很多同学拿到源码最怕的就是找不到代码在哪里实际上只要按 controller 层方法名去对照接口文档每一层的关系很快就能理清。3. 数据库设计与SQL脚本的导入使用要点拿到源码包第一步不是急着npm install而是先把数据库跑通。这套项目自带schema.sql和data.sql两份脚本前者是建表语句后者是初始化数据。如果你直接双击导入后一脸懵多半是这几个地方没注意。3.1 核心表结构设计从用户表到文章表一次看懂建表脚本里最核心的表大致有这些表名核心字段设计要点sys_userid, username, password, nickname, avatar, role, statuspassword 存的是 BCrypt 加密值不是明文role 用ADMIN/USER字符串kb_categoryid, name, parent_id, sort_orderparent_id 为 0 表示顶级分类支持无限层级树kb_articleid, category_id, title, summary, content, author_id, status, view_count, like_countcontent 用mediumtext存长文本status 有草稿、已发布、回收站三态kb_commentid, article_id, user_id, parent_id, content用 parent_id 支持楼中楼回复kb_collectid, user_id, article_id联合唯一索引(user_id, article_id)防止重复收藏sys_operation_logid, user_id, module, operation, method, params, ip记录关键操作便于答辩演示安全设计一个特别值得留意的字段是kb_article里的status。很多同学会把删除做成了物理DELETE一旦删了数据就真的没了。这套源码用的是逻辑删除1正常、2回收站、0草稿。回收站里的文章还能恢复这在业务上很加分在答辩时也是一个可以闲聊的亮点。3.2 索引设计思路为什么这四张表必须建索引我能看到schema.sql里已经预设了索引这也是有些人忽略的关键点。sys_user表的username上建唯一索引保证登录名的唯一性kb_article表的category_id和author_id建普通索引因为列表页一定要按这两个字段做筛选kb_comment表的article_id建索引因为评论区的查询是高频操作kb_collect表建联合唯一索引。索引不是越多越好而是查询频率高、数据区分度大的字段才值得建。配合索引还有一个加分设计文章的浏览数、点赞数如果每次请求都直接UPDATE数据库压力会集中在热门文章上。所以这套源码把热点文章的访问计数先打到 Redis在一定阈值后才异步刷回 MySQL。你答辩讲到这一句面试官/老师通常都会点头。3.3 SQL脚本导入的完整步骤与常见报错导入脚本建议按下面顺序操作别省步骤用 Navicat 或命令行创建数据库CREATE DATABASE knowledge_base DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;注意是 utf8mb4不是 utf8否则表情符号和特殊字符会乱码。选中刚创建的数据库右键运行 SQL 文件先执行schema.sql确认所有表都建好再执行data.sql。如果data.sql报外键约束错误很可能是你执行了两次、或者表顺序没对上。删库重建一次性跑完就好。打开sys_user表确认有一条admin用户。登录密码如果是加密值你不在库里改直接用文档里给的管理员初始密码即可不用去猜。提示很多毕设项目最容易翻车的就是把 SQL 脚本在 root 用户的系统库mysql里执行结果表建到了系统库里。建库、选库、执行三部别混。3.4 初始化数据里藏着哪些演示素材data.sql里通常预置了管理员账号、测试用户账号、几篇示例知识文章、分类树数据和少量评论。这些数据不是随便写的分类层级会让你打开页面就有内容可看示例文章覆盖了如何发布文档常见问题系统说明之类的话题。你先用演示账号发一篇文章、再评论、再收藏把所有流程走一遍后面换自己的数据时心里就有数了。4. 后端三大核心模块鉴权、文档、检索的接口设计拿到接口文档后不要只把它当成前端同事的对接手册。把它当成后端代码的导览图每个接口背后都对应一段你可以讲清楚的业务逻辑。这套系统里最有含金量的三个模块是认证鉴权、文章文档、搜索检索。4.1 认证与权限登录接口、JWT拦截器与RBAC控制登录流程是经典的验证码校验 账号密码校验 签发 token。核心代码逻辑大致是这样PostMapping(/auth/login) public ResultLoginVO login(RequestBody LoginDTO dto) { // 1. 校验验证码从 redis 取出当前会话的 code与 dto.getCode() 比对 // 2. 根据 username 查用户用 BCrypt 的 matches 方法比对密码哈希 // 3. 校验用户状态 status 1被禁用用户不允许登录 // 4. 生成 JWTheader 放算法payload 放 userId 和 role签名密钥在 yml 中 // 5. 把 token 返回前端Redis 记录已登录标记 return Result.success(loginVO); }登录后客户端请求业务接口时要带Authorization: Bearer token后端通过拦截器解析。拦截器的粒度通常是这样的不需要登录的接口登录、注册、获取验证码、公开文章详情、分类树、搜索。需要登录的接口发布文章、评论、收藏、个人中心、退出登录。需要管理员权限的接口用户管理、分类管理、操作日志查看、仪表盘统计。这套源码里我特别喜欢的一点是权限校验不是散落在各个 Controller 里而是用自定义RequireRole注解 拦截器统一做的。前端菜单按角色渲染是一道门槛后端拦截器才是真正的安全边界。4.2 知识文档模块草稿、发布、回收站与版本记录如何设计文章接口的设计决定了这个系统是玩具 CRUD还是可演示的内容系统。这里有几个设计值得讲清楚草稿与发布分离status字段区分。前端编辑页面有保存草稿和发布两个按钮分别调不同的接口列表页默认只显示status1的数据。回收站回滚删除文章不直接物理删除而是把status改成2。回收站页面只对作者和管理员可见支持彻底删除和恢复两个操作。乐观锁与版本文章表里可以加一个version字段每次更新version1更新时WHERE id? AND version?。这在多人同时编辑文档的场景下防止最后保存的人覆盖前一个人答辩时提到这一点会显得你考虑过并发问题。这里必须说一个接口设计上的坑新增和编辑是两个接口不要合并。很多新手为了省事用一个接口判断 id 是否为空来区分新增和更新这在接口文档里会让前端很困惑Swagger 里的请求参数也会变得混乱。4.3 搜索与热度查询接口的分页、排序与缓存策略搜索接口是知识管理系统考核的重头戏。这套源码的搜索支持按关键词匹配title、summary、content并按相关度和时间排序大概长这样LambdaQueryWrapperKbArticle wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(keyword)) { wrapper.and(w - w .like(KbArticle::getTitle, keyword) .or().like(KbArticle::getContent, keyword) .or().like(KbArticle::getSummary, keyword)); } wrapper.eq(KbArticle::getStatus, 1) .orderByDesc(KbArticle::getIsTop) .orderByDesc(KbArticle::getCreateTime); PageKbArticle page articleMapper.selectPage(new Page(current, size), wrapper);大多数毕设项目到这个程度就足够了。如果你的技术水平想再往上走一层可以把content字段在 MySQL 里设成FULLTEXT用MATCH...AGAINST做真正的全文检索或者在系统里引入 Elasticsearch把文章数据同步到索引。但这套源码的定位是开箱即用所以它用LIKE查询来保证零额外依赖这个取舍是合理的。热度统计的接口同样不建议频繁查库。文章被点击时请求先到Redis用INCR对article:view:{id}自增然后接口直接返回当前浏览量 缓存值 数据库基准值。后台定时任务每 5 分钟把缓存中的增量批量写入数据库既保证了实时性又不会在高访问下压垮 MySQL。4.4 统一响应体与全局异常处理所有接口的通用语言这套源码的每个接口都返回下面这个统一结构{ code: 200, message: 操作成功, data: { } }code约定为200成功、400参数错误、401未登录或 token 失效、403无权限、500服务器异常。前端 Axios 拦截器只看code这一个字段200就走成功分支否则弹message。这样后端不管挂在哪里前端都能统一处理不会出现一会儿返回直接数据、一会儿返回包装数据的混乱情况。全局异常处理用的是RestControllerAdvice。校验注解Validated抛出的参数异常、业务主动抛出的BizException、数据库连不上的系统异常分别在 advice 里被捕获并转成统一 JSON。这个类在整个项目里差不多是复制粘贴率最高的文件但它恰恰决定了接口联调时的体验。5. 前端Vue工程如何落地从路由守卫到知识详情页后端接口设计得再漂亮最终要落到页面上。Vue 端拿到这套源码第一步是npm install然后npm run dev但我建议你先别急着打开浏览器先把几个前端核心文件的位置搞清楚后面改起来才有方向。5.1 工程结构src目录下每个文件夹是干什么的src/api/按模块拆分的接口调用文件每个文件导出一个对象方法名与后端接口一一对应比如article.js里有getArticlePage、getArticleDetail、addArticle。src/router/路由配置。和页面目录基本一一对应。src/store/全局状态。Vuex 或 Pinia 里存token、userInfo、menuList。src/views/页面。常见的有login.vue、home.vue、article/detail.vue、article/editor.vue、admin/user.vue、admin/category.vue等。src/components/公共组件比如富文本编辑器、分页器、评论列表。src/utils/request.jsAxios 实例的封装统一配置baseURL、超时时间、请求拦截器、响应拦截器。5.2 路由守卫、动态菜单与 localStorage 的配合前端权限控制的逻辑通常是这样的用户登录成功后后端返回role和可以访问的菜单权限前端把它存到localStorage和Vuex。在路由前置守卫里判断router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (!token to.path ! /login) { next(/login); // 未登录强制跳登录页 } else if (token to.path /login) { next(/); // 已登录不许回登录页 } else { // 路由 meta 里标记了 adminOnly 的页面额外校验角色 if (to.meta.adminOnly store.state.userInfo.role ! ADMIN) { next(/403); } else { next(); } } });这套逻辑的精髓是前端路由防君子不防小人。真正的数据安全永远在后端前端守卫只是用户体验辅助这个观点如果你能在答辩时说出来会显得你对前后端分离架构理解得很透彻。5.3 核心页面链路列表页→详情页→编辑页怎么串起来整个前端最核心的一条链路是知识列表页 → 知识详情页 → 编辑发布页。列表页调用articlePage接口拿到records遍历渲染。点击文章卡片router.push({ path: /article/ row.id })跳转详情。详情页根据路由参数id调用getArticleDetail拿到文章数据。访问量、点赞数、评论列表都在这个页面展示。内容字段如果是 Markdown前端用markdown-it渲染成 HTML再配代码高亮插件。编辑发布页如果路由是/editor走新增如果路由是/editor/:id先拉文章详情回显再允许修改后提交。页面里内置文件上传组件把图片传到后端接口返回的 URL 直接插入 Markdown 正文。5.4 Axios请求封装与跨域问题的一次性解决src/utils/request.js是整个前端的命门它做三件事请求拦截器里把token放进请求头响应拦截器里如果code 401清除本地登录态并跳回登录页对后端返回的数据统一做解包页面代码里直接拿response.data.data后的内容。开发环境的跨域问题通常是靠 Vite 的代理配置搞定的。在vite.config.js里配置server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端页面里请求/api/article/page后端拿到的是http://localhost:8080/api/article/page规避了浏览器同源策略。一个常见误区是前端请求地址必须写成完整 URL然后去后端改CrossOrigin注解。用代理反而更干净生产环境也更容易迁移。6. 接口文档的规范与前后端联调的经验教训接口文档在毕设里的地位很微妙。很多学生不写答辩时口述也有学生写了但就是给 Swagger 截个图。这套源码里附带的接口文档我建议你把它当项目第二源码来用。它不仅能帮你和前端同学对接顺畅更是你自己梳理后端逻辑最好的工具。6.1 接口文档的两种落地形式Swagger自动生成与手工维护对于 SpringBoot 项目最省事的做法是引入springfox-boot-starter或 Knife4j启动项目后访问http://localhost:8080/doc.html就能看到所有接口的在线文档包括请求参数类型、返回值结构、接口分组。源码包里如果已经配好你只需要在写 Controller 时把ApiOperation(获取文章分页列表)这类注解补上文档就会自动更新。手工维护的接口文档则更适合用于答辩材料。你可以在 Word 里整理出每个模块的接口清单列出接口地址、请求方式、请求参数、返回示例、注意事项。我见过很多做得好的毕设就是把这一份文档打印出来放在答辩桌上评委翻到哪一页都能对应到系统里的真实功能。6.2 一次登录→查列表→发文章的全链路联调过程我把这套源码的联调过程还原一遍你以后自己调试时可以参考这个思路。第一步配置前端环境变量。.env.development里写VITE_API_BASE_URL/api后端application.yml里配置server.port: 8080和context-path: /api的对应关系。第二步后端启动浏览器打开localhost:8080/doc.html确认接口能调通。第三步前端npm run dev打开localhost:5173在登录页用admin/123456登录验证码从 Redis 里能正常生成。第四步登录成功后打开浏览器开发者工具Network 面板里可以看到三个请求captcha、login、getUserInfo全部返回 200。第五步进入文章列表页确认分类树和分页列表都正常渲染再发一篇测试文章整个链路结束。联调过程中F12 的 Network 面板是你最好的朋友。前端报错先看请求有没有发出去请求发出去了就看响应状态码响应是 200 但页面没数据就看返回的 JSON 结构是不是和你预期的不一致。大部分页面白屏问题最后都出在解包路径不一致。6.3 联调必踩的三个坑CORS、参数命名、时间格式第一个坑是 CORS。如果不用代理、直接跨域请求后端要么加全局 CORS 配置要么等着浏览器 Localhost 之间的拦截报错。我用下来最稳的是前端代理方案生产环境再交给 Nginx 反向代理后端完全不用写CrossOrigin。第二个坑是参数命名。后端用下划线风格如category_id还是驼峰风格如categoryId必须要统一。MyBatis-Plus 默认开启驼峰映射所以后端的categoryId字段能自动映射到数据库category_id列但前端传参时如果和后端 DTO 字段对不上接口就会返回参数缺失。建议所有接口参数都用驼峰和 Java 字段保持一致别混用。第三个坑是时间格式。Java 返回的LocalDateTime默认格式是一长串带T的比如2024-06-01T12:30:45前端直接显示会很丑。统一在application.yml里配上jackson.date-format: yyyy-MM-dd HH:mm:ss和time-zone: GMT8前后端的时间展示问题就一次解决了。7. 从localhost到公网启动顺序与部署避坑前面所有内容讲的基本都是在你电脑上把项目跑起来。到这一步项目只完成了 70%。剩下 30% 是把它部署到一台真正的 Linux 服务器上用 Nginx 托管前端、用 systemd 托管后端这才是完整的交付状态。7.1 本地开发环境的启动顺序与验证清单本地启动一定要按顺序来不然会白白浪费时间排查启动 MySQL确认knowledge_base数据库存在导入过 SQL 脚本。启动 Redis确认端口 6379 可以ping通。修改application.yml里的数据库账号密码和 Redis 密码确保能连上你本地实例。启动后端。观察控制台日志看到Started Application说明成功。日志里如果出现Access denied for user一定是数据库密码错了。打开http://localhost:8080/doc.html验证接口文档能加载。启动前端。npm install之后npm run dev打开http://localhost:5173登录一次。最后验证一条业务链路登录 → 发文章 → 搜索到这篇文章 → 收藏 → 在个人中心看到收藏记录。这条清单跑通说明开发环境 100% 没问题后面部署遇到问题可以拿它做对照。7.2 前端打包与Nginx配置为什么部署后页面白屏前端打包用npm run build产物在dist/目录里。把dist里的文件传到服务器的/usr/share/nginx/html或你自己指定的目录然后关键就在 Nginx 配置。SPA 应用有个特点路由是前端控制的如果你直接访问http://你的域名/article/5Nginx 会去找服务器上真实存在的/article/5路径结果自然是 404。所以 Nginx 配置必须有一行try_fileslocation / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }try_files的意思是先找真实文件找不到就返回index.html让前端路由接管这个路径。很多部署后白屏、刷新页面 404 的问题90% 都出在没写这一行。后端接口也要在同一个 Nginx 里做代理配置大致是location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }7.3 Linux服务器部署要点Java环境、放行端口与进程守护服务器上需要装一个 JDK8 或 JDK11把后端的 jar 包用java -jar xxx.jar跑起来。但直接跑在终端里有个问题关掉窗口进程就死了。建议用nohup或注册 systemd 服务。我用 systemd 比较多因为它能实现开机自启和宕机自动重启。简单写个/etc/systemd/system/knowledge-backend.service然后systemctl enable knowledge-backend就能托管了。防火墙方面MySQL 3306 端口不要对外开放只允许本机访问因为后端和它在同一台服务器上对外只需要开80Nginx和443HTTPS端口。后端 8080 端口也应该只对 Nginx 开放或者直接让 Nginx 代理转发不让外部直连 Tomcat。这些安全细节做出来答辩老师一看就知道你不是只会run。7.4 答辩前必须想明白的几个为什么最后列几个答辩高频问题这套源码的每一行都能回答上为什么用 JWT 而不用 Session答无状态、跨域友好、适合分布式部署通过 Redis 维护黑名单解决注销问题。密码为什么不存明文答BCrypt 加盐哈希即使数据库泄露也无法逆向得到明文密码。删除为什么用逻辑删除答保留历史数据可恢复配合deleted字段对统计报表也很友好。前端路由守卫和后端权限拦截有什么区别答前端守卫改善体验后端拦截器才是安全边界权限最终由接口决定。文章浏览量高并发怎么处理答Redis 先INCR扛实时流量再异步批量落库降低数据库压力。把这一段反复读熟你答辩的状态会比源码能跑好很多。我在接手这类源码项目时的体会是看源码不是看它写了多少行代码而是看懂作者在每个技术选型上做的取舍。这套知识管理系统平台最值得学习的地方不是某个炫酷的页面而是它用最少的外部依赖把一条业务主线走完整的能力。你照着它的思路跑通一遍后面再做任何管理系统都能搭出差不多的骨架。最后再分享一个小技巧拿到源码后先花半小时把 SQL 脚本和接口文档从头到尾读一遍再动手启动代码效率远高于直接run。
阅读完成 · 觉得有帮助?
咨询建站