ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringBoot美食网站代码拆解:前后端分离、版本兼容与接口鉴权实战

SpringBoot美食网站代码拆解:前后端分离、版本兼容与接口鉴权实战 简介一份基于Spring Boot Vue开发的美食网站项目源码面向计算机、电子信息工程等专业的学生适合作为毕业设计、课程设计或期末大作业。项目采用B/S架构与MVC分层模式后端由Spring Boot整合MyBatis访问MySQL前端为Vue页面与Axios交互可通过IDEA结合Maven、Tomcat快捷运行。代码包含后台管理界面的主框架、侧边栏、头部、面包屑、密码修改等Vue组件能够完整呈现前后端分离网站从接口到页面的实现思路。资源包为zip格式共670个文件约20.62MB其中171个Java文件为主要后端逻辑117个Vue文件构成前端页面另有SVG/PNG/JPG图片资源、JS/CSS样式脚本、XML/JSON配置文件、构建运行脚本及说明文档便于按目录学习、部署和二次修改。目前已有99人学习下载源码经过博主测试可放心用于课程设计或毕业设计参考。希望获得一套可运行、可拓展的Spring Boot美食网站项目作为课设参考或学习模板的读者这份资料较为实用。1. 拿到 SpringBoot 美食网站代码包先看那些 .bak 文件一份压缩包丢过来多数人第一反应是找 README但这套基于 SpringBoot 的美食网站代码里真正暴露项目底细的是那批.bak文件IndexMain.vue.bak、IndexAsideStatic.vue.bak、BreadCrumbs.vue.bak、update-password.vue.bak外加 run.bat、3-build.bat 这类脚本。.bak后缀说明作者改崩过、留有备份而从命名能直接推断出前端是个典型后台管理布局主框架、顶栏、侧边栏、面包屑、改密码页一应俱全。这说明它不是传统 JSP 单体项目而是 Vue 写页面、SpringBoot 出接口、MySQL 5.7 存数据的前后端分离结构。这套代码适合拿来当毕业设计骨架也适合想搞明白 SpringBoot 前后端分离项目怎么组织的人。下面按实际代码结构依次讲环境版本对应、接口调用链路、启动方式和改密码模块的改造。2. 环境选型不是随便定的JDK 1.8、SpringBoot 2.x 与 MySQL 5.7 的版本对应关系2.1 为什么是这套组合而不是新版代码摘要里写得很清楚JDK 1.8、Maven 3.6、MySQL 5.7、Tomcat 8.0/9.0。这套组合在 2024 年依然能跑但有一个关键边界必须知道JDK 1.8 只能配合 SpringBoot 2.xSpringBoot 3.x 强制要求 JDK 17 起步。网上很多人用 IDEA 新建项目时默认拉到 SpringBoot 3.xJDK 还是 1.8编译直接报UnsupportedClassVersionError这不是代码问题是版本组合错了。另一个容易踩的坑是 MySQL 驱动。SpringBoot 2.4 之前默认用mysql-connector-java从 2.7.8 开始坐标换成了com.mysql:mysql-connector-j。如果你拿到的是较老代码pom 里写的是旧坐标在 Maven 3.6 下也能解析但最好不要手贱去升级驱动版本5.7 的 MySQL 配合 8.x 驱动虽然一般没事但在老项目里保持原样最稳。组件推荐版本说明JDK1.88u201对应 SpringBoot 2.x不能用 3.xMaven3.6.xIDEA 内置的 3.9 也能用但仓库建议用阿里云镜像MySQL5.78.0 也可以跑但驱动和时区配置需要额外调整Tomcat8.0 / 9.0SpringBoot 内嵌 Tomcat外部部署时可以打 war 包放进去前端Vue 2.x Axios对应代码里的 .vue 文件Vue 3 语法不完全兼容2.2 pom.xml 里的关键依赖长什么样这类项目的 pom 结构基本一致父工程是spring-boot-starter-parent版本锁定在 2.x然后引入 Web、MyBatis、MySQL、Lombok。看代码时重点检查 MyBatis 的 starter 用的是哪个parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.5.4/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.2.0/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies这里要注意mybatis-spring-boot-starter的版本是独立管理的不从 parent 继承所以必须显式写。2.2.0 这个版本对应 MyBatis 3.5.x和 SpringBoot 2.5.x 配合没有问题。scope为 runtime 意味着编译时不需要运行时由容器加载如果你在 IDEA 里看到 ClassNotFound先看这个依赖是不是被误删了。2.3 application.yml 配置的四个关键项拿到代码后第一步不是点运行而是改src/main/resources/application.yml。这个文件决定项目能不能连上数据库、端口会不会冲突、MyBatis 能不能找到 Mapper 映射文件。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/food_website?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.food.entity configuration: map-underscore-to-camel-case: true四个关键点拆开说第一serverTimezoneAsia/Shanghai必加不加 5.7 会报The server time zone value的异常这是中文教程里最常见的坑。第二driver-class-name如果是com.mysql.cj.jdbc.Driver对应新版驱动老代码里可能是com.mysql.jdbc.Driver两者都能用但别混。第三mapper-locations指向 XML 文件所在的目录如果代码里 Mapper 接口和 XML 不在同名包下这个配置缺了的话运行时报Invalid bound statement。第四map-underscore-to-camel-case开启后数据库里的create_time字段能自动映射到 Java 属性createTime不用手写 ResultMap 映射。3. 从 .bak 文件还原前端骨架IndexMain、IndexHeader、IndexAsideStatic 的配合方式3.1 五个 Vue 组件各自承担什么职责压缩包里出现的IndexMain.vue.bak、IndexAsideStatic.vue.bak、BreadCrumbs.vue.bak、IndexHeader.vue.bak、update-password.vue.bak不是散装文件它们拼起来就是一套后台管理系统的标准布局。.bak后缀只是备份把后缀去掉、内容替换回来就能参与编译。IndexMain.vue路由容器负责把侧边栏、顶栏、内容区组合在一个页面上IndexHeader.vue顶部导航栏通常放系统名称、用户信息、退出登录按钮IndexAsideStatic.vue静态侧边栏菜单Static说明菜单项是写死的不是从数据库动态加载BreadCrumbs.vue面包屑导航根据当前路由显示当前位置update-password.vue修改密码页面一般通过顶栏头像下拉入口进入这套结构在 SpringBoot 后台管理系统里非常典型电商后台、文章管理系统、班级管理系统基本都是这个套路。IndexAsideStatic里的菜单项对应的就是 Vue Router 里的路由表路由表里每个页面组件对应一个后端接口模块。3.2 前端菜单到 SpringBoot Controller 的调用链路以一个美食分类管理模块为例页面加载时 Vue 组件里发请求路径是/category/list后端 Controller 接收后走 Service 层调 Mapper 查数据库数据再一层层返回给页面渲染RestController RequestMapping(/category) public class CategoryController { Autowired private CategoryService categoryService; GetMapping(/list) public Result list() { ListCategory list categoryService.listAll(); return Result.success(list); } PostMapping(/save) public Result save(RequestBody Category category) { categoryService.save(category); return Result.success(null); } }这里RestController表示所有方法返回 JSON不走视图解析器。RequestBody接收前端传来的 JSON对应 Vue 页面里axios.post的请求体。返回的Result是统一包装类一般结构是{ code: 200, message: success, data: [...] }前端根据code判断请求是否成功。很多新手误把Result当普通实体类其实它承载的是接口协议字段名一旦跟前端约定好就不能乱改。3.3 Axios 请求与后端接口怎么对上前端页面的核心调用方式常见做法是用 Axios 的实例统一配置 baseURL然后在组件里按需调用import axios from axios const request axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000 }) export function getCategoryList() { return request({ url: /category/list, method: get }) }调用方在IndexMain.vue或者分类管理页里onMounted时执行拿到数据后赋值给响应式变量。这里的VUE_APP_BASE_API在.env.development里定义通常值是/api然后通过 devServer 的 proxy 把/api前缀代理到后端的http://localhost:8080。这样做的好处是前端开发时不需要后端地址写死部署时只改环境变量不动业务代码。要注意这套项目的接口通常没有全局前缀Controller 里直接写/category/list。如果加了 server.servlet.context-path那所有接口路径会多一层前缀前端 baseURL 也要对应调整。代码里如果出现 404优先检查这两处是否匹配。4. 启动三步走建库、改配置、跑 run.bat 还是 IDEA4.1 先把数据库准备好再谈启动代码包解压后根目录一般附带.sql文件文件名可能是food_website.sql或db.sql。用 SQLyog 或 Navicat 新建一个名为food_website或与 application.yml 里 url 后缀一致的库名的数据库字符集选utf8mb4排序规则选utf8mb4_general_ci然后导入 sql 文件。导入时注意两个细节第一如果 sql 文件里没有CREATE DATABASE语句先手动建库再导入不然 Navicat 会报错第二导入完成后检查表名前缀有的代码表名带sys_或t_前缀两套不同代码的表名命名风格很可能不一样直接决定 Mapper XML 里的表名能不能对上。4.2 run.bat 与 3-build.bat 的分工逻辑压缩包里有run.bat、2-run.bat、build.bat、3-build.bat四个脚本数字前缀暗示执行顺序。这类 bat 脚本内容通常很短作用是指定端口和启动方式echo off echo Starting Food Website... set JAVA_HOMED:\Java\jdk1.8.0_202 set PORT8080 java -jar -Dserver.port%PORT% target\food-website-0.0.1-SNAPSHOT.jar pause这段脚本做的事可以拆成四层set JAVA_HOME是把 JDK 指向本机安装路径如果系统装过多个 JDK这一步能避免命令行找到错误版本java -jar表示直接运行编译后的 jar 包前提是target目录下有产物-Dserver.port表示运行时覆盖配置文件里的端口适合同一台机器部署多个实例时用最后的pause是为了在双击运行时不让窗口闪退方便看到报错信息。build.bat则对应打包动作常见内容就是mvn clean package -DskipTests这个命令的作用是清理旧的 target 目录、重新编译源码、跳过测试用例、把项目打成可执行的 jar 包。3-build.bat和2-run.bat的数字前缀意味着作者的习惯是先 run 再 build还是反过来从命名看我推测作者的执行顺序是 2 运行、3 打包也就是先本地跑起来看效果确认没问题再打部署包。这个顺序本身没有对错但你要明白每个脚本做了什么再双击。4.3 本地启动最常见的四个报错排查现象原因排查手段启动后浏览器报 404但页面框架能出来前端路由是 history 模式刷新时后端没有对应路由兜底临时改用 hash 模式或加 forward 到 index.html连接数据库报Access denied for userapplication.yml 里的账号密码和本机 MySQL 不一致在 Navicat 里确认 root 密码改 yml 后重启控制台报Port 8080 was already in use端口被其他进程占用netstat -ano | findstr 8080查 PID杀掉对应进程页面能打开但接口返回 500Mapper XML 里的 SQL 和表名对应不上打开数据库看真实表名对照 XML 逐字核对第一个 404 的情况很隐蔽开发阶段用 IDEA 跑 Vue devServer 时一切正常把前端打包放 SpringBoot 的static目录后刷新/food/list这类路由就会出现 404。原因很简单后端没有这个路径的 Controller而 Vue Router 是 history 模式时浏览器直接请求了真实路径。常见做法是把前端路由改成 hash 模式或者在后端加一个 forwarding 配置把所有非接口路径都指向 index.html。这个问题在 SpringBoot Vue 项目里出现的频率非常高先记住结论遇到时直接处理。5. 把 update-password.vue.bak 从「能改密码」改成「带鉴权的改密码接口」5.1 原实现的问题所在update-password.vue.bak这类页面在毕业设计代码里通常是纯前端校验旧密码、新密码、确认新密码三个输入框点击提交时把用户名和密码 POST 给后端。但很多套代码的后端接口只校验新密码和确认密码是否一致完全没有校验旧密码是否正确。更严重的是如果接口路径是/user/updatePassword并且没有做登录态校验那任何人只要知道接口地址就能直接改任意用户的密码。排查方法很简单打开这个 Vue 文件看请求头里带不带token或Authorization如果只是axios.post(/user/updatePassword, params)这种裸请求那这个接口就是不设防的。5.2 用 HandlerInterceptor 把修改密码接口保护起来SpringBoot 里最轻量的做法是写一个拦截器校验请求 Header 里是否有合法的登录令牌。这里以常见的 token 存 Redis 为例但考虑到毕业设计代码一般没有 Redis可以直接用 session 或 JWT。用 JWT 的改动最小不需要额外依赖缓存组件public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (token null || token.isEmpty()) { response.setStatus(401); response.getWriter().write({\code\:401,\message\:\未登录\}); return false; } // 校验 token 合法性这里简化为解析 JWT String userId JwtUtil.parseToken(token); request.setAttribute(userId, userId); return true; } }这个拦截器的核心逻辑分成三步第一步从请求头取Authorization没有就直接返回 401第二步调用JwtUtil.parseToken解析 token这个方法内部会验证签名和过期时间第三步把解析出的 userId 放进 request 属性后续 Controller 里直接取不用再查一遍用户身份。HandlerInterceptor是 SpringMVC 提供的接口SpringBoot 直接复用不需要额外引包。注册拦截器是另一个关键点只拦截需要登录的接口放行登录接口本身Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/user/**, /order/**) .excludePathPatterns(/user/login, /user/register); } }addPathPatterns指定拦截哪些路径excludePathPatterns声明哪些不需要登录。注意顺序问题先 add 路径再 exclude 路径否则放行的规则可能不生效。还有一个隐藏问题如果代码里用了CrossOrigin处理跨域预检请求 OPTIONS 也会被拦截器拦到需要在 preHandle 里放行 OPTIONS 请求否则前端浏览器控制台会报 CORS 错误但没有实际请求发出去。5.3 前端页面怎么配合这套鉴权后端加完拦截器后update-password.vue里的请求必须带上 token否则会被 401 挡下来。在 Axios 请求封装里加一个请求拦截器request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config })这段代码在每次请求发出前从 localStorage 取 token如果存在就挂到Authorization头。对应的登录成功后需要把后端返回的 token 存到 localStorage退出登录时清除。到这里修改密码接口就从前端校验裸奔状态变成了必须携带有效 token 才能访问的状态。验证方式很简单不登录直接访问/user/updatePassword应返回 401登录后用 Postman 或浏览器开发者工具手动带 token 请求应正常返回成功。本文还有配套的精品资源点击获取
返回列表