尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

SpringBoot+MySQL新闻系统:从源码到部署的完整实战拆解

SpringBoot+MySQL新闻系统:从源码到部署的完整实战拆解 简介在Java后端开发中SpringBoot与MySQL组合是构建数据驱动型Web应用最经典的方案之一。SpringBoot通过自动配置与约定优于配置大幅简化项目启动流程MySQL则提供稳定可靠的关系型数据存储。二者结合形成从Controller控制层到Service业务层再到Mapper数据访问层的标准分层架构为开发者提供了清晰的职责边界与高效的开发体验。无论是用户登录鉴权、新闻增删改查还是分页排名、文件上传这类高频业务场景都依赖这套基础技术栈。理解其核心原理和工程实践有助于快速上手各类内容管理系统的开发。本文以一款基于SpringBootMySQL的新闻网站项目为例从数据库设计、核心代码实现到部署上线完整拆解项目落地的全过程并总结常见踩坑排查技巧帮助读者将理论转化为可运行的工程能力。基于SpringBootMySQL的新闻网站从源码到上线的完整拆解如果你正打算找一份能练手、能交作业、能写进简历的 Java Web 项目那“基于 SpringBootMySQL 的新闻网站”绝对是一个绕不开的经典选择。前阵子我刚好把一个新闻网站的源码和数据库完整过了一遍顺手做了不少改造和修复。这篇文章就把整个项目的结构、核心代码、数据库设计、部署经验以及我在实际踩坑后总结的排查思路一次性说清楚。这套项目属于典型的“小而全”案例SpringBoot 负责后端接口和数据业务逻辑MySQL 负责数据持久化前端用模板引擎或静态页面展示整套东西跑起来就是一个能浏览新闻、管理分类、维护用户信息的完整网站。对于刚学完 SpringBoot 基础、想通过项目夯实技能的人或者正在准备课程设计、毕业设计的人都特别合适。看完这篇文章你不仅能把它跑起来还能知道每一处代码背后的设计意图遇到问题也知道去哪里排查。另外再说一句这个项目虽然看起来简单但它包含了一套 Web 系统最常见的几个能力用户登录与权限控制、新闻增删改查、分页排行榜、文件上传新闻配图、分类管理等。这些能力放到任何企业级项目中都是高频场景把它们吃透比单纯背面试题有价值得多。1. 项目整体设计与技术选型1.1 为什么是 SpringBoot MySQL而不是其他组合先说说技术选型。很多初学者喜欢纠结“到底用 SSHSpringStrutsHibernate还是 SpringBoot”我的答案是除非你的课程大纲强制要求 SSH否则一律选 SpringBoot。原因很直接SpringBoot 内置了 Tomcat省去了一堆 XML 配置通过自动配置把“约定大于配置”贯彻到了极致。你用 Spring 写一个 Hello World 可能要配置 10 个文件用 SpringBoot 只需要一个类加一行注解。MySQL 更是没什么争议的选择。它是开源数据库里生态最成熟、资料最多、最容易上手的关系型数据库。对新闻网站这种以结构化数据为主、事务要求不算极端的场景MySQL 有着极高的性价比。配合 Navicat、DBeaver 这类图形化工具建表、导数据、调试 SQL 都非常方便。这套组合在市面上还有一个非常大的优势——学习成本低岗位需求量大。你去招聘网站搜一下“Java 工程师”十有八九要求熟悉 SpringBoot大部分要求熟悉 MySQL。所以做这个项目本质上就是在提前练习未来的工作技能。1.2 项目目录结构与分层思想我把这套新闻网站的源码目录结构整理了一下大致是这个样子src/main/java/com/news/ ├── NewsApplication.java // 启动类 ├── controller/ // 控制层接收请求 │ ├── LoginController.java │ ├── NewsController.java │ ├── CategoryController.java │ └── UserController.java ├── service/ // 业务层处理逻辑 │ ├── NewsService.java │ ├── UserService.java │ └── CategoryService.java ├── mapper/ // 数据访问层MyBatis-Plus │ ├── NewsMapper.java │ ├── UserMapper.java │ └── CategoryMapper.java ├── entity/ // 实体类 │ ├── News.java │ ├── User.java │ └── Category.java └── config/ // 配置类 └── WebConfig.java有些版本会多一层voView Object用来封装返回给前端的对象有些会把工具类放在utils包下这个按个人习惯来但核心的三层结构Controller → Service → Mapper一定要清晰。我见过不少新手把业务逻辑全写在 Controller 里一个方法几百行后面调试的时候想哭都哭不出来。分层的好处我用一句话概括Controller 只负责接收参数和返回结果Service 只负责业务逻辑Mapper 只负责和数据库打交道。每一层各司其职任何一层出问题都能快速定位。而且这个结构在企业开发中几乎就是标配你提前养成习惯对你将来的工作帮助很大。1.3 核心功能模块拆解以一个常规的新闻网站项目为例功能模块一般包含用户模块注册、登录、登出、修改密码新闻模块新闻列表、新闻详情、新闻发布、新闻编辑、新闻删除分类模块分类列表、分类管理前端页面首页、列表页、详情页、登录注册页、后台管理页听起来功能不多但你把每个模块拆开去看里面覆盖的点非常全面。比如新闻列表要支持分页分页就涉及到 SQL 的LIMIT语法新闻发布时间要排序这就涉及 MySQL 的ORDER BY新闻配图要上传这就涉及服务器文件存储和访问映射。这些全都是实战中天天要用的技能。所以我的建议是拿到这套项目之后不要只为了“跑起来”而跑而是按照模块逐个去读源码把每个模块对应的前端请求、后端接口、数据库操作串成一条线。这样做完一遍你对整个 Web 开发流程的理解会有一个质的提升。2. 数据库设计与核心表结构2.1 建表思路三张核心表搞定大部分需求数据库是这个项目的基础我先看数据库脚本。大多数新闻网站的表结构都包含三张核心表用户表、新闻表、分类表。如果是更完整一点的版本还会有评论表和收藏表。下面是我提取并整理过的建表 SQL以 MySQL 5.7 及以上版本为例CREATE DATABASE IF NOT EXISTS news_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE news_db; CREATE TABLE t_user ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码建议MD5加密存储, nickname varchar(50) DEFAULT NULL COMMENT 昵称, role tinyint(4) DEFAULT 1 COMMENT 角色1普通用户 2管理员, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; CREATE TABLE t_category ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 分类名称, sort int(11) DEFAULT 0 COMMENT 排序号, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT新闻分类表; CREATE TABLE t_news ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(200) NOT NULL COMMENT 新闻标题, content text COMMENT 新闻内容, image varchar(255) DEFAULT NULL COMMENT 封面图地址, category_id int(11) DEFAULT NULL COMMENT 分类ID, view_count int(11) DEFAULT 0 COMMENT 浏览量, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 发布时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), KEY idx_category_id (category_id), KEY idx_create_time (create_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT新闻表;2.2 表结构设计里的关键细节我在看这套项目的表结构时有几点细节值得拿出来说一说。第一是utf8mb4字符集。很多老教程喜欢用utf8但utf8在 MySQL 中并不是真正的“全部 UTF-8”它只能存储最多 3 个字节的字符。一旦新闻内容里出现生僻字或 emoji 表情就会报错或者变成乱码。现在统一用utf8mb4是标准做法它能完整覆盖 4 字节字符。尤其是新闻内容这块用户转发、复制粘贴内容时很容易带上特殊符号字符集不对就等着挨骂吧。第二是时间字段用datetime而不是varchar。有些偷懒的开发者会用字符串存时间看起来方便但后续做排序、范围查询、格式化输出的时候非常痛苦。数据库提供的datetime类型配合CURRENT_TIMESTAMP默认值能保证时间格式统一而且 SQL 里的排序和比较操作能直接使用原生能力效率更高。第三是索引的建立。新闻表里的category_id和create_time是两个高频查询字段按分类查新闻、按时间排序是新闻网站最常用的两个查询场景所以需要加索引。但注意不要每个字段都加索引索引过多会拖慢写入速度占用磁盘空间。索引这种东西够用就好。2.3 初始化数据让项目一启动就有内容可看很多时候你拿到源代码数据库是空的首页打开除了一个框架什么都没有那体验太糟糕了。我建议你把初始化数据一起导入。常用的做法是在resources目录下放一个data.sql或init.sql或者在 SpringBoot 配置里开启spring.sql.init.modealways让项目启动时自动执行。建完表后至少插入一个管理员账号和几篇测试新闻比如INSERT INTO t_user (username, password, nickname, role) VALUES (admin, e10adc3949ba59abbe56e057f20f883e, 管理员, 2); -- 密码为 123456 的 MD5 值 INSERT INTO t_category (name, sort) VALUES (科技, 1), (体育, 2), (财经, 3); INSERT INTO t_news (title, content, category_id, view_count) VALUES (SpringBoot 3.0 正式发布, 这是科技频道的一条测试新闻内容..., 1, 120), (本地足球队夺冠, 这是体育频道的一条测试新闻内容..., 2, 85);e10adc3949ba59abbe56e057f20f883e就是123456的 MD5 值这种预置数据能让登录功能“开箱即用”省去你先注册再登录的流程。3. 核心功能模块的代码实现解析3.1 用户登录与权限控制的完整流程用户登录是所有 Web 项目的“门面”也是面试中必问的内容。我看过的这份新闻网站源码里登录处理比较常规但不乏可圈可点之处。先看 Controller 层的代码结构Controller public class LoginController { Autowired private UserService userService; PostMapping(/login) public String login(String username, String password, HttpSession session, Model model) { User user userService.login(username, password); if (user ! null) { session.setAttribute(loginUser, user); return redirect:/news/list; } model.addAttribute(msg, 用户名或密码错误); return login; } }这段逻辑非常清晰接收用户名和密码 → 调用 Service 层做校验 → 成功则写入 Session 并跳转到新闻列表页 → 失败则返回错误提示。Service 层的实现Service public class UserServiceImpl implements UserService { Autowired private UserMapper userMapper; Override public User login(String username, String password) { // 实际项目中建议对密码做加密处理而不是明文比对 String md5Password DigestUtils.md5DigestAsHex(password.getBytes()); return userMapper.selectOne(new LambdaQueryWrapperUser() .eq(User::getUsername, username) .eq(User::getPassword, md5Password)); } }这里有几个值得注意的地方。密码用 MD5 加密存储这一点在课程设计中足够用但在真实项目里我更推荐 BCrypt因为 MD5 已经能被彩虹表轻松破解。如果你只是交作业MD5 没问题如果你想把项目写进简历建议把加密方式升级为BCryptPasswordEncoderSpring Security 原生支持而且加盐机制能大幅提高安全性面试官问起来你也能说出个所以然。至于权限控制这个项目采用的是“Session 判断 拦截器”的模式。后台管理的页面会先判断 Session 里有没有loginUser没有就跳转登录页有就继续访问。代码大致如下public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); if (session.getAttribute(loginUser) null) { response.sendRedirect(/login); return false; } return true; } }提示如果你在源码中看到了WebMvcConfigurer的实现类里面通常注册了拦截器并配置了放行路径比如放行静态资源和登录接口。这个配置类非常重要很多新手折腾半天发现“页面永远跳转登录”就是拦截器路径没放行导致死循环了。3.2 新闻增删改查你绕不开的 CRUD 实战新闻模块是整个网站的核心其操作就是标准的增删改查。在 MyBatis-Plus 的加持下CRUD 代码量非常少。以新闻列表分页查询为例GetMapping(/news/list) public String list(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) Integer categoryId, Model model) { PageNews page new Page(pageNum, pageSize); LambdaQueryWrapperNews wrapper new LambdaQueryWrapper(); if (categoryId ! null) { wrapper.eq(News::getCategoryId, categoryId); } wrapper.orderByDesc(News::getCreateTime); PageNews result newsMapper.selectPage(page, wrapper); model.addAttribute(page, result); return newsList; }这段代码用到了 MyBatis-Plus 的Page分页插件和LambdaQueryWrapper条件构造器把分页和条件查询都封装得非常优雅。你不需要手动写LIMIT ? OFFSET ?也不需要拼接WHERE子句一行selectPage搞定。增删改就更是标准操作了核心代码几乎就一行// 新增 newsMapper.insert(news); // 修改 newsMapper.updateById(news); // 根据ID查询 newsMapper.selectById(id); // 删除 newsMapper.deleteById(id);3.3 文件上传新闻配图背后的完整链路新闻网站通常需要给新闻配图所以文件上传功能是躲不开的。这也是很多初学者第一次接触“服务器文件存储”概念的入口。核心配置在application.yml中spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB然后提供一个文件上传接口PostMapping(/news/uploadImage) ResponseBody public String uploadImage(RequestParam(file) MultipartFile file, HttpServletRequest request) { if (file.isEmpty()) { return 上传失败; } String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String fileName System.currentTimeMillis() _ UUID.randomUUID().toString().replace(-, ) ext; String datePath new SimpleDateFormat(yyyyMMdd).format(new Date()); String realPath request.getServletContext().getRealPath(/) upload/ datePath /; File dir new File(realPath); if (!dir.exists()) { dir.mkdirs(); } try { file.transferTo(new File(realPath fileName)); return /upload/ datePath / fileName; } catch (IOException e) { e.printStackTrace(); return 上传失败; } }文件名用“时间戳UUID”拼接能有效避免同名文件互相覆盖按日期建目录可以避免一个目录下文件过多导致访问变慢。这些细节都是实际生产中的常用手法虽然代码看着简单但思路很值得学习。3.4 前端页面与模板引擎的配合方式这套新闻网站源码的前端有的版本用的是 JSP有的用 Thymeleaf也有的用静态 HTML Ajax。我强烈建议你优先选择 Thymeleaf 版本因为它是 SpringBoot 官方推荐的模板引擎和 SpringBoot 的整合是最顺滑的。Thymeleaf 页面的核心片段大概是这样的tr th:eachnews : ${page.records} td th:text${news.title}新闻标题/td td th:text${news.categoryName}分类/td td th:text${news.viewCount}浏览量/td td th:text${#temporals.format(news.createTime, yyyy-MM-dd HH:mm)}发布时间/td td a th:href{/news/detail/{id}(id${news.id})}查看/a a th:href{/news/edit/{id}(id${news.id})}编辑/a a th:href{/news/delete/{id}(id${news.id})} onclickreturn confirm(确认删除吗)删除/a /td /tr这套代码里没有任何复杂的 JavaScript 框架就是服务端渲染的标准玩法。页面代码在服务端执行将数据填充到模板中然后返回完整的 HTML 给浏览器。好处是简单直接对 SEO 友好且初学者容易理解整个数据流。4. 项目启动与部署从零到可访问的完整过程4.1 环境准备JDK、Maven、MySQL 的版本搭配在运行这个项目之前先要确保本机环境没有问题。我推荐的环境搭配是JDK 1.8 或 JDK 11SpringBoot 2.x 均可支持Maven 3.6 以上MySQL 5.7 或 8.0IDE 使用 IntelliJ IDEA 或 Eclipse这里特别注意一下 SpringBoot 的版本。如果你的项目是 SpringBoot 2.x那用 JDK 8 就可以了如果你用的是 SpringBoot 3.x那必须 JDK 17 以上因为 SpringBoot 3 基于 Jakarta EE 9对 JDK 版本有硬性要求。我看到不少人把 SpringBoot 版本升到 3.x 之后JDK 还在 8结果项目怎么都启动不起来。所以我的建议是先用源码里锁定的版本跑通再考虑升级。4.2 配置数据库连接一处在 application.yml 中搞定数据库连接信息通常在src/main/resources/application.yml中配置。你需要把它改成你自己本机的数据库账号密码server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/news_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver这里面有几个配置项非常容易踩坑serverTimezoneAsia/Shanghai如果不加高版本 MySQL 驱动会报时区错误。characterEncodingutf8mb4要和你数据库的字符集保持一致否则中文乱码。useSSLfalse是在本地开发时关闭 SSL 校验避免告警。driver-class-name在 MySQL 8.0 下必须写com.mysql.cj.jdbc.Driver老版本的com.mysql.jdbc.Driver已经废弃。4.3 启动步骤与常见告警配置好数据库之后启动流程非常简单用 IDEA 打开项目等待 Maven 依赖下载完成。在数据库中执行news.sql脚本完成建库建表和数据初始化。修改application.yml中的数据库密码。运行NewsApplication.java主类。浏览器访问http://localhost:8080。启动过程中如果看到红色的ERROR日志不要慌先看异常信息。90% 的启动失败都是数据库连接问题要么是密码不对要么是库没建好要么是端口被占用。如果出现Port 8080 was already in use说明你的 8080 端口被别的程序占了可以通过netstat -ano | findstr 8080找到占用进程或者直接在配置里把端口改成 8081。5. 常见问题与排查技巧实录5.1 问题速查表我在跑这套项目时整理了一份常见问题清单很多问题都是初学者会反复踩的坑做成表格方便你对照排查。现象原因解决方法启动报Access denied for user数据库账号或密码错误检查application.yml中的username和password启动报Unknown database news_db没执行建库脚本或库名不一致执行SQL脚本确认库名一致页面中文乱码连接串缺characterEncoding或库表字符集不对统一使用utf8mb4确保连接串带characterEncodingutf8mb4启动报时区错误缺serverTimezone配置连接串加serverTimezoneAsia/Shanghai访问页面 404拦截器路径配置问题或静态资源未放行检查WebConfig中addInterceptors的放行路径上传图片后访问 404文件未保存到正确目录或路径映射丢失确认realPath路径是否存在检查WebMvcConfigurer的静态资源映射分页数据不对pageNum从 1 还是 0 开始的理解偏差MyBatis-Plus 默认pageNum从 1 开始前端传参时注意5.2 MyBatis-Plus 的坑Mapper 接口扫描与分页插件MyBatis-Plus 虽然在代码层面很方便但它有两个特别容易踩的坑。第一个是 Mapper 扫描。别忘了在启动类上添加MapperScan(com.news.mapper)注解或者在每个 Mapper 接口上加Mapper注解。否则项目启动时会报找不到 Mapper 的错原因是 Spring 容器不知道去哪里找数据访问层接口。第二个是分页插件。如果你写了selectPage但发现分页不生效大概率是没配置 MyBatis-Plus 的分页拦截器。SpringBoot 2.x 中需要添加如下配置Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }没有这个配置selectPage查出来的数据会是全量的强行分页还会得到奇怪的结果。5.3 项目拿到手以后第一步应该做什么很多同学拿到一个开源项目后第一时间就点运行结果报错一堆当场心态爆炸。我根据经验总结了一个比较稳妥的检查顺序先读README文件。虽然不是每个项目都有但只要作者写了 README里面通常包含环境要求、运行步骤和注意事项。第二步看pom.xml确认 SpringBoot 版本和依赖框架。第三步看application.yml检查数据库配置、端口配置这里的信息基本决定了项目能否启动。第四步看启动类确认 Mapper 扫描是否配置。最后再执行news.sql确认数据表结构。这一步做完项目跑不起来的概率已经降到了最低。6. 从课程设计到面试谈资这个项目的价值挖掘6.1 在简历上如何描述这个项目很多同学做的项目内容差不多但简历上的描述千差万别。有人写“熟悉新闻网站开发”有人写“独立完成新闻网站”这都没什么亮点。我建议你用“技术栈 核心功能 量化成果”的结构来写。可以参考这个表述基于 SpringBoot MySQL MyBatis-Plus 构建新闻管理系统实现用户注册登录、新闻分类管理、新闻发布与检索、浏览量统计及后台管理功能数据库设计包含用户、分类、新闻三张核心表并通过索引优化新闻列表查询效率在项目中负责从数据库设计、接口开发到部署上线的全流程开发并通过拦截器实现简单的登录鉴权。面试官看到这种描述不用追问就能知道你的项目规模和技术含量。6.2 项目里可以继续优化的点如果你不满足于当前版本可以尝试从这些方向把它升级为分布式或微服务风格的“进阶版”把密码加密从 MD5 换成 BCrypt。引入 Spring Security 或 Sa-Token 做更完善的认证授权。用 Redis 做新闻浏览量的缓存解决高并发下的热键问题。增加新闻全文搜索用 Elasticsearch 替代LIKE模糊查询。将图片上传改用云存储 OSS避免本地存储的扩展性问题。增加评论和点赞功能让网站的互动性更强。这些点每做完一个你对该项目的理解就会上一个台阶。最重要的是面试时你能说出每个优化背后的“为什么”这才是真正的亮点。6.3 这套项目中的通用能力迁移最后我想说不要把自己限定在“新闻网站”这个概念里。把它抽象一下这就是一个“内容管理类系统”的典型实现。你把新闻换成商品加上购物车和订单表就变成了电商系统换成文章加上标签和评论就变成了博客系统换成课程加上视频地址和选课表就变成了在线教育系统。所以你会了这一套未来做任何 CRUD 为主的业务系统核心逻辑都相通。这段时间我自己的体会是表面上是做完了新闻网站实际上是把 Web 开发中“请求 → 处理 → 存储 → 渲染”这条链路彻底搞清楚了。这条链路才是真正起作用的东西它不会因为你换一个项目、换一张表就失效。我最后再分享一个小技巧在跑通整个项目之后建议你打开数据库客户端随便改几条数据再刷新页面直观感受一下数据库和网页之间的联系。这个“改数据 → 刷页面 → 看变化”的循环我到现在都觉得是理解前后端关系最有效的方式没有之一。本文还有配套的精品资源点击获取
返回列表