每年这时候都会有一大批同学被管理系统类项目折腾得够呛。前几天还有人问我“新闻发布信息收集系统”到底该从哪下手,我看了下市面上的资料,要么讲得太空不讲落地,要么代码片段东一块西一块根本拼不起来。这个选题看起来普通,但真要做得完整、能答辩、能演示,里面值得扣的细节其实不少。这里我把做这套SpringBoot + Vue全栈系统时积累的东西完整写出来,从设计思路到具体实现再到部署落地,希望能给准备做类似网站的同学一份能直接参考的完整路线。
1. 从需求出发:这个系统的核心其实不是“新闻发布”
一说“新闻发布系统”,很多人第一反应就是后台发文章、前台看列表,但其实这类选题的完整名字里还有“信息收集”四个字。这才是整套系统中经常被忽略、却最能体现工作量与设计水平的部分。
1.1 一次完整的功能拆解:谁在用、用哪几个页面、完成什么任务
我习惯先把用户角色和一整套流程画出来。这套系统里,常规情况下有两种用户:一种是普通访问者(网站访客),另一种是后台管理员,两者所需功能差异很大。
普通访问者能看到的是前台页面:新闻列表、新闻详情、分类浏览,以及“信息收集”相关的模块——比如提交新闻线索、在线投稿、留言反馈,或填写联系信息。这些提交的数据最终汇总到后台,由管理员处理。
后台管理员需要完成的工作,拆开来看大概有这么几块:
- 新闻分类管理:增删改查,控制前台展示的分类结构。
- 新闻内容管理:发布、编辑、下线、删除新闻,支持封面图上传、摘要填写、正文编辑。
- 信息收集处理:查看用户提交的线索/投稿/反馈列表,标记处理状态(未处理、已处理、已驳回),必要时删除或导出。
- 用户状态管理:管理管理员账号,必要时可扩展管理普通用户列表。
- 系统数据统计:一个简单的仪表盘,展示新闻总数、今日发布数、待处理收集记录数等。
换句话说,在答辩或需求文档里,这套系统的定位应当是:一套面向网站访客的信息展示与提交平台,同时为管理员提供完整的内容维护和信息审核后台。这个定位一句话就能讲清楚,但功能边界非常清晰,比笼统的“新闻发布管理系统”更有说服力,也更容易撑起一篇完整的论文。
1.2 原型参考:信息收集模块要设计到什么程度才不显得凑数
我看到过很多类似的系统,信息收集模块就是一张表加两个页面,提交完就完了,管理员连“处理状态”都不能改。这样会给人一种“为了凑选题要求硬塞了一个模块”的感觉。
我建议至少做到这种程度:前台提供一个“信息提交”页面,支持用户选择提交类型(新闻线索、在线投稿、意见反馈),填写标题、内容、联系方式,提交后能看到自己的提交记录和当前处理状态。后台对应提供列表筛选(按类型、按状态)、处理操作(更改状态、填写处理备注)、删除,以及批量导出。可选的加分项包括邮件通知管理员新提交、验证码防刷、敏感词过滤等。我实际做的时候,核心流程围绕“提交-管理-处理-反馈”闭环来做,系统整体在演示时逻辑非常完整,也不会显得冗长臃肿。
2. 技术选型与工程结构:为什么是SpringBoot + Vue这套组合
这类系统的技术栈选择,其实不需要追求新潮或复杂。SpringBoot + Vue的组合能成为管理系统领域的“主流”,有它非常现实的原因——上手曲线平滑、生态成熟、前后端开发效率高,而且对后期扩充分布式或微服务也留了余地。
2.1 版本选型与脚手架搭建细节
先说后端。SpringBoot我推荐使用2.7.x版本,不要一上来直接上Spring Boot 3.x。原因很简单:3.x底层的Jakarta命名空间迁移会让不少老教程失效,部分第三方starter也未完全跟上,而2.7已经非常成熟,资料多、坑少、兼容性好。Java环境用1.8或11都行,我个人建议1.8,零配置、生态完善,在学校机房的旧环境上也能顺利跑起来。
依赖管理上我走的组合是Spring Web + MyBatis-Plus + MySQL驱动 + Lombok。MyBatis-Plus的使用能明显减少样板代码,提供分页插件、逻辑删除、自动填充等能力,非常适合快速开发。要注意的是,MyBatis-Plus的新版本(3.5.x)与旧版API有少量差异,尤其是分页插件的配置方式,我后面会专门说明。
前端我选择Vue 3 + Vite + Element Plus + Pinia。Vite相比Webpack最直观的改善是启动速度快,开发体验好很多。Element Plus的表格、表单、弹窗和布局组件刚好覆盖后台管理所需的全部界面元素,不需要额外引入图表库或复杂工具。接口请求用Axios,并且通过封装拦截器统一处理token注入、错误提示和登录失效跳转。
工程结构采用标准前后端分离:backend目录存SpringBoot工程,frontend目录存Vue工程。后端包结构控制层、业务层、持久层严格区分,层与层之间用DTO对象做数据隔离,不直接把Entity暴露给前端。这个习惯在开发和维护时会让你少掉很多头发,尤其是后续改动表结构时。
2.2 为什么我坚持不引入Redis和JWT做登录
这里想特别说一个问题。现在网上很多模板一上来就Redis + JWT + Spring Security,看着很“专业”,但对这类管理系统来说,很多时候是过度设计。
新闻发布信息收集系统的真实使用场景通常很明确:后台使用者是固定的一两名管理员,不存在高并发分布式会话同步的需求。JWT虽然无状态,但会遇到token失效控制麻烦、服务端主动踢人实现复杂等额外问题。Spring Security更是有一整套配置和学习成本,对初期项目来说性价比很低。
我的方案是用SpringBoot默认的Session会话 + 一个登录拦截器,前端登录后将返回的信息存下来,后续请求统一携带凭证,被拦截时配合Axios拦截器跳回登录页。这点会话机制足以实现“未登录不可访问后台”这个核心诉求,等到项目需要多服务部署或前后台分离部署之后再考虑引入JWT也不迟。能让系统保持简单的地方就让它保持简单,这也是一种成熟的设计能力。
3. 数据库设计与后端落地:信息收集的表结构和新闻发布流程
数据库设计是整个系统最容易在论文里被单独放大的部分,也是最容易暴露“没想清楚”的地方。而新闻发布系统的表结构并不复杂,核心在于把字段设计得够用、合理、不冗余,同时让状态流转清晰可查。
3.1 核心表结构与字段设计思路
我最终落地时一共用了5张表,每张都是必需品:
新闻分类表(news_category):主键、分类名称、排序、创建时间。字段尽量精简,不需要放状态字段和描述字段,因为分类本身只承担分组作用。
新闻信息表(news_info):主键、分类ID、标题、摘要、封面图路径、正文内容、发布时间、浏览量、是否置顶、是否发布、创建时间、修改时间。其中“是否置顶”和“浏览量”是我建议保留的,因为这两个字段能支撑前台排序的丰富性,也更接近真实新闻网站的行为。覆盖图建议只保存图片的相对路径字符串,图片文件本身放在独立的上传目录,不要以二进制形式直接入库。
信息收集表(collect_info):主键、提交类型(线索/投稿/反馈)、标题、详细内容、联系人、联系电话、邮箱、处理状态(待处理/已处理/已驳回)、处理备注、提交时间、处理时间。这是“信息收集”的核心落点。是否允许匿名提交、是否强制填联系方式,可以根据需求配置,我建议联系方式和类型必填,其他项可以放宽。
用户表(sys_user):主键、用户名、密码(BCrypt加密存储,这里不要用MD5)、昵称、头像、创建时间。
操作日志表(sys_log):可选但推荐。管理员每次登录、发布新闻、修改处理状态时记录一条日志,作为审计痕迹。在答辩展示时,这个表会显得系统非常完整,不仅“能用”还“可追溯”。
3.2 发布时间与浏览量:字段虽小,逻辑要闭环
表格设计完毕后,有大量的细节逻辑需要考虑。就拿“发布时间”来说,很多管理系统只在后台发布新闻时保存当前时间,之后就不再修改了。但实际运营中,管理员经常会更新新闻内容,此时“发布时间”和“修改时间”就出现了概念分叉。
我的处理是:新增新闻的创建时间即发布时间;编辑新闻时如果勾选了“更新时间等于当前时间”,则刷新发布时间,否则保持原发布时间不变。虽然这只是一个很小的交互细节,但决定了系统在语义上是否合理。
浏览量的字段设计也需要做初始化处理。我推荐在前端详情页请求到达时会路径持有一个浏览量值,首次访问调一次自增操作,避免每次浏览都执行一次全表更新。这块可以不需要Redis,直接SQL更新就能支撑当前量级的系统。
3.3 后端核心接口设计:从Controller到Mapper的完整链路
后端开发的顺序我建议按照“分类管理 → 新闻管理 → 信息收集管理 → 登录与用户”这样的依赖次序推进。每做一个模块,直接完成从前端所需的最小接口集到数据库的完整闭环。
新闻模块的接口设计,我按照类似REST的风格展开:
- GET /api/news/list:前台分页查询已发布新闻,支持分类筛选和关键词搜索。
- GET /api/news/detail/{id}:前台获取新闻详情,同时浏览量加一。
- GET /api/news/adminList:后台分页查询新闻(含未发布的,支持状态筛选)。
- POST /api/news/save:新增新闻(需要登录)。
- PUT /api/news/update:编辑新闻(需要登录)。
- DELETE /api/news/delete/{id}:删除新闻(需要登录)。
信息收集模块的接口类似:
- POST /api/collect/submit:前台提交收集数据。
- GET /api/collect/queryByToken:前台根据联系方式/提交编号查询自己的提交记录。
- GET /api/collect/adminList:后台分页查询收集记录,支持类型和状态筛选。
- PUT /api/collect/process:后台处理,更新处理状态和备注。
- DELETE /api/collect/delete/{id}:后台删除收集记录。
Controller层我不建议写具体业务逻辑,只负责参数校验和调用业务;业务层处理好接口接收的数据并做统一异常封装。Mapper层编写SQL时,新闻列表的分页查询几乎必利动态三元素查询和排序功能,这块MyBatis-Plus的QueryWrapper处理起来很方便。
3.4 统一返回结构与优雅校验:没人告诉你但是必须做的工程习惯
两个非常重要的工程习惯:第一,所有接口返回统一的结构,类似Result.success(data) / Result.error(msg)。第二,所有参数必须做校验。
统一返回结构的好处在前端排错时特别明显。我见过不少同学的前后端交互,后端有时返回一个对象、有时返回字符串、有时直接抛500,导致前端Axios拦截器很难统一处理错误提示。用统一结构之后,前端只需要判断code字段,然后处理data或message,两行代码就能覆盖绝大多数接口的交互逻辑。
参数校验这里我跟你分享一个容易忽略的点:后台新闻保存时,标题、分类ID、内容这些必填项一个都不能少校验,否则空数据进库,前台列表展示直接出现空卡片,而信息收集表单的校验还可以防止无效垃圾数据刷爆后台。前端Form表单的rules校验和后端Controller的参数校验必须双重保障,因为前端校验可以绕过,后端校验才是真正的底线。
4. Vue侧页面编排与交互实现:后台管理界面的关键细节
前端开发方面,这套系统的重点是后台管理界面。管理界面的设计并不是漂亮就行,更关键的是核心交互流程自然顺畅、状态清晰、操作位置固定。
4.1 权限控制与页面路由组织
前端路由集中管理,分为公开路由和需要登录的路由。新闻前台浏览、信息提交和信息查询归属公开路由;后台所有页面归属需要登录的路由。Vue Router的全局前置守卫是控制访问权限的主要手段:每次跳转前判断目标路由的requireAuth标记,如果未登录就强制跳转登录页,并携带redirect参数以便完成登录后再回到原来想访问的页面。
后台管理的整体布局采用典型的三段式:左侧为侧边导航栏,顶部为用户区与退出按钮,中间为内容区域。导航菜单的菜单项与后端模块一一对应,菜单层级建议最多两级,避免为一个动作单独建一个页面。
4.2 新闻编辑器选型:覆盖图与正文的处理策略
新闻正文编辑器是这类系统前端最容易纠结的部分。经反复实测,我选用了wangeditor 5,它开源免费、界面简洁、中文支持良好、可按需上传图片并返回URL,对新闻管理系统来说是最顺手的选择,没有之一。富文本内容以HTML片段形式提交并入库,前端详情页直接v-html渲染。
这里必须提醒一个安全事项:后端在保存富文本内容时,不要轻易过滤HTML标签,否则可能会破坏样式,但需要在前端提交时对上传图片做文件类型限制,后端接口也需要对文件类型做二次拦截,防止恶意文件上传。安全这道防线越早做越好。
覆盖图(首图)的处理,我推荐的方案是:上传接口将图片存入后端static/upload目录,返回相对路径,前端用路径拼接方式访问。部署时再将静态资源交由Nginx统一处理,后面是我踩过坑才搞明白的,如果直接用SpringBoot的静态资源映射,相对路径转换成绝对URL的规则会容易出偏差,不如部署时做一个静态资源转发统一解决了。
4.3 信息收集模块的前端闭环与操作细节
信息收集模块虽然结构简单,但细节设计仍然需要多花心思。提交页面的表单,除了必要的输入校验外,我强烈建议加上验证码或留痕字段,否则部署到公网后,防止被脚本批量提交垃圾数据会是一个困扰。即使暂时不做验证码,也可以加一个简单的提交频次限制。
后台处理页面的“处理状态”我用了带tag标签的表格展示,待处理显示为橙色标签、已处理为绿色、已驳回为红色。行内操作按钮区放“处理”“详情”“删除”三个操作,删除都要二次确认弹窗。筛选栏默认显示全部状态,这样管理员能一眼看到待处理的数量。
需要特别说明的还有前台“查询我的提交记录”这个功能。由于没有强制注册登录,我采用了联系方式作为查询凭证的方案:用户提交时留联系电话,然后通过输入联系电话查询系统里该联系人的提交记录。在开发时只需要对联系人字段做索引,查询性能完全不需要担心,这一设计既避免了强制注册带来的流程冗余,又能让提交者感受到“进度可查”的服务闭环。
4.4 Axios拦截器与全局状态管理实践
前端与后端的沟通关键是Axios的全局拦截器配置。我在request拦截器里把BaseURL定义为同一环境下的 /api 前缀,以便后期后端网关统一转发;response拦截器里统一处理业务错误码。登录接口成功后,后端会返回id、用户名、昵称信息,再由前端把登录状态和用户基本信息存入Pinia和sessionStorage,在路由守卫中一并校验。
Pinia的store我单独拆了两个:一个管理用户信息,一个管理系统基础配置(例如前台展示的分类列表缓存)。组件内部不要直接修改store里的数据,统一通过actions方法异步更新,这样状态变更逻辑集中可查,后期排查问题时会更高效。
5. 联调期的隐蔽问题清单:从跨域到文件上传的逐一排雷
前后端分离开发到联调阶段,很多工程性问题会集中爆发。我会把这些大多数教程不会写、但几乎每个项目都会遇到的问题列出来,可以直接对照检查。
5.1 跨域配置:三种写法里最推荐的一种
本地开发时前端默认跑在5173端口,后端跑在8080端口,两者端口不同,浏览器会拦截跨域请求。解决跨域的方式有三类:前端Vite配置proxy代理转发;后端Controller加@CrossOrigin注解;后端写一个全局WebMvcConfigurer配置类。
我推荐第三种。优劣势如下:Vite proxy仅在开发模式下生效,打包上线后还需要重新配置Nginx反向代理;@CrossOrigin散落在各个方法上,管理不集中。后端全局配置类通过addCorsMappings方法统一匹配/**路径,开发联调时让后端允许所有来源,上线前再收紧到具体域名,这种灵活性和可维护性是最好的。
5.2 文件上传三个常见坑:编码、大小、路径
后端上传接口需要配置一个很关键的文件大小参数。SpringBoot默认的单文件上传上限只有1MB,富文本里稍微放几张高清照片就直接报错。在application.yml里调整spring.servlet.multipart.max-file-size和max-request-size,我把它们都设为50MB,实际项目里完全够了。
其次,上传路径必须绝对可控。我的实现是上传目录默认用项目根目录下的upload文件夹,同时通过配置类将其映射为 /images/** 的静态资源URL前缀,前端展示时直接用相对路径即可访问,既保证了开发模式,也不妨碍后续用Nginx接管。
最后,文件名生成不要用原始文件名,一是包含中文路径时解码容易出现乱码,二是同名文件会互相覆盖。我推荐UUID + 原扩展名的格式,存储时按日期分目录存放,例如upload/20250512/xxx.jpg。
5.3 富文本上传图片的未来困扰
富文本编辑器图片上传集成是联调期最容易卡住的一环。wangeditor 5默认采用自定义upload的hook方式,需要自己把File对象POST到后端上传接口,再把返回的URL拼进编辑器。
操作细节上,要注意后端上传接口的返回格式跟编辑器期望的格式保持一致,编辑器需要返回具体的data类型,内部要求url和alt两个字段。如果嫌麻烦在前端通过FileReader转成Base64再插入编辑器,也能实现预览功能,但这种方式会让数据库体积膨胀得非常快,我强烈不建议。
6. 部署上线与运行测试:从本地跑通到服务器可访问
能本地跑通系统只能算是完成了一半。另一半是发布部署的整套流程,这部分在答辩中同样占有重要的展示权重,尤其是“线上可以稳定运行”这句描述,体系构建的都是一般同学直接落下的分数。
6.1 打包前的配置分离思路
打包部署前需要处理环境配置分离。开发环境与生产环境的数据库地址、文件上传路径、部署域名都不同,如果每次都手工改配置文件,简直是一场心理折磨。
我的做法是用两种方式配合:启动时通过application.yml加载一套默认配置,同时用application-prod.yml等配置文件覆盖生产环境差异项。后端用Maven的profile方式切换不同环境的打包配置;前端在根目录创建 .env.production 文件,通过Vite的环境变量机制,将生产环境的API请求地址指向后端域名。这样一份代码在本地和服务器都能跑起来。
6.2 部署方案的推荐:前后端独立部署还是同时放在Nginx下
前后端如何部署,我见过三类方案:
- 前后端分别部署在不同服务器,通过CORS跨域访问。
- 前后端打包后的静态文件同时放在同一台服务器的Nginx下,后端接口通过Nginx代理转发。
- 前后端静态文件放在后端Jar包内部,由Spring Boot接管。
我强烈推荐第二,这也是我在生产环境中使用的方案。前端构建后的dist目录指定为Nginx的网站根目录,然后对 /api 和 /images 的请求做反向代理转发到SpringBoot服务端口。整个部署下来只有一个Nginx暴露端口,无需处理跨域,也便于后续配置HTTPS证书。对于这类管理系统,这个方案具有极强的可维护性。
6.3 我遇到的三个线上环境问题
第一次部署时,我遇到过几个问题,都需要在交付前仔细检查:
第一,数据库连接时区问题。MySQL连接串必须带serverTimezone=Asia/Shanghai,否则部署后时间会相差8小时。
第二,前端路由刷新404。这是因为Nginx默认找不到Vue Router的history模式下的匹配文件,需要配置 try_files $uri $uri/ /index.html,否则前台详情页或后台深层页面刷新时直接白屏。
第三,上传目录权限问题。Linux下进程对写upload目录没有权限时,Spring Boot虽然启动正常但任何图片都无法上传。通过 chmod 授权和数据卷映射解决即可。
7. 总结与个人经验
最后谈一点个人对这类项目的体会。很多人觉得新闻发布信息收集系统太普通,体现不出技术含量,但从我的经验看,项目的价值不在于技术框架有多新、代码量有多庞大,而在于能否把一整套业务逻辑完整跑通,并且在设计上有明确的思考和取舍。从用户提交线索,到管理员审核处理,再到用户查询反馈,这个流程真正的名字是内容生产闭环,并不只是“增删改查”。
项目做到后期,我最大的感受是:任何管理系统最难的部分都不是某一个具体功能,而是所有小细节交织在一起后仍然保持稳定。一个浏览量自增、一个富文本图片上传、一个登录过期跳转,所有细节单独看都不算什么,但组合在一起体验就会天差地别。
如果你是从零开始做这个选题的同学,建议先按我第二章的功能清单梳理需求,再按第三章的表结构建库建表,后端按章节顺序逐个模块开发,前端以管理端为主、展示端为辅,最后在部署阶段按第六章的清单逐项排查。只要能走通这条线,你在这个项目上的收获甚至会比跟一个复杂框架的教程学三个月还要多。