news 2026/9/15 4:25:51

Spring Boot校园新闻管理系统毕业设计完整开发指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot校园新闻管理系统毕业设计完整开发指南

校园新闻管理系统这个选题,在 Java 后端方向的毕业设计里属于“经典款中的经典款”。它的好处很实在:题目不难理解,技术栈主流,业务场景贴近校园生活,评委一眼就能看懂系统在干嘛。基于 Java + Spring Boot 来做这套系统,刚好能覆盖 Web 开发的一整条链路——前端页面、后端接口、数据库建模、权限控制、状态流转、部署上线,做完之后你对整个 Java Web 开发的流程会有非常具体的体感,而不只是停留在“会写几个接口”的层面。

这周有个学弟让我帮他过一遍这个项目的设计文档,我才发现很多人拿到这个题目的第一反应是“不就是新闻的增删改查吗”,然后直接开始写代码,结果写到评论、审核、角色权限的时候就懵了。这篇文章我打算从需求分析开始,把数据库设计、后端实现、前端联调、部署上线到答辩准备全部串一遍,每个环节都给你可以直接抄作业的思路和代码。不管你打算用 Thymeleaf 做服务端渲染,还是用 Vue 做前后端分离,这篇文章都能让你少踩不少坑。

1. 需求分析与功能拆解:先把系统会碰到的角色和流程理清楚

1.1 三种角色与两条核心业务流

做校园新闻管理系统,第一步不是建表,不是写 pom.xml,而是先把“谁在用这个系统”和“系统里会发生什么”说清楚。这个项目里我一般把用户分成三类:普通用户(学生、老师)、新闻编辑、系统管理员。普通用户负责看新闻、搜新闻、评论和点赞;新闻编辑通常是校报记者团或者院系宣传员,负责写稿和投稿;系统管理员则是整个系统的运营者,掌握分类管理、新闻审核、用户管理这些后台权限。

这里有一个很关键的设计:校园新闻毕竟是代表学校发声的内容,正式发布前必须经过管理员审核,不能编辑写完就直接挂到首页。所以整个系统的核心业务流其实是两条:第一条是内容生产流——“编辑写草稿 → 提交审核 → 管理员审核通过 → 新闻发布 → 管理员下架”;第二条是互动消费流——“用户搜索/浏览新闻 → 点击查看详情 → 评论/点赞 → 浏览量累计”。这两条链路一条对应后台管理,一条对应前台展示,全部走通之后,这个系统才是完整的,而不是一堆孤立页面的拼凑。

1.2 前台与后台的功能清单

把角色和流程定下来之后,功能模块就非常清楚了。我习惯在动手前先列一张表,把自己要做的东西全部摊开,避免写着写着漏了模块,也方便后面排开发顺序。

模块包含功能使用角色说明
用户认证登录、注册、退出登录、密码加密所有用户推荐使用 BCrypt 加密,明文密码在毕业设计里是硬伤
新闻展示首页推荐、分类列表、新闻详情、站内搜索所有用户未登录也能浏览,这是内容型网站的基本体验
互动功能评论、回复、点赞、浏览量统计登录用户点赞必须做防重复,否则答辩时点两次就露馅
新闻管理新闻增删改查、提交审核、编辑草稿新闻编辑编辑只能维护自己的新闻,看到自己提交的审核状态
审核流程列表审核、通过/驳回、上下架系统管理员这是区分“CRUD 项目”和“管理系统”的核心模块
分类管理分类增删改查、排序、启用禁用系统管理员分类变化频率低,但要考虑删除时已有新闻怎么处理
用户管理用户列表、禁用/启用、角色分配系统管理员可以简化,但必须能禁用异常账号
数据统计总新闻数、分类占比、最新审核动态系统管理员后台首页做个简单的仪表盘,答辩演示效果好

1.3 为什么要刻意设计一个“业务闭环”

很多同学做毕设容易陷入“能跑就行”的心态,结果论文只能写“实现了新闻的增删改查”,答辩被老师一追问就直接卡壳。我建议哪怕时间再紧,也要想办法把业务闭环做完整。所谓闭环,就是让数据在系统里流动起来:编辑投稿后台产生一条待审核新闻,管理员审核后在首页可见,用户看完会产生评论、点赞和浏览数据,这些数据又回到后台成为运营依据。

这一步不需要额外引入什么中间件,只要在数据库表设计上把新闻表的状态字段、评论表的外键、点赞表的唯一索引设计好,后端把状态流转的逻辑写严谨,整个项目在老师眼里的完整度马上就不一样了。严格来说,这套系统的最小可用版本其实就是两张表——用户表和新闻表,但真正值得写进论文和讲给评委听的,是后面慢慢补上的审核流程、互动逻辑和权限控制。

2. 技术选型:Spring Boot 之外的搭配不是越新越好

2.1 后端选型:ORM、鉴权与缓存怎么配

后端框架基本没有悬念,Java 后端毕业设计用 Spring Boot 是绝对主流。真正让人纠结的是围绕 Spring Boot 周边怎么选,尤其是 ORM 和权限框架。ORM 方面,我建议优先考虑 MyBatis-Plus。它比原生 MyBatis 省去了大量写 mapper XML 的功夫,单表增删改查直接继承 BaseMapper,条件查询用 LambdaQueryWrapper,分页插件也内置好,做毕设的效率高非常多。需要注意的是,不要让 MyBatis-Plus 成为你的盲区。答辩时老师很可能问“MyBatis 的动态 SQL 你会不会写”,这部分基础还是要补一补。

鉴权方案是另一个容易纠结的点。Spring Security 功能强大但学习曲线陡峭,对毕设来说很容易陷入配置地狱。实际带项目的过程中,我一般推荐两条路线:如果你对框架比较熟,用 Sa-Token,它把登录、踢人下线、权限注解都封装得很简洁,集成的代码量小,源码也不难读;如果你想在答辩时多讲一点底层原理,就手写 JWT + 拦截器,整个鉴权链路差不多一两百行代码就能讲清楚。两种方案都比 Spring Security 更适合“毕设交付”这个场景。

2.2 前端选型:Thymeleaf 还是 Vue,取决于你的剩余时间

前端部分到底用服务端渲染还是前后端分离,本质上是时间预算问题。我列个表,你直接对号入座:

方案优点缺点适合人群
Thymeleaf + Bootstrap不用处理跨域,项目结构简单,部署只打一个 jar页面交互体验一般,前端展示效果不够“现代化”时间紧张,后端基础一般,求稳能跑通
Vue3 + Element Plus(前后端分离)页面美观,交互流畅,答辩演示效果好需要处理跨域、Token 存储、前端打包,难度和工时都增加有前端基础,想冲高分,愿意多花时间
原生 HTML + jQuery简单直接代码混乱,后期维护困难,不推荐几乎无前端基础,临时应付

我自己带学生的时候通常建议:如果毕设周期在三个月以上,就顶住压力做 Vue + Element Plus 的前后端分离,学到的东西更多,简历上也更好写;如果只剩一个多月,老老实实用 Thymeleaf + Bootstrap,先把业务闭环跑通,前端展示用一套现成的后台管理模板,效果也不会差。

2.3 项目结构与版本依赖参考

无论选哪种前端方案,后端项目的目录结构都建议规范一些。我常用的分包方式是标准的三层架构加一个 config 包:

src/main/java/com/example/campusnews/ ├── config/ # 配置类:跨域、拦截器、MyBatis-Plus 分页插件 ├── controller/ # 控制层:接收请求、参数校验、返回 Result ├── service/ # 业务逻辑层:包括接口和实现类 ├── mapper/ # 数据访问层:MyBatis-Plus 的 Mapper 接口 ├── entity/ # 数据库实体类 ├── dto/ # 前端入参对象,用于接收请求参数 ├── vo/ # 视图对象,用于返回给前端的结构 ├── common/ # 通用类:Result、异常类、常量、枚举 └── util/ # 工具类:JWT 工具、日期工具等

版本方面,这里直接给一套我验证过的组合:JDK 8 或 11 + Spring Boot 2.7.x + MyBatis-Plus 3.5.x + MySQL 8.0。如果学校要求 JDK 17,可以上 Spring Boot 3.x,但要注意 3.x 里 javax 包名变成了 jakarta,有些老教程里的代码需要改 import。能用 2.7 就用 2.7,省掉这些兼容问题。集成测试时你会发现这套组合非常成熟,网上基本能搜到所有踩坑记录。

3. 数据库设计:五张核心表撑起整个系统

3.1 核心表结构说明

数据库设计是这个项目的地基,很多同学一上来就建表,结果字段名不规范、类型选错,后面写代码全是坑。校园新闻管理系统正常情况只需要五张核心表:系统用户表、新闻分类表、新闻信息表、评论表和点赞表。如果还想要操作日志、消息通知这类功能,再加表也不迟,但最核心的业务五张表就够了。

先明确一下每张表的关键职责。用户表除了登录认证字段,还要有角色字段和状态字段;新闻表承担的是最重的业务逻辑,除了标题、正文、封面图这些内容字段,一定要设计好分类外键、作者外键和状态字段;评论表通过新闻外键和用户外键关联内容,父评论 ID 字段用于支持楼层回复;点赞表的结构非常简单,核心是建一个联合唯一索引防止重复点赞。

3.2 建表 SQL 与字段设计要点

下面是核心表的建表 SQL,我精简了主要字段,你直接拿去改成自己项目的表名前缀就行:

-- 用户表 CREATE TABLE `sys_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码(BCrypt)', `nickname` varchar(50) DEFAULT NULL COMMENT '昵称', `avatar` varchar(255) DEFAULT NULL COMMENT '头像地址', `role` tinyint NOT NULL DEFAULT '1' COMMENT '角色 1普通 2编辑 3管理员', `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态 1正常 0禁用', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';
-- 新闻表 CREATE TABLE `news` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '新闻ID', `category_id` bigint NOT NULL COMMENT '分类ID', `title` varchar(100) NOT NULL COMMENT '新闻标题', `summary` varchar(255) DEFAULT NULL COMMENT '摘要', `content` longtext COMMENT '正文内容', `cover_image` varchar(255) DEFAULT NULL COMMENT '封面图', `author_id` bigint NOT NULL COMMENT '作者ID', `author_name` varchar(50) DEFAULT NULL COMMENT '作者昵称(冗余)', `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态 0草稿 1待审核 2已发布 3已下架', `view_count` int NOT NULL DEFAULT '0' COMMENT '浏览量', `like_count` int NOT NULL DEFAULT '0' COMMENT '点赞数', `comment_count` int NOT NULL DEFAULT '0' COMMENT '评论数', `is_top` tinyint NOT NULL DEFAULT '0' COMMENT '是否置顶', `publish_time` datetime DEFAULT NULL COMMENT '发布时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_category` (`category_id`), KEY `idx_status_publish` (`status`, `publish_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='新闻信息表';

这里有几个很关键的细节。第一,content 字段用 longtext,新闻正文如果是富文本,长度可能会比较长,varchar 撑不住。第二,status 字段是整个系统的状态机核心,建议用 tinyint 加注释,代码里再定义一个枚举类对应,避免全项目到处写魔法数字。第三,作者昵称是冗余字段,因为用户表里可能会改昵称,新闻列表页直接用 news 表里的 author_name 就能显示,不需要每次 JOIN 用户表,性能更好,即使用户改名也不会影响历史新闻的显示。

点赞表和评论表也一并给出:

-- 评论表 CREATE TABLE `news_comment` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID', `news_id` bigint NOT NULL COMMENT '新闻ID', `user_id` bigint NOT NULL COMMENT '评论用户ID', `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父评论ID,0表示顶级评论', `content` varchar(500) NOT NULL COMMENT '评论内容', `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态 1正常 0删除', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_news` (`news_id`, `create_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='新闻评论表';
-- 点赞表 CREATE TABLE `news_like` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '点赞ID', `news_id` bigint NOT NULL COMMENT '新闻ID', `user_id` bigint NOT NULL COMMENT '用户ID', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_news_user` (`news_id`, `user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='点赞表';

点赞表的联合唯一索引 uk_news_user 是最关键的设计,它是防重复点赞的最终兜底。哪怕你的代码里并发判断出了纰漏,数据库这一层也会把重复插入直接拦截掉,只需要在业务代码里捕获 DuplicateKeyException 然后返回“您已经点过赞了”即可。

3.3 冗余字段、逻辑外键与自动填充

写清楚了 SQL 再聊聊设计心得。第一,我设计的表基本都不加物理外键。外键看似能保证数据完整性,但实际开发里它会带来很多麻烦:删除新闻时要先删评论,删除分类时要处理关联新闻,测试数据清理起来非常痛苦。我更推荐用逻辑外键,也就是只保留关联字段,加上普通索引,在代码里保证引用的正确性。这更贴近企业里的实际开发习惯。

第二,create_time 和 update_time 这种公共字段,不需要在每一处代码里手动 set。MyBatis-Plus 提供了 MetaObjectHandler 自动填充机制,只需要在实体类字段上加 @TableField(fill = FieldFill.INSERT) 注解,然后写一个处理器统一填充创建时间和更新时间。另外,表名我用的是小写下划线,实体类用驼峰命名,配置 mybatis-plus 的 map-underscore-to-camel-case 默认开启即可自动映射。做项目时最好一开始就把这些公共约定定好,避免后面切库或者换人接手时一地鸡毛。

4. 后端实现:从登录认证到新闻状态机的完整落地

4.1 统一返回体与全局异常处理

后端代码的第一个基础设施,是统一返回体 Result 类。它的作用是把成功、失败、未登录、无权限等各种情况包装成固定结构,前端处理起来才不用东猜西猜。下面是我常用的模板:

@Data public class Result<T> { private Integer code; // 200成功 401未登录 403无权限 500异常 private String message; private T data; public static <T> Result<T> ok(T data) { Result<T> r = new Result<>(); r.code = 200; r.message = "操作成功"; r.data = data; return r; } public static <T> Result<T> fail(Integer code, String message) { Result<T> r = new Result<>(); r.code = code; r.message = message; return r; } }

配合 Result 类,一定要写全局异常处理。用 @RestControllerAdvice 捕获业务异常、参数校验异常和兜底异常,否则一旦代码抛了 NPE,前端看到的就是整页又长又难看的报错信息。业务异常建议定义一个 BizException,Service 层判断不合法时直接 throw new BizException("新闻不存在"),全局处理器负责把 message 转成 Result 返回。这样一个约定下来,后面写所有接口都会快很多。

4.2 登录认证与接口权限控制

登录认证这一块,如果你选择手写 JWT,核心流程是这样的:用户登录成功后,用用户 ID、角色和过期时间生成 token 返回给前端;前端后续请求在请求头里带上 Authorization: Bearer token;后端写一个拦截器,对需要认证的接口先解析 token,再把用户信息放到 ThreadLocal 里供后续使用。这个方案核心代码量不大,关键是拦截器注册和放行路径要配置清楚。

如果你用 Sa-Token,代码就更简洁了:

@PostMapping("/login") public Result<String> login(@RequestBody LoginDTO dto) { User user = userService.findByUsername(dto.getUsername()); if (user == null || !BCrypt.matches(dto.getPassword(), user.getPassword())) { return Result.fail(500, "用户名或密码错误"); } if (user.getStatus() == 0) { return Result.fail(500, "账号已被禁用"); } StpUtil.login(user.getId()); // 把角色写入 Sa-Token 的权限体系 StpUtil.getSession().set("role", user.getRole()); return Result.ok(StpUtil.getTokenValue()); }

接口权限控制建议按角色严格区分。后台管理相关的接口全部要管理员角色,用户中心相关的接口要登录才能访问,新闻浏览接口直接放行。前端再配合按钮级隐藏,普通用户即使猜到后台 URL,后端也会拦下来。这是答辩时最容易被追问的点,你哪怕实现得很简单,也要把这条链路讲清楚。

4.3 新闻审核状态机的关键代码

新闻审核是整个项目里最有业务深度的部分,也是我把前面数据库状态字段落到实处的关键。新闻状态定义为:0 草稿、1 待审核、2 已发布、3 已下架。编辑保存新闻时为草稿,点击提交后变成待审核;管理员在待审核列表中点击通过变成已发布,点击驳回则回到草稿或标记为已驳回;已发布的新闻可以下架,下架后可以重新发布,也可以修改后再次走审核流程。

审核接口的实现核心在于状态校验,不能把“任何状态”都允许切换到“任何状态”:

@Transactional(rollbackFor = Exception.class) public void audit(Long newsId, Integer pass) { News news = newsMapper.selectById(newsId); if (news == null) { throw new BizException("新闻不存在"); } if (news.getStatus() != NewsStatus.PENDING.getCode()) { throw new BizException("当前状态不可审核,请刷新后重试"); } if (pass == 1) { news.setStatus(NewsStatus.PUBLISHED.getCode()); news.setPublishTime(LocalDateTime.now()); } else { news.setStatus(NewsStatus.DRAFT.getCode()); } newsMapper.updateById(news); }

这里有两个细节值得写进论文:一是 setPublishTime 只在审核通过时赋值,不要用数据库的默认时间,否则草稿期就把发布时间写进去了;二是接口必须加 @Transactional 事务注解,状态更新是单表 update 虽然简单,但养成事务习惯对后面做多表操作非常重要。

4.4 点赞防重、评论列表和浏览量统计的实现细节

点赞接口是防重设计的最佳练兵场。完整实现分三步:先通过 uk_news_user 联合唯一索引判断记录是否存在,不存在就插入,同时给新闻表的 like_count 加一;如果插入时抛出 DuplicateKeyException,说明并发情况下重复点了,直接捕获异常返回提示。还要考虑一个边界情况:用户点了赞之后能不能取消?这个完全看你设计需求,如果要支持取消点赞,删除 news_like 记录并给 like_count 减一即可。这里不能直接 update news 表里的 like_count,而是应该用 update news set like_count = like_count + 1,避免先查后改的并发覆盖问题。

评论列表查询时,我建议前端详情页直接拉两级结构:顶级评论按时间排序,每条新闻最多显示前几页,回复评论通过 parent_id 关联。列表查询用一个 JOIN 把评论用户头像和昵称带出来,避免在循环里一条条查用户表,这种 N+1 查询是新手最容易犯的性能错误。浏览量统计在这个量级的项目中不需要额外引入中间件,详情页打开时执行一条 update news set view_count = view_count + 1 就足够了,配合置顶状态和发布时间做列表排序,业务上很够用。

5. 前端页面与交互落地:从首页展示到后台管理

5.1 前台首页和新闻详情页的关键处理

前台首页是整个系统的门面,信息架构上一般分四大块:顶部导航栏(分类菜单 + 搜索框)、轮播推荐区(置顶新闻或重点新闻)、分类新闻列表(按栏目展示最新几条)、热门排行(按浏览量排序)。用 Thymeleaf 做的时候,可以直接在 Controller 里查好数据塞进 Model,然后通过 thymeleaf 的 each 循环渲染;用 Vue 分离做的时候,就定义好几个接口返回 JSON,前端按接口拼数据。

新闻详情页是整个系统里接口最集中的一个页面。进入详情页时要调用详情接口,返回新闻正文、作者信息、浏览量;正文渲染时最需要注意的是 XSS 安全问题,如果是富文本编辑器上传的内容,后端必须对 script 标签做过滤,可以引入 jsoup 设置白名单,只保留 p、img、h2、h3 这类安全标签。点赞按钮和评论列表的加载都要基于登录状态做判断,未登录用户点击点赞应该提示“请先登录”,评论框也不要展示成可输入状态。

5.2 后台管理界面的布局与状态联动

后台管理前端可以直接用一套现成的模板,比如 AdminLTE 或者自己写个简单的侧边栏加内容区布局。左侧放菜单:仪表盘、新闻管理、审核管理、分类管理、用户管理。右侧内容区用表格展示数据,每一个业务操作按钮都要和新闻的状态联动:待审核的新闻显示“通过/驳回”按钮;已发布的显示“下架”;已下架的显示“重新发布”;草稿状态的显示“编辑/提交审核”。这个“按钮跟着状态走”的逻辑,比把所有按钮都堆上去要合理得多,答辩演示的时候观感会好很多。

如果你做前后端分离,联调时有两个地方容易卡壳:跨域和 Token。跨域在开发环境可以通过 Vue CLI 的 devServer proxy 代理解决,后端加一个 CORS 配置类也行,但上线后还是建议用 Nginx 做反向代理,把 /api 路径转发到后端服务,这样浏览器里就只有一个同源地址,不会出跨域问题。Token 的存储一般放 localStorage,请求拦截器里统一带 Authorization 头,遇到 401 状态码就跳转登录页。

5.3 站内搜索、富文本编辑器和图片上传的坑

站内搜索最简单可靠的实现是 SQL like 加 concat 拼接,查标题、摘要、正文三个字段,然后用发布时间倒序。查询的关键是判断关键字是否为空,以及用 #{} 占位符防 SQL 注入。对于毕设来说 MySQL 的 like 已经足够,真到了数据量大那一天,再考虑 Elasticsearch 也不迟。如果你想让性能好看一点,可以给新闻表的 title 字段建一个普通索引,并解释一下“前置通配符会导致索引失效”这个面试点。

富文本编辑器我推荐 wangEditor 或者类似的开源编辑器,轻量且文档齐全。这里最大的坑是图片上传。编辑器里粘贴的图片,如果直接以 base64 形式存进长文本,一条新闻的 content 能上几万字符,数据库压力很大,页面加载也会变慢。正确做法是单独写一个文件上传接口,前端编辑器配置好图片上传回调,上传成功后将服务器返回的图片 URL 插入到正文中。项目里静态资源文件路径要单独配置,一般放在本机某个目录,或部署时用 Nginx 映射到一个 /uploads 路径。

6. 本地运行、服务器部署与答辩准备

6.1 从零把项目跑起来

你拿到这套系统之后,最优先的任务是把它在本地跑起来。准备工作就四步:安装 JDK、Maven、MySQL 和 IDE。JDK 版本按你项目实际用的来,如果 Spring Boot 2.7 用 JDK 8 就行。MySQL 建议 8.0 以上,在数据库中执行建表脚本,把五张核心表建好,顺便插入初始化数据——比如设置一个管理员账号、几个新闻分类、三五条演示新闻、一些测试评论,切到后台页面时就不用现场编数据了。

接着修改 application.yml 里边的数据库连接:地址、账号、密码,连接串记得带上 useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai,不然会出现中文乱码和日期时区报错。启动主类,浏览器访问 8080 端口,能进首页基本就成功了。整个过程中如果遇到端口被占用,改一下 server.port 即可,这个问题在答辩现场的电脑上经常出现,提前弄清楚怎么换端口很重要。

6.2 打包部署到服务器的简化方案

本地跑通之后,如果想让老师通过公网或者校园网访问,就需要部署。简化方案是打包成 jar 文件,然后放到一台装有 JDK 的服务器上运行。打包这里用 Maven 命令就可以:

mvn clean package -DskipTests

打包完成后,target 目录下会生成一个 jar 文件,把它上传到服务器,执行下面的命令就能后台启动:

nohup java -jar campus-news-0.0.1.jar > app.log 2>&1 &

第一次访问服务器时,记得确认服务器安全组或防火墙放行了对应端口。更稳妥的做法是在 jar 前面加一层 Nginx,Nginx 监听 80 端口,把请求代理到本机 8080 端口,同时把 /uploads 静态目录也交给 Nginx 管理。这样的部署架构虽然简单,但已经很接近真实企业项目的形态了,写进论文里是加分项。

6.3 把这个项目变成面试和答辩素材的方法

项目做完了,剩下的就是“讲故事”。我平时跟学生强调最多的一个观点是:你做的每一个功能,都要能回答“为什么”三个字。比如 Spring Boot 为什么能简化开发?因为它约定大于配置、自动装配、内嵌容器。新闻列表的分页查询用了什么?MyBatis-Plus 分页插件底层就是拦截器加 SQL 改写。登录为什么用 JWT?因为它无状态、适合前后端分离场景。这些概念就是 Java 面试里常见的基础问题,你把它们和这个项目绑定在一起记忆,面试时就不是背八股文,而是讲真实经历。

答辩高频追问我也提前给你梳理几个方向:正文富文本如何防 XSS、点赞防重怎么保证并发安全、浏览量一小时内被刷一万次怎么办、用户越权访问后台接口如何拦截。针对这些问题,你只要把安全过滤、唯一索引、事务回滚、角色校验这几个关键词准备好,再结合代码回答,基本都能过关。很多同学觉得八股文和做项目是两回事,其实做完这个项目你就会发现,八股文里讲的概念几乎全都能在项目里找到实例。

7. 常见问题排查:启动、数据访问和业务逻辑的 12 个坑

7.1 启动失败类问题

症状可能原因解决办法
启动报端口被占用8080 端口被其他程序使用改 server.port,或找到占用进程杀掉
启动报 Access denied for user数据库账号密码错误检查 application.yml 的账号和权限
启动报 Unknown database数据库没有创建,或库名不匹配先执行 CREATE DATABASE,再确认连接串库名
启动报时区错误MySQL 连接 URL 缺少时区参数连接串加 serverTimezone=Asia/Shanghai
Maven 依赖下载缓慢或者报红默认中央仓库访问慢配置阿里云镜像仓库,重新导入依赖

7.2 数据访问类问题

Mapper 接口已经写了,启动却报找不到扫描对象,一般是没加 @MapperScan 或者没在接口上加 @Mapper 注解。MyBatis-Plus 写了分页查询但分页不生效,这是最容易漏掉的一环——新版 MyBatis-Plus 分页必须配置 PaginationInnerInterceptor 插件,不配置的话你的 Page 参数会被当成普通条件。中文乱码问题的根源通常有两个:数据库连接 URL 没加 characterEncoding,或者数据库表本身建成了 latin1 字符集。顺手检查一遍这三处,数据访问的坑基本都能解决。

7.3 业务逻辑类问题

点赞接口第一次点成功,第二次还能点,检查一下点赞表的唯一索引有没有真的建上,代码里先查再插和唯一索引必须两个都做。评论删除后新闻的评论数不变,因为你的删除逻辑只删了评论记录,没有去更新 news 表的 comment_count,这个字段属于冗余计数,删除时必须同时处理。富文本编辑器上传的图片在新闻详情页打不开,大概率是图片上传保存的是本地绝对路径,详情页访问时 Nginx 或者静态资源映射没配置对应目录,后台管理界面里通过相对路径访问一次就能验证。

7.4 安全与细节问题

安全方面的坑,每个都值得单独强调。密码一定不要明文存库,用 BCrypt 加密,这个没有例外。SQL 写法的原则是能用 #{} 就不要用 ${},前者是预编译占位符,后者是字符串拼接,后者有 SQL 注入风险。富文本内容上传到数据库之前听过一遍 XSS 过滤,尤其是 script 标签和 onerror 事件。后台管理接口要有角色校验,哪怕前端已经隐藏了管理入口,后端接口没有鉴权一样会被 URL 扫描器发现。最后提醒一个小细节:错误提示不要太详细,不然等于把系统内部结构告诉了攻击者,生产环境里异常信息统一返回“系统繁忙,请稍后重试”就够了。

这个项目我前后陪着很多学生完整做过,最大的感受是:真正让你和普通 CRUD 项目拉开差距的,从来不是用了多冷门的技术,而是你把需求分析做到多细、把状态流转做得多严谨、把防重和权限设计想得多全面。最后分享一个答辩实用技巧:开场不要急着打开系统点来点去,先花三分钟把业务闭环讲清楚——谁投稿、谁审核、谁消费、数据如何回流——然后再演示对应功能。评委听到你有清晰的业务设计思路,再看代码里状态机、唯一索引、统一异常处理这些都落到了实处,分数自然就上去了。你做完这套系统之后,后续可以试着把新闻分类扩展成多级栏目,或者给编辑加一个个人投稿数据看板,这个项目还能延伸出很多有趣的方向。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 4:25:03

LLM生成CUDA算子双轨拦截:静态检查与动态校验实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 4:24:55

欧姆龙CP1H脉冲控制程序解析与工业自动化应用

1. 欧姆龙CP1H脉冲控制程序的价值重现十年前编写的欧姆龙CP1H脉冲控制程序&#xff0c;如今看来依然散发着工业自动化领域的经典光芒。作为日系PLC的代表作之一&#xff0c;CP1H系列凭借其稳定的脉冲输出性能和友好的编程环境&#xff0c;在小型运动控制领域建立了持久的口碑。…

作者头像 李华
网站建设 2026/9/15 4:22:23

GPS星历解析与卫星位置计算:从参数到ECEF坐标的完整实现

简介&#xff1a;本资源是一份面向卫星导航算法学习者与MATLAB初学者的轻量级GPS星历解析与卫星位置计算实践代码&#xff0c;聚焦于理解星历数据结构、坐标系转换及定位基础原理。资源核心为1个MATLAB脚本文件&#xff08;GPS.m&#xff09;&#xff0c;完整实现星历数据解码、…

作者头像 李华
网站建设 2026/9/15 4:21:38

HFSS端口激励报错“faces must lie on same plane”的排查与修复技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 4:21:09

Vue+ECharts高校打卡数据可视化大屏实战解析

前阵子接了一个挺典型的校园需求&#xff1a;教学楼大厅要放一块大屏&#xff0c;把全校学生每天早晚打卡的数据实时滚动出来。领导的要求很直接——“要好看、要直观、不能像Excel表格”。这句话基本就给这个项目定了调子&#xff1a;前端数据可视化大屏&#xff0c;技术栈顺着…

作者头像 李华
网站建设 2026/9/15 4:21:00

北京二手房房价预测:从Scrapy爬虫到随机森林的完整实现

简介&#xff1a;一套基于机器学习实现的房价与二手房价格预测综合项目&#xff0c;适合计算机相关专业学生用作大作业、课程设计或毕业设计参考。项目已经过导师指导与评审&#xff0c;获得98分的高分&#xff0c;全部源码均在本地编译并调试通过&#xff0c;确保可运行。资源…

作者头像 李华