每年毕业季Java Web方向的毕设选题绕来绕去就那么几个组合但SpringBootVue这套组合一直是妥妥的“顶流”。打开任何招聘网站看后端岗位要求SpringBoot几乎是必备项再看前端岗位Vue的占有率也是数一数二。所以很多导师和学生会直接默认毕设就选SpringBootVue。话虽这么说真正动手的时候很多人还是会卡在“项目能跑通”和“项目像个完整的毕设”之间的巨大鸿沟上。这篇文章我就围绕一套完整的SpringBootVue网站平台项目把源码、SQL脚本、接口文档这三件套从头到尾讲讲清楚包括每一件套到底该怎么组织、怎么落地、怎么避坑以及这三者之间怎么互相配合才能让答辩老师挑不出硬伤。这套项目适合谁三类人第一类是正在准备Java Web方向毕业设计的本科生需要一份能讲清楚、能扩展的完整基线第二类是刚入行不久、想系统走一遍前后端分离开发流程的初级Java开发第三类是准备跳槽、想快速搭建一个可演示的个人项目的开发者。无论你属于哪一类核心诉求都是一样的别人用一套模板糊弄而你想真正搞明白里面的门道同时拿到一份可以直接跑、能复现、能答辩的工程。1. 项目全景毕设里的SpringBootVue到底在写什么1.1 从标题拆出“完整项目”的真实含义很多人看到“SpringBootVue 网站平台完整项目源码SQL脚本接口文档”这个标题会觉得这就是一个打包好的网盘资源。但“完整项目”四个字放在毕设语境里是有严格边界的。它不只是一堆能编译的Java文件加几个.vue页面而是一套“需求可追溯、代码可运行、数据可初始化、接口可对接”的闭环。我一般把毕设项目拆成四层来验收需求层这个平台解决什么问题服务谁核心流程是什么。代码层后端SpringBoot工程结构清晰前端Vue工程模块化关键业务逻辑有注释。数据层MySQL库表设计合理SQL脚本能一键初始化包含测试数据。接口层接口文档覆盖所有前后端交互点约定统一响应格式有请求示例。举个例子一个典型的“校园二手交易平台”标题里写“网站平台”落到代码里就该有用户注册登录、商品发布、商品浏览、订单管理、个人中心、后台管理这几条主线。你不能说“我写了一个平台”但只有登录注册和一张列表页那叫Demo不叫平台。1.2 技术选型背后的逻辑为什么偏偏是SpringBootVue很多同学问过我Java Web框架那么多SSH、SSM、SpringBoot各有人用为什么毕设普遍推荐SpringBoot答案很实在SpringBoot不是一个新技术而是一套“约定大于配置”的整合方案。它把Spring、SpringMVC、MyBatis等组件的集成过程大幅简化内置Tomcat跑一个main方法就能起服务。对于毕设这种“时间紧、要稳定、要能讲清楚”的场景SpringBoot就是让你少写配置、少踩环境坑。Vue同理。Vue 3 Vite Element Plus这套组合组件化开发、路由管理、状态管理、mock调试都有成熟的生态前端页面写起来快展示效果也现代。更关键的是Vue和SpringBoot天然构成前后端分离架构前端跑在8080端口后端跑在8081端口通过HTTP接口通信各司其职。还有一个细节值得注意SpringBoot 2.x和3.x的差异。现在很多教程默认用2.7.x但新项目已经大量迁移到3.x。如果你用SpringBoot 3.x必须配Java 17以上而且注意包名从javax.servlet变成了jakarta.servlet。选型定版之前先想清楚你自己的JDK环境别等代码写到一半才发现版本不兼容。2. SpringBoot后端骨架、配置与自动装配原理2.1 用IDEA创建SpringBoot项目的三个关键点工欲善其事必先利其器。IDEA创建SpringBoot项目现在主流方式有两种一种是去 start.spring.io 生成基础包再导入IDEA另一种是IDEA内置的Spring Initializr。我个人推荐后者因为版本选择、依赖勾选、目录结构一步到位省去手动调Maven的麻烦。创建时有三个关键点容易栽跟头第一JDK版本要和SpringBoot版本匹配。SpringBoot 2.x要求JDK 8或11SpringBoot 3.x要求JDK 17及以上。如果你本机只装了JDK 8硬选SpringBoot 3.2.x启动直接报UnsupportedClassVersionError。第二依赖不要乱勾。新建项目时Spring Initializr会列一堆依赖项毕设项目一般只需要Spring Web、MyBatis Framework或MyBatis-Plus、MySQL Driver、Lombok顶多加一个Validation。像Spring Security这种如果你不熟悉它的过滤器链机制建议先不碰用拦截器实现登录校验就够用。第三选择Maven还是Gradle。国内教程氛围下Maven是绝对主流毕业设计的任务书也通常明确写着“基于Maven构建”。Maven的核心是pom.xml所有依赖版本都在这里管理。就算你不会写Maven高级配置只要会看依赖树、会clean和install就已经够用了。创建完后标准的包结构应该是com.xxx.platform下分controller、service、mapper、entity、config、common这几层。不同人写代码命名习惯有差异但分层的思想必须清晰——Controller层只做参数接收和响应返回Service层只做业务逻辑Mapper层只管数据库操作。有些同学图省事在Controller里直接写SQL查询当时是爽了后面前后端联调、出错排查的时候痛苦翻倍。2.2 SpringBoot自动装配原理面试也常问的那点事做毕设的时候很多人会用SpringBoot但被问到“SpringBoot自动装配原理”就支支吾吾。这其实是SpringBoot最核心的机制也是答辩老师最喜欢问的点。我用一句话概括SpringBoot启动时通过EnableAutoConfiguration注解结合Conditional系列条件注解根据你引入的依赖和配置自动决定要不要创建某个Bean。spring-boot-autoconfigure包里的META-INF/spring.factories文件或AutoConfiguration.imports文件中注册了大量自动配置类。比如你引入了mybatis-spring-boot-starter启动时就会加载MybatisAutoConfiguration它先判断classpath里有没有SqlSessionFactory和DataSource相关类如果没有就不生效这就是条件装配。你不需要写出这些自动配置类但你应该知道它们存在并且知道怎么在application.yml里通过spring.autoconfigure.exclude排除掉某个自动配置。举个实际情况你只是想用MyBatis连一个MySQL结果SpringBoot还自动给你配置了Redis的数据源因为classpath里有Redis依赖这时候你就得排除掉它否则启动报错。2.3 配置文件多环境切换与关键参数解析SpringBoot的配置文件有两种格式application.properties和application.yml。我推荐用application.yml层级结构清晰读起来一目了然。一个规范的毕设项目至少应该拆出三个环境的配置application-dev.yml本地开发环境连本机MySQL日志级别DEBUG。application-test.yml测试环境连测试数据库用于联调。application-prod.yml生产环境/答辩演示环境数据库、Redis等指向服务器。用spring.profiles.activedev来切换环境。很多同学只留一个application.yml数据库连接写死换台电脑就得改配置改半天。多环境配置加上之后换环境只是改一个参数差距不小。关键配置项逐个说明server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/platform_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl这里有个细节数据库URL里的serverTimezoneAsia/Shanghai必须加。MySQL 8.0之后的驱动要求明确时区不加的话连接会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。characterEncodingutf8解决中文乱码useSSLfalse避免本地连接时报SSL警告。日志配置也值得说一嘴。log-impl设置为StdOutImpl在控制台能看到MyBatis打印的完整SQL语句。这一步对调试太重要了——前端传了个参数后端查出来的数据不对你一眼就能从SQL日志里看出问题是出在SQL拼接还是参数传递。2.4 实体类、Mapper与Service写一个完整CRUD的套路我个人习惯用MyBatis-Plus因为它内置了BaseMapper单表CRUD不用写SQL大大减少重复劳动。但要注意MyBatis-Plus不等于MyBatis它的逻辑删除、分页插件、字段自动填充都需要额外配置。在毕设项目里我会用MyBatis-Plus但前提是把原理讲清楚——不能只会调selectPage不知道它底层怎么生成SQL。核心套路是四步第一步建实体类User用TableName(t_user)注明对应表用TableId(type IdType.AUTO)标注主键用TableField处理字段映射。注意createTime这类字段名Java属性写成createTime数据库列名是create_time靠全局配置map-underscore-to-camel-case: true自动映射但前提是你的Java属性确实遵循驼峰命名。第二步建UserMapper接口继承BaseMapperUser。一个接口都不需要写方法就有全表的selectById、selectList、insert、updateById、deleteById。第三步建UserService接口和UserServiceImpl实现类。我习惯在Service里封装带有业务含义的方法比如register、login、updatePassword而不是直接把Mapper的CRUD暴露给Controller。这层是业务逻辑的所在地也是答辩时“你做了哪些设计”最集中的体现。第四步写Controller。Controller只做三件事接收参数、调用Service、返回统一结果。RestController RequestMapping(/api/user) public class UserController { Resource private UserService userService; PostMapping(/login) public ResultString login(RequestBody LoginDTO loginDTO) { String token userService.login(loginDTO); return Result.success(token); } }Controller里绝不出现selectById这种直接跟数据库打交道的调用。边界清晰后面做权限拦截和接口文档都会省事很多。3. Vue前端从环境搭建到动态路由、组件化页面3.1 Vue环境配置与工程化创建版本选型最省心组合做前端第一件事是装环境很多第一次接触Vue的人卡在Node.js和npm上。我的建议是Node.js装LTS版本也就是长期支持版当前推荐18.x或20.x。不要急着追最新大版本有些依赖不兼容安装的时候就会报错。装完Node.js后npm会自带。但国内npm默认源下载速度不稳定可以先把npm源切换到国内镜像站。这里说的切换源是正常开发操作比如用npm config set registry指向公共npm镜像地址这属于开发者日常环境配置。Vue项目的创建方式我用的是Vite。命令就一行npm create vitelatest frontend -- --template vueVite的好处是启动快、热更新快比老一代的vue-cli webpack方案体验好一个档次。模板创建好后按提示npm install装依赖npm run dev就能起一个默认页面。如果你非要用vue-clinpm install -g vue/cli然后vue create frontend也可以但Vite是当前主流方向。给导师演示的时候Vite启动服务一秒钟就能起来现场效果好太多。工程结构我会这样规划src/api统一存放所有接口调用方法。src/routerVue Router路由配置。src/storePinia状态管理。src/views页面级组件。src/components可复用功能组件。src/utils请求封装、工具函数。3.2 路由与动态路由从登录到页面权限的完整链路Vue的页面跳转靠路由。毕设平台几乎都有一个共性需求没登录就不能访问业务页面。方案是给每个路由设置meta字段标记requiresAuth全局路由守卫里做拦截。const router createRouter({ history: createWebHistory(), routes: [ { path: /login, name: Login, component: () import(/views/Login.vue) }, { path: /dashboard, name: Dashboard, component: () import(/views/Dashboard.vue), meta: { requiresAuth: true } } ] }) router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.matched.some(record record.meta.requiresAuth) !token) { next(/login) return } next() })动态路由是另一个进阶点。不同角色普通用户、管理员看到的菜单和页面应该不一样。实现思路是用户登录后后端返回该用户有权限访问的菜单列表、角色标识前端拿到后用router.addRoute动态注册对应路由。这一步讲出来答辩面试都是加分项。很多教程里的动态路由写得过于复杂其实核心就两步登录成功后保存token和menus到本地。在全局守卫里判断路由是否已注册如果没有就解析menus调用router.addRoute。有同学问我Vue里真正的权限判断到底在前端还是后端我的回答是前端控制的是“显示与跳转”是体验层后端控制的是“数据访问”是安全层。后端接口必须要有真正的权限校验前端路由守卫只是不把页面暴露给无权限的人。这一点答辩老师很爱追问你能用这句话回答明显就是自己设计过、想过。3.3 组件化开发Vue插槽、Axios封装、Element Plus使用Vue的强大核心在组件化。你写一个页面不是把HTML堆在一个文件里而是拆成多个模块化组件。组件之间传参用props和emit插槽slot用来做组件内容分发。以弹窗组件为例el-dialog同类型的弹窗在多个页面出现我就封装一个ModalDialog.vue内容部分用slot/slot预留父组件往里面填充表单或表格。插槽用得好代码复用率直线上升这也是答辩时能讲的设计点。Axios封装是必做项。原生axios每发一次请求都要写一遍baseURL、headers重复率太高。我一般在src/utils/request.js里统一创建实例import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动携带token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) // 响应拦截器统一处理业务码 request.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.message) return Promise.reject(new Error(res.message)) } return res }, error { ElMessage.error(网络异常请稍后重试) return Promise.reject(error) } ) export default request写完封装之后业务接口就是纯粹的接口定义比如export const login (data) { return request.post(/user/login, data) }前端跑起来后有一个非常关键的开发配置跨域问题。SpringBoot后端在8081端口Vue开发服务器在5173端口直接fetch是跨域请求。解决方案有两种一是在Vue的vite.config.js里配proxy代理二是后端写CORS跨域配置。我推荐Vite的proxy方案原因在于它只在开发环境生效打包之后前端和静态资源同源部署不会有多余的跨域风险。server: { proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } }这样前端请求/api/user/login会代理转发到http://localhost:8081/api/user/login。注意这里有个小坑后端的RequestMapping里是否也要带/api前缀前后要统一约定我习惯后端Controller统一加/api前缀这样Vite代理和后端路径天然衔接。4. SQL脚本从建库建表到初始化数据的完整规范4.1 数据库设计别在第一步就把项目写死拿到一个网站平台的毕设题目先别急着写Java代码第一步应该是设计数据库。库表设计的好坏直接决定项目能撑多大规模、后期扩展顺不顺手。一个合格的毕设数据库要遵循几个原则命名规范库名、表名用下划线分隔如platform_db、t_user字段名如user_name、create_time。主键固定每张表都有主键我用id BIGINT AUTO_INCREMENT不搞复合主键的自然主键。通用字段统一create_time、update_time、deleted这三列几乎每张业务表都放。冗余字段宁可少一点比如用户表里存user_name订单表也存一份user_name作为冗余展示字段这在大数据量下不推荐但毕设阶段为了简化联表查询少量冗余可以接受。平台类项目最基础的核心表我列一个通用参考表名用途关键字段t_user用户表id, username, password, nickname, avatar, role, statust_role角色表id, role_name, role_codet_menu菜单权限表id, parent_id, menu_name, path, component, permst_category分类表id, parent_id, name, sort, statust_business核心业务表根据题目而定如公告、商品、订单t_comment评论表id, business_id, user_id, content, create_time密码字段尤其注意数据库里存的是加密后的密文我用BCrypt加密。有的毕设项目直接明文存储答辩时这就是个很大的安全扣分项。4.2 从SQL脚本反推业务边界初始化数据别抠门SQL脚本交付不只是CREATE TABLE那么简单。一套完整脚本要包含三部分建库语句CREATE DATABASE IF NOT EXISTS platform_db DEFAULT CHARACTER SET utf8mb4;utf8mb4比utf8更完整能存emoji和更广泛的字符。建表语句每张表带DROP TABLE IF EXISTS保证脚本可重复执行。初始化数据管理员账号、默认角色、测试分类、几条演示业务数据全都要有。很多同学觉得自己系统没数据脚本里就几张空表结果前端列表页打开一片空白只能截图说“功能做好了只是没数据”。这是大忌。初始化数据要让你演示的时候打开页面就有内容展示哪怕只有10条记录页面的分页、排序、详情效果都能立刻体现出来。特别提醒一个细节模拟数据要用真实中文内容别用test、123这种。展示场景下一堆“测试数据”给人感觉非常粗糙。4.3 索引、外键与逻辑删除几个容易翻车的MySQL细节设计SQL脚本时有几个人人都会踩的坑。第一外键到底建不建。我的建议是毕设项目不要建物理外键。外键约束会严重影响插入和删除性能而且前后台系统里大量逻辑删除场景下物理外键会导致删不掉数据。表之间的关联逻辑放到Service层去控制用代码保证数据一致性。数据库只保留普通索引。第二逻辑删除用deleted字段0未删除、1已删除。配合MyBatis-Plus的TableLogic注解查询的时候自动过滤已删除数据。这样做的好处是历史数据不丢坏处是实现不当容易漏查比如你自己写SQL时也要条件带上deleted 0。第三索引别乱加。很多同学每一列都加索引结果索引体积比数据还大。原则是WHERE条件高频使用、关联查询的字段、唯一性字段才加索引。用户表的username加唯一索引就足够status这种区分度不高的字段没必要。下面是用户表的参考脚本片段CREATE TABLE t_user ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键ID, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(100) NOT NULL COMMENT 密码密文, nickname VARCHAR(50) DEFAULT NULL COMMENT 昵称, avatar VARCHAR(255) DEFAULT NULL COMMENT 头像URL, role VARCHAR(20) NOT NULL DEFAULT USER COMMENT 角色ADMIN/USER, status TINYINT NOT NULL DEFAULT 1 COMMENT 状态1启用 0禁用, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, deleted TINYINT NOT NULL DEFAULT 0 COMMENT 逻辑删除0未删 1已删, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;一个插入管理员的语句INSERT INTO t_user (username, password, nickname, role) VALUES (admin, $2a$10$7JB2yAIlXgZlLKNqQ1wFQeD8nB0k1s9pT4N8wXUzY8dH6yG7sMKnK, 管理员, ADMIN);这串$2a$10$...开头的就是BCrypt加密后的固定密文对应明文是123456。教科书写脚本时老老实实写上加密后的值别在脚本里写明文密码也不要在脚本里现场调用Java代码加密保持脚本的可执行性。5. 接口文档让前后端联调少吵架的硬通货5.1 接口文档到底该写什么一个接口的完整示例很多同学把接口文档当成一个可有可无的Word附件但其实它是整个项目中性价比最高的东西。写清楚接口文档不仅方便前端调用答辩的时候也能让老师直观看到你的系统设计能力。一个合格接口文档每个接口至少包含六要素接口名称一句话说明用途。请求URL具体路径如POST /api/user/login。请求方式POST/GET/PUT/DELETE。请求参数参数名、类型、是否必填、说明。响应结果成功和失败的JSON结构示例。错误码说明不同失败场景返回什么业务码。比如登录接口文档里我会这样写POST /api/user/login Content-Type: application/json 请求参数 { username: admin, // 必填用户名 password: 123456 // 必填明文密码后端负责加密比对 } 成功响应 { code: 200, message: 操作成功, data: { token: eyJhbGciOiJIUzI1NiJ9.xxx, nickname: 管理员, role: ADMIN } } 失败响应 { code: 500, message: 用户名或密码错误, data: null }参数类型要精确到Java类型和JSON类型映射。比如Long在前端容易精度丢失大整数ID必须用字符串返回文档里就要特别注明。5.2 统一响应体后端跟前端的“交通规则”接口文档质量高不高很大程度上取决于后端有没有统一响应体设计。我用的是最常见三层结构public class ResultT { private Integer code; private String message; private T data; }业务码设计要有全局观念。200成功400参数错误401未登录或token失效403无权限500系统异常。状态码和HTTP状态码不必完全重叠但含义要清晰。前后端联调时前端统一在Axios响应拦截器里判断code所有接口都走同一个成功/失败逻辑代码量省掉一大截。一个细节后端校验参数时千万别把内部异常堆栈直接返回给前端。message要写人话比如“用户名不能为空”而不是“NullPointerException: null”。错误信息的可读性也是文档质量的一部分。5.3 接口文档的生成方式手写、Swagger还是Apifox文档怎么落地常见有三种方式第一手写Markdown表格。优点是灵活不用引入额外依赖。缺点是有接口变动时必须手动同步容易过期。第二使用Swagger/SpringDoc。在SpringBoot里集成springdoc-openapi然后访问/swagger-ui.html就能在线查看接口文档。它的好处是接口定义跟着代码走代码改了文档自动变。缺点是注解写起来有点啰嗦而且Swagger UI的界面对于答辩展示来说不够直观。第三使用Apifox或Postman。联调时用工具调试接口然后导出一份接口文档。我个人的习惯是开发期用Apifox做自测答辩交付时额外整理一份Markdown接口文档放进项目压缩包的/doc目录下。老师打开就能看不用装任何环境。不管用哪种方式代码里的接口注释一定要写。有人觉得“代码就是最好的文档”这话对高手成立对读者不成立。毕设源码是要被老师翻看的Controller每个方法上一行Operation(summary 登录接口)或者简单的// 登录接口阅读体验天差地别。6. 常见问题与排查实录从环境到部署的硬核避坑6.1 SpringBoot版本太高导致的环境连锁反应“spingboot版本太高”很多人亲手踩过。SpringBoot版本高本身不是问题问题是配套环境没跟上。比如你下载了一个SpringBoot 3.3.0的项目模板但本机JDK还是8Maven编译直接失败。高版本SpringBoot对Maven版本也有要求Maven 3.6.3以下可能无法正确解析某些插件。还有一种情况别人给的源码里用的是SpringBoot 2.6.x你本机装了JDK 17原本也好好的但你为了追求新版强行升级到SpringBoot 3.2.x然后发现javax.servlet包全部报红因为3.x换成了jakarta.servlet一堆第三方适配库版本不兼容。我的建议很直接不要迷信最新版。SpringBoot 2.7.18是目前最稳的毕设版本资料多、坑都被踩平了各种第三方库版本都能对上。如果必须要用3.x请确保你从创建项目起就明确选型别中途升级。6.2 前后端联调跨域、404、字段对不上前端页面上调接口常见报错分四类Network Error后端没启动、端口不一致、路径错了。先用浏览器直接访问后端接口URL确认后端可用。CORS error跨域配置没生效。开发环境下优先检查Vite代理配置后端CORS配置有时候被拦截器屏蔽注意配置顺序。404 Not Found前后端URL不一致。后端/api/user/login前端代理配置写成了/user/login拼接后路径错误。统一约定是很省心的预防手段。返回undefined或数据为空字段映射问题。数据库字段user_nameJava实体属性只写了个username中间没开驼峰映射查出来就全是null。联调效率最高的习惯先在Apifox里把后端接口调通再从前端页面发起请求。这样能快速把问题定位到“后端接口问题”还是“前端调用问题”。你省掉的不只是排查时间还有两个人互相甩锅的沟通成本。6.3 Vue打包后放进SpringBoot的部署细节本地开发时前端和后端分开跑但交付时往往希望给人一个“双击就能跑”的印象。这时可以把Vue项目打包然后把静态资源放进SpringBoot的src/main/resources/static目录下后端启动后直接访问http://localhost:8081就能看到前端页面。执行npm run build后dist目录里是打包产物。把dist下的所有文件复制到resources/static。但有一个高频问题刷新页面会404。原因是Vue Router用的是history模式刷新非首页路径时后端没有对应的路由返回404。解决办法两个后端写一个ViewController或自定义ErrorController把非/api开头的请求都转发到index.html。把前端路由模式改成hash模式URL里有#刷新不会404但看起来不够美观。毕设演示用我推荐第一个方案看起来更接近真实上线效果。部署时还有几个注意点前端请求的baseURL如果在Axios里写死了http://localhost:8081部署到别的机器就废了。打包前把baseURL配置成相对路径/api本地开发靠Vite代理打包后靠Nginx或SpringBoot同源部署一套代码到处跑。6.4 数据库连不上最扎心的启动失败后端启动时最常见的报错就是Cannot create PoolableConnectionFactory满屏的红色日志对新手极其劝退。排查顺序MySQL服务有没有启动。Windows下winr输入services.msc查看MySQL服务状态。端口是不是3306。如果你的MySQL改过端口比如3307配置文件里要相应修改。密码和用户名对不对。root密码忘了可以先通过命令行mysql -uroot -p验证。URL里时区参数有没有加。MySQL 8.0以上没有serverTimezone会直接连不上。还有一个隐蔽问题MySQL 8.0的驱动类和5.x不同驱动类名要从com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver。SpringBoot 2.7引入的mysql-connector-j其实已经默认兼容但如果你手动在pom里改了旧坐标就会报驱动类找不到。我建议做毕设时把MySQL装成8.0版本及以上因为8.0是目前教学和业界的主流SQL脚本里的utf8mb4、CURRENT_TIMESTAMP这些特性都能用上不容易出现版本兼容的尴尬。写在最后的几句实在话这套SpringBootVue网站平台项目从技术栈选择到三件套交付我完整走了一遍。带过不少学弟学妹的毕设我发现真正拉开分数差距的不是代码量多少而是“是否真正理解自己写的东西”。有人代码堆了上万行但问他“登录校验在哪个环节做的”就语塞也有人核心代码只有几千行但每个模块为什么这么写、数据怎么流动、接口怎么约定讲得明明白白。毕设考察的本质是你面对一个具体问题时的拆解和落地能力。如果你准备用这套路线做自己的项目记住三个落地的关键点先设计数据库再写代码先约定接口再各自开发先跑通主流程再补充细节。这三条顺序不乱项目大概率能顺顺当当交付。往后做商业项目也一样技术方案会变但这套做事逻辑不会变。