ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring Boot新闻分类系统全解析:从表设计到功能实现

2026/9/7 22:55:09 拓冰建站 浏览量
Spring Boot新闻分类系统全解析:从表设计到功能实现 新闻分类系统光听名字就知道是毕设里的常青树。我前后经手过好几个类似选题的源码这套编号 31188 的 Spring Boot 新闻分类系统是我认为结构最规整、扩展起来最舒服的一套。它不是什么花哨的大项目但 Spring Boot MyBatis 这一条主线上该有的东西全都齐了分类管理、新闻发布、列表分页、关键字搜索、登录拦截、文件上传甚至后台管理和前台展示都分得清清楚楚。对准备做 Java 毕设、想搞懂 Spring Boot 项目到底是怎么串起来的人来说这套源码比看十篇零散的教程都管用。它解决的实际问题很明确把杂乱的新闻内容按照分类组织起来让用户能按类别浏览、按关键词检索让管理员能统一维护新闻和分类信息。这个场景不管在校招项目、课程设计还是毕业设计里出现频率都很高因为它的业务逻辑足够完整却又不至于复杂到一个人做不完。网上问得最多的“springboot 项目怎么做”“springboot 框架介绍”“springboot vue 前后端分离”这些问题拿这套源码对应的技术栈去回答基本能覆盖大半。我写这篇东西的目的很实在把这套 Spring Boot 新闻分类系统的设计思路、表结构、关键代码、实际踩过的坑以及答辩时容易被抓着问的点全部摊开讲清楚。不管你是打算直接参考这套源码还是想自己从零写一个类似的系统都能从里面找到可以直接抄作业的部分。1. 项目定位与整体设计思路1.1 新闻分类系统到底在做什么很多同学拿到选题第一反应是“新闻分类系统不就是 CRUD 吗”这个说法对了一半。它确实绕不开增删改查但真正的难点不在 CRUD 本身在于把业务规则理顺。新闻分类系统里有几个核心角色普通访客、登录用户、管理员。访客能看到前台的新闻列表、分类导航、新闻详情登录用户在前台基础上还能做评论或者收藏这套源码里主要做了浏览和检索扩展空间很大管理员进后台维护分类和新闻。整个系统的数据流转也不复杂管理员先创建新闻分类比如“科技”“体育”“财经”“娱乐”然后在某个分类下发布新闻新闻包含标题、作者、封面图、正文、发布时间、状态这些字段。前台页面按分类展示新闻列表用户点击进入详情也能通过搜索框按标题关键字查新闻。后台的管理页面则提供分类的新增修改删除、新闻的发布编辑上下架以及分页列表展示。从这个流程可以看出它本质上是一个典型的内容管理类系统。你把它换成“博客系统”“公告系统”“资讯管理系统”表结构和业务代码至少能复用七成。所以做完这一套后面遇到同类型选题基本就是改字段的事。1.2 技术栈选型的权衡为什么是 Spring Boot MyBatis这套源码的技术栈是 Spring Boot 2.7.x MyBatis MySQL前端使用的是 Thymeleaf 模板引擎加 Bootstrap如果是前后端分离的版本则换成 Vue。这个选型放在毕业设计的场景里非常合理原因有三个。第一Spring Boot 是目前 Java 后端开发的事实标准。网上搜“springboot 配置”“springboot 框架介绍”“springboot 项目”这些关键词资料饱和度极高遇到问题很容易找到解决方案。对基础一般的同学来说生态完善意味着容错率高卡住了不至于寸步难行。第二MyBatis 上手门槛比 JPA 低SQL 是自己写的能清楚地看到每条查询怎么执行。这一点在答辩时非常加分因为老师问“你的查询怎么实现的”你直接把 Mapper XML 里的 SQL 拿出来讲就行。用 JPA 反而容易陷入“框架帮我做了什么”的解释困境。MyBatis 的半自动特性让你对 SQL 有绝对掌控力这在查分类统计、分页、模糊搜索这类需求时特别直观。第三Spring Boot 的自动配置特性让项目搭建成本极低。不用像 SSM 时代那样写一大堆 XML 配置依赖一引、配置一写、启动类一跑项目就起来了。配合 Lombok 省掉 getter/setter开发效率能提升一大截。选型时还有个细节值得注意Spring Boot 版本不要追新。热搜词里总有“springboot 版本太高”这类问题确实我在实际项目里也遇到过Spring Boot 3.x 强制要求 JDK 17很多老教材和老依赖在新版本下会报错。这套源码选的 2.7.x 搭配 JDK 8 是兼容性最好的组合任何教程、任何中间件基本都能匹配上不折腾。1.3 项目模块划分与代码结构我拿到一套源码习惯先看包结构包结构清晰的项目代码质量通常不会差。这套源码的标准包结构如下com.news.system ├── controller # 控制层接收请求、返回视图或JSON ├── service # 业务层处理业务逻辑 │ └── impl # 业务实现类 ├── mapper # MyBatis Mapper接口 ├── entity # 实体类对应数据库表 ├── common # 通用工具、常量、统一返回结果 ├── config # 配置类拦截器、静态资源映射等 └── NewsSystemApplication.java # 启动类这个分层结构对应的是经典的“三层架构”Controller 负责接收参数和返回结果Service 负责业务规则Mapper 负责数据库操作。它最大的好处是职责单一出了问题能快速定位。比如分页查新闻列表出错了先看 Controller 传入的参数对不对再看 Service 里有没有处理分页逻辑最后看 Mapper XML 里的 SQL 是不是写错了。项目启动类一定要放在最外层包下这样 Spring Boot 的组件扫描才能覆盖到所有子包。很多新手把启动类放错位置结果全是一堆Autowired注入失败的报错。另外 common 包里建议放一个统一返回结果类比如ResultT封装 code、msg、data 三个字段前台和后台的接口都返回这个结构前后端联调时就不容易出现“数据结构对不上”的问题。2. 数据库设计与核心业务逻辑2.1 数据表设计从分类到文章的字段规划数据库设计是一套毕设源码的灵魂表结构合理后面的代码写起来就顺风顺水。这套新闻分类系统的核心表主要有三张新闻分类表、新闻信息表、用户表另外视功能扩展情况可能还有评论表。新闻分类表是整套系统的基石字段不多但作用关键字段名类型说明idbigint主键自增category_namevarchar(50)分类名称category_codevarchar(50)分类编码唯一sort_orderint排序号越小越靠前statustinyint状态0停用 1启用create_timedatetime创建时间update_timedatetime更新时间新闻信息表是内容主体字段要覆盖标题、来源、作者、封面图、摘要、正文、所属分类、浏览量、状态、发布时间等。字段名类型说明idbigint主键category_idbigint所属分类ID关联分类表titlevarchar(200)新闻标题summaryvarchar(500)摘要authorvarchar(50)作者cover_imagevarchar(255)封面图URLcontenttext正文内容view_countint浏览量statustinyint0草稿 1发布 2下架create_timedatetime创建时间publish_timedatetime发布时间用户表根据需求可繁可简最基本的就是 id、username、password、nickname、role、status、create_time。密码字段要注意存的是加密后的密文绝不能存明文。这里有一个表设计上的关键决策分类到底做单级还是树形这套源码做的是单级分类也就是所有分类平级。如果要做多级分类比如“科技”下面有“互联网”“AI”“硬件”那么需要在分类表里加一个 parent_id 字段改成树形结构。毕设场景下单级分类足够而且前后端展示都简单不建议一上来就做无限级分类容易把自己绕进去。扩展成两级分类是性价比最高的方案加一个 parent_id 就行三级以上就要考虑递归查询效率了。2.2 分类管理的实现思路分类管理是这套系统里第一个完整的业务闭环实现逻辑非常适合作为理解整个项目的切入口。管理员的分类管理页面会展示一张分类列表每条分类都有“编辑”“删除”按钮顶部有“新增分类”按钮。这个功能的流程是Controller 接收请求调用 Service 层的分类服务Mapper 执行 SQL数据通过 Thymeleaf 或 JSON 返回到页面。分类管理的核心难点不在 CRUD而在两个细节上。第一个是查分类下有多少篇新闻这个信息能帮管理员判断分类能不能删。实现这句统计 SQL 很直接SELECT c.id, c.category_name, COUNT(a.id) AS news_count FROM news_category c LEFT JOIN news_article a ON c.id a.category_id GROUP BY c.id, c.category_name ORDER BY c.sort_order ASC;这里用 LEFT JOIN 而不是 INNER JOIN是为了把那些“还没有新闻的分类”也查出来新闻数量显示为 0 而不是直接不出现。删除分类时也要先判断下面的新闻数量分类下有新闻时应该提示管理员先转移或删除新闻否则数据就会变成悬空状态前端拿到一个找不到分类名的 category_id页面就容易显示异常。第二个细节是唯一性校验。分类名称和分类编码都不能重复Controller 层在新增和修改时都要做查重否则数据库里出现两个“体育”分类前台导航栏就会很奇怪。查重的 SQL 也简单WHERE category_name #{name}或者WHERE category_code #{code}查到记录就返回“分类已存在”。2.3 新闻列表与分页查询的常见坑新闻列表是前台用户看到最多的页面也是最容易出问题的地方。列表页一般有几个筛选条件分类 ID、标题关键字、状态后台用然后按发布时间倒序排列。组合条件一多SQL 动态拼接就成了不可避免的事。MyBatis 的if标签在动态 SQL 里用得极多一个标准的组合查询是这样写的select idselectNewsList resultTypecom.news.system.entity.NewsArticle SELECT * FROM news_article where if testcategoryId ! null and categoryId ! AND category_id #{categoryId} /if if testtitle ! null and title ! AND title LIKE CONCAT(%, #{title}, %) /if if teststatus ! null AND status #{status} /if /where ORDER BY publish_time DESC LIMIT #{offset}, #{pageSize} /select这里的where标签很聪明它会自动处理掉第一个条件的 AND 前缀不用手动加WHERE 11。模糊查询要用CONCAT(%, #{title}, %)而不是直接在参数里拼%这样做能避免 SQL 注入风险。分页这块我强烈建议初学者先手工分页LIMIT #{offset}, #{pageSize}配合计算offset (current - 1) * size逻辑清清楚楚。PageHelper 这类分页插件虽然方便但它基于拦截器改 SQL 的原理对新手来说太黑了翻车时很难排查。手工分页的代码写完你心里对分页机制的把握是扎实的。后面真要用 PageHelper再看官方文档也很快。分页接口返回的数据结构要包含四个核心信息当前页数据集合、总数、当前页码、每页条数。前端渲染时要用到总数来计算总页数用当前页码来高亮当前页和判断“上一页”“下一页”是否可点击。3. 关键功能实现与代码解析3.1 项目初始化与核心配置这套源码的初始化方式很标准通过 Spring Initializr 生成基础项目Maven 管理依赖。pom.xml 里最核心的依赖就是 Web 场景启动器和 MyBatis 启动器如果用 Thymeleaf 还要引入对应的 starter。一段典型的 pom 核心依赖如下parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies这里有个版本对应关系值得注意Spring Boot 2.7.x 使用的是 MySQL Connector/J 8.0.xdriver-class-name 要写com.mysql.cj.jdbc.Driver。网上老教程里的com.mysql.jdbc.Driver是 5.x 的老写法在新版本下会直接报错。驱动名称这个坑几乎每个用 MySQL 8 的人都会踩一次。application.yml 是 Spring Boot 项目里最重要的配置文件。数据源配置、MyBatis 配置、文件上传大小限制都在这里调整。核心配置如下server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/news_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.news.system.entity configuration: map-underscore-to-camel-case: true spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB数据库连接 URL 里的serverTimezoneAsia/Shanghai在 MySQL 8 下必须加否则会因为时区问题报错。useUnicodetruecharacterEncodingutf8负责告诉驱动用 UTF-8 编码传输中文数据。MyBatis 的map-underscore-to-camel-case配置是神器开启后数据库的 create_time 字段能自动映射到实体类的 createTime 属性省掉一大堆手动映射。3.2 基于MyBatis的持久层实现前面的配置把环境搭好了接下来就是 Mapper 层的实现。Mapper 接口只是定义方法签名真正的 SQL 写在 resources/mapper 目录下的 XML 文件里。这个分离的设计让 SQL 修改不用动 Java 代码尤其是毕设后期改需求时改 XML 比改 Java 再重新编译要省事得多。以新闻详情查询为例前台点击一条新闻后要展示新闻的标题、内容、作者、发布时间同时要显示所属分类的名称。新闻表里只有 category_id分类名在分类表里这就需要联表查询select idselectNewsDetail resultTypemap SELECT a.*, c.category_name FROM news_article a LEFT JOIN news_category c ON a.category_id c.id WHERE a.id #{id} /select一次联表查询就把两个表的数据查回来了比先在新闻表查出 category_id再查一次分类表高效得多。这也是 MyBatis 和 JPA 在思维方式上的差异JPA 倾向于对象导航MyBatis 倾向于直接写 SQL 拿结果。浏览量自增这个细节容易被忽略。正确写法是发一条独立的 UPDATE 语句UPDATE news_article SET view_count view_count 1 WHERE id #{id}这条 SQL 是原子操作高并发下也不会丢更新。如果你先 SELECT 出来在 Java 里加 1 再 UPDATE并发请求下数据就会覆盖丢失。虽然毕设场景没什么高并发但这个写法上的好习惯最好一开始就养成。新增新闻时有一个需求是自动设置发布时间。这里推荐在 Java 代码里用LocalDateTime.now()直接赋值而不是依赖数据库的 DEFAULT CURRENT_TIMESTAMP。原因很简单如果你把 insert 语句里的 publish_time 字段省略Java 里没赋值那这条数据可能存了 NULL 进去前台排序就会出现没有时间的脏数据。显式赋值是最可控的方式也方便后期做定时发布之类的扩展。3.3 后台管理功能与登录拦截后台管理是系统的另一大块。管理员登录之后进入后台能看到仪表盘、分类管理、新闻管理、系统管理等菜单。这套源码的后台权限控制方式非常简单且实用登录成功后把用户信息放到 Session 里然后定义一个拦截器拦截/admin/**路径下的请求判断 Session 里有没有用户没有就重定向到登录页。拦截器的核心逻辑如下public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(/admin/login); return false; } return true; } }然后在配置类里注册这个拦截器并指定拦截路径和放行路径Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/admin/**) .excludePathPatterns(/admin/login, /admin/doLogin); } }这个方案简单到没有什么学习成本但足以应对毕设的权限需求。密码加密必须用 BCryptPasswordEncoder这是 Spring Security 自带的加密器比 MD5 可靠得多。MD5 加不加盐都是过了时的方案彩虹表一查一个准。教师问起来直接回答“用 BCrypt 加盐哈希存储密码即使数据库泄露也无法反推出明文”这句话说出来老师就知道你关注过安全问题。后台新闻管理页面还有一个高频操作用途是上传封面图。图片上传后要保存到服务器本地磁盘同时在数据库中存文件的访问 URL。这里面有一个 Spring Boot 新手必踩的坑上传的图片存在本地磁盘路径后默认是无法通过浏览器 URL 直接访问的。必须额外配置静态资源映射Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath); }addResourceHandler(/upload/**)表示浏览器访问 /upload/xxx.jpg 时Spring 会去file:指定的本地磁盘路径找文件。这个配置不做前端 img 标签的 src 就永远显示裂图。至于把图片传到云存储 OSS 之类的那是后话毕设阶段本地存储完全够用。3.4 前端页面与前后端交互前端部分这套源码有两种形态一种是服务端渲染的 Thymeleaf 版本一种是前后端分离的 Vue 版本。对毕设而言Thymeleaf Bootstrap 是最省事的组合页面直接用模板语法从后端拿数据不用考虑跨域不用 Mock 数据开发效率极高。前后端分离版本则要处理跨域配置、接口联调、Token 传递这些额外议题学习成本明显更高。热搜词里“springboot vue 前后端分离”出现频率很高如果你选择这个方案需要额外做好三件事。第一是配置跨域在 Spring Boot 里实现 CorsFilter 或实现 WebMvcConfigurer 的 addCorsMappings 方法允许前端开发服务器的 Origin 进行跨域访问。第二是统一返回 JSON 结构前端拿到{code: 200, data: {...}}后根据 code 判断成功还是失败这一步在 common 包里封装 Result 类就是为了这个。第三是接口鉴权前后端分离后登录态不适合用 Session 存需要改成 JWT 之类的 Token 方案前端每次请求在 Header 里带 Token后端用拦截器解析。我个人的建议是如果你是 Java 后端方向优先做 Thymeleaf 版本把精力集中在后端逻辑上答辩时也容易讲透彻。如果指导老师特别强调前后端分离那再上 Vue但要有额外的时间预期毕竟前端调试的坑不比后端少。前台的新闻列表页推荐加一个简单的搜索框。这个功能表面上是查标题关键字实际上一做出来整个系统的完整度立刻上来了。导航栏按分类展示是“分类浏览”搜索框是“站内检索”两个入口一组合用户找新闻的路径就闭环了。搜索接口就是前面那段where标签组合查询参数传 title 就行实现成本几乎为零但答辩演示时效果很好。4. 常见问题与排查技巧实录4.1 启动失败的典型原因我每次帮别人看毕设源码花时间最多的就是排查启动失败。Spring Boot 项目启动失败的报错一般分为三类端口被占用、数据库连接失败、依赖冲突。端口被占用是最常见的启动日志里出现Port 8080 was already in use就是它。解决办法要么杀掉占用进程要么在 application.yml 里改端口比如改成 8081。这里有个实用命令记录一下Windows 下netstat -ano | findstr 8080查 PID然后taskkill /F /PID 进程号杀掉Linux 或 macOS 下用lsof -i:8080和kill -9 PID。数据库连接失败的报错特征是Access denied for user rootlocalhost或者Unknown database news_system。前者是用户名或密码错了后者是数据库没创建或者名字没对上。排查思路很简单先用 Navicat 或命令行试试能不能用配置里的账号密码连上库。本地能连上项目肯定也能连上连不上基本就是配置里的用户名、密码、库名、端口这四个里有一个写错了。依赖冲突这个问题隐蔽一些典型表现是启动时 NoSuchMethodError 或 ClassNotFoundException。用 Maven 的话最常用的一条命令是mvn dependency:tree查看依赖树里有没有同一个 jar 的不同版本。Spring Boot 的 parent 已经管理了大部分依赖版本自己手动加依赖时不要再写 version 标签让 parent 统一管理。我在项目里见过有人手动指定了一个很老的 fastjson 版本结果和 Spring Boot 内置的 Jackson 在序列化时互相干扰数据输出直接乱套。4.2 Mapper 注入失败的排查Autowired报错可能是 Spring Boot MyBatis 项目里最让新手崩溃的问题。报错信息类似于Field newsMapper in com.news.system.service.impl.NewsServiceImpl required a bean of type com.news.system.mapper.NewsMapper that could not be found。这个报错绝大多数原因是 Mapper 接口没有注册到 Spring 容器里。解决办法有两种。第一种是在 Mapper 接口上直接加Mapper注解第二种是在启动类或者配置类上统一加MapperScan(com.news.system.mapper)。我推荐用MapperScan好处是新增 Mapper 时不用每个接口都手动加注解扫描范围一目了然。还有一种不太容易注意到的情况是 Mapper XML 里的 namespace 写错了。MyBatis 要求 namespace 必须是对应的 Mapper 接口的全限定名比如com.news.system.mapper.NewsMapper。如果 namespace 写成了别的即使接口注入成功真正执行 SQL 时也会报Invalid bound statement (not found)。这个报错一出现优先检查两件事检查 XML 文件是否在 mapper-locations 配置的目录下检查 namespace 和接口全限定名是否一字不差。4.3 中文乱码与时间格式问题中文乱码在后台新闻管理里特别常见尤其是通过表单提交新闻标题和正文时出现???或一堆乱码。产生原因通常是字符集在某个环节没有统一为 UTF-8。排查链路要从下往上捋数据库表字符集建议 utf8mb4、数据库连接 URL 里的 characterEncodingutf8、Spring Boot 本身的过滤器配置大多数情况下 spring-boot-starter-web 已经自动配置了 CharacterEncodingFilter。数据库表没有指定字符集的话在 MySQL 里执行建表语句时可以加上CREATE TABLE news_article ( ... ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci;如果已经建表了可以用 ALTER 语句修改。utf8mb4 是 utf8 的超集能存 emoji 和更多特殊字符做内容管理类系统建议直接用 utf8mb4。时间格式问题则集中在 JSON 返回给前端时LocalDateTime 序列化后变成一串数字或者显示格式难看。处理方法是在 application.yml 里配置spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8列表页的时间就会显示成2025-01-15 10:30:00这个可读性很高的格式。假如前端还要求展示“几分钟前”这类相对时间那是前端模板的活后端只管把标准时间传过去就行。4.4 安全与性能细节最后一个板块我想把安全性和性能这些容易被浮于表面的东西讲透一点。虽然毕设不会上生产环境但代码里体现出的意识是答辩评分的隐形分。SQL 注入的防范就是坚定使用#{}占位符不要用${}拼接参数。${}在大多数场景下都不该出现它唯一的合理用途是动态表名或动态排序字段而这些在毕设里几乎用不到。写 MyBatis 语句时但凡犹豫该用哪个选#{}永远没错。前端页面上的 XSS 问题也不能完全无视新闻正文如果允许直接输入 HTML用户提交的script标签可能会被浏览器执行。Thymeleaf 的th:text默认会做 HTML 转义比用th:utext安全得多。除非你明确知道自己在干什么否则展示用户输入内容时永远用th:text。性能方面最值得做的一件事是给查询频率高的表加索引。新闻列表的查询条件通常是分类 ID 和发布时间所以建立联合索引ALTER TABLE news_article ADD INDEX idx_category_time (category_id, publish_time);这个索引能让按分类浏览新闻的查询速度明显提升在新闻数据量稍大时效果更明显。索引的原理很简单相当于给数据建了目录查找时不用全表扫描。答辩时如果老师问“系统性能怎么优化”你能说出这个联合索引的设计思路比背一堆缓存理论实在得多。5. 从毕设源码到高分项目的进阶思路5.1 如何在答辩时把系统讲清楚很多同学功能做完了一到答辩就讲得稀里糊涂。我建议按照“项目背景、功能分解、表结构设计、核心流程、技术亮点、演示”这个顺序来讲。第一页展示系统截图时直接说“这是一个基于 Spring Boot 的新闻分类系统前台面向访客提供分类浏览和新闻检索后台面向管理员提供新闻和分类的维护”这句话就把定位定死了。讲技术时要主动抛出细节。比如讲到分页查询重点说清楚为什么要用 LIMIT offset 公式页码和条数是怎么算出来的。讲到登录拦截演示一下不登录直接访问后台地址会被重定向到登录页这个动作用截图展示出来说服力是很强的。讲到密码加密对比一下 MD5 和 BCrypt一句话就能体现深度。如果老师问 Spring Boot 的好处在哪不要背“自动配置、约定大于配置”这种概念。讲一个具体例子引入 spring-boot-starter-web 之后内嵌的 Tomcat 帮你把服务器问题解决了你直接写 Controller 就能跑起来而不用像 SSM 时代那样手动配置 Tomcat。概念加案例说服力完全不同。5.2 值得扩展的高价值功能这套系统的底子非常干净扩展空间很大而扩展功能正是把毕设从“及格”拉到“优秀”的关键。如果时间充裕我建议按优先级考虑下面几个方向。第一个是达到“集成中间件”的层次。引入 Redis 缓存分类列表减少每次访问前台都查数据库的压力这是一个很小但很典型的“缓存”技术体现。引入 Spring Task 做定时任务可以实现新闻定时发布比如设置凌晨 0 点自动发布某篇新闻这里是Scheduled注解加上一个定时扫描 SQL 就能实现。这两个扩展点都不算难但它们能在答辩时向老师证明你掌握的不只是 CRUD。第二个方向是做内容维度的增强。给新闻表加一个recommend字段实现“推荐新闻”功能加评论表实现用户评论功能用 ECharts 做一个后台分类统计图表展示每类新闻的数量占比。这些功能在业务上很自然加进去页面立刻显得丰满代码复杂度也完全可控。第三个方向是引入流程引擎比如热搜词里反复出现的 springboot 使用 flowable。如果你的毕设想再上一个台阶把新闻发布流程变成“编辑提交 - 主编审核 - 发布”这种带审批流转的状态机那可以引入 Flowable 或者 Activiti。但这里我给一个实在的建议流程引擎本身学习成本不低如果不是选题本身就和审批流程强相关不要硬上。把审核状态字段做成 status 的几档流转一样能讲清楚业务规则。最后再聊一个很多人忽视的事情一份合格的源码交付物不仅要能跑文档也要跟上。至少要有三份资料数据库初始化 SQL 脚本、项目部署说明、核心流程的文字说明。数据库脚本要用带CREATE DATABASE和USE的完整版别人拿到之后导入就能跑。部署说明要把 JDK、Maven、MySQL 的版本写清楚避免对方环境对不上。这三份东西不仅是为了让别人能跑通源码更是你梳理自己项目逻辑的过程。我见过不少同学源码写得还行但交上去缺这少那指导老师印象分直接打了折扣。这套新闻分类系统做下来我最大的体会是技术栈不在多而在真正理解每个选型为什么这么定。Spring Boot 负责把项目快速跑起来MyBatis 负责让 SQL 可控MySQL 负责把关系型数据存明白前端负责把内容呈现出来这一条链路本身就是一个完整的 Web 全栈认知闭环。把这套东西吃透往后看其他 Spring Boot 项目都会轻松很多。