ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot+Vue3前后端分离电影网站系统实战开发指南

SpringBoot+Vue3前后端分离电影网站系统实战开发指南 基于SpringBootVue3前后端分离的电影网站系统是这几年Java后端学习里出现频率很高的项目类型尤其是毕业设计、课程实训、简历项目这几个场景都能看到它的身影。它的核心不是做一个能看电影的站点而是把一套典型业务系统完整串起来前端页面展示电影信息后端提供接口维护数据中间经过登录鉴权、评论收藏、后台管理等环节最后还能打包部署到服务器上。按这个方式练一遍你基本就能理解一个真实Web项目是怎么从表结构一步步变成可访问系统的。这篇内容我会按实际做项目的顺序来拆而不是单独讲Vue或SpringBoot。先分析这个题目需要实现哪些模块再定版本和环境然后走通最小闭环之后扩展业务逻辑最后处理部署和常见报错。如果你正准备用这个题目做毕设或者想快速把前后端分离练扎实按这个思路走会省很多时间。我自己的建议是不要一上来就把所有功能堆进代码。先把“电影列表能展示出来”闭环跑通再逐步加登录、评论、收藏最后补后台管理。这样每次改动都有明确验证点出问题也容易定位。1. 先判断这个项目最该做哪些模块不该做什么1.1 一套电影网站系统到底需要哪些核心能力从用户视角看一个电影网站通常需要这几块能力电影列表展示按热度、上映时间、评分等维度展示电影。分类筛选按类型、地区、语言等条件筛选也可能支持关键词搜索。电影详情展示海报、简介、导演、主演、上映时间、评分、播放或预告片链接等。用户体系注册、登录、个人信息查看一般配套修改密码。用户行为对电影发表评论、收藏喜欢的电影、查看自己的收藏列表。后台管理管理员登录后维护电影信息包括新增、编辑、上架下架、删除以及对用户和评论做基础管理。从技术实现角度看前台用户系统和后台管理系统可以共用同一套后端接口只是通过权限来控制。比如普通用户只能调用评论接口管理员才能调用电影维护接口。这样写一套服务就够不需要拆成两个后端项目。如果做成“前后端分离”用户看到的所有电影页面都由Vue负责渲染数据则通过Ajax或Fetch请求从SpringBoot接口获取。这个过程中的核心难点不是某一个操作很难而是“一个完整功能从前端点击到后端入库”整条链路必须清晰。1.2 为什么不适合一开始就把演员表、影厅表、座位表都加进去很多人在拿到电影网站题目后第一反应是功能越多越好。于是把演员、导演、影厅、排片、座位全部做成表甚至想加一个在线选座系统。功能设计当然可以这样做但它会带来一系列连锁问题表结构数量增加多表关联复杂。后台维护工作量翻倍。前端页面数量暴涨。评审和同学关注点就会从“业务逻辑是否完整”转向“为什么这里还没实现”。这个题目在多数场景下是练手和答辩项目不是要做一个商业级票务平台。比功能数量更重要的是核心流程是否跑通、代码结构是否清晰、异常处理是否到位。建议第一版只保留电影、分类、用户、评论、收藏、管理员这几个核心概念。演员、导演可以先作为电影表的字符串字段保存例如director、actors不额外建表。等基础版本稳定后再考虑是否拆成独立的演员表做多对多关系。1.3 哪些人会用到这套系统评审和面试会关注什么第一种是刚学完JavaWeb的后端初学者主要目的是把SSM或传统Servlet写法升级成SpringBoot工程顺便了解Vue3。第二种是准备毕业设计的在校生。这种场景下评审老师往往不会细看每一个按钮是否能用而是先问你整个项目分成几个模块、数据库有哪些表、遇到跨域问题怎么解决、登录状态怎么管理。如果你的项目只有一堆页面和接口却没有办法清楚表达设计理由很容易扣分。第三种是有工作经验但想补Vue3技能的开发者或者想拿开源项目作为简历素材的人。这种读者通常更关心目录结构、Api设计规范、接口权限、部署方式等工程化内容。所以文章里我会把后端工程结构和前端封装方式一起写清楚不只给零散代码。如果你把这个项目放在简历里建议在项目描述里突出两个点一个是你独立完成了从数据库设计到前后端联调的全流程另一个是你解决了某些具体问题比如JWT鉴权、文件上传、跨域代理、部署后接口404等等。这两个点比单纯写“熟悉SpringBoot、Vue3”更有说服力。2. 开发环境与项目结构先把版本组合锁稳2.1 后端环境JDK、SpringBoot、MySQL、MyBatis相关选型电影网站系统的后端推荐用SpringBoot MySQL MyBatis或MyBatis-Plus。这个组合资料多、坑少、面试里也常见。环境版本方面我比较推荐的组合是JDK1.8或者11。如果你的SpringBoot版本是2.7.xJDK1.8完全够用。SpringBoot2.7.x。很多教程和开源代码都基于这个版本遇到问题时最容易搜到答案。MySQL5.7或8.0。学习阶段用8.0问题不大注意数据库驱动配置的区别。MyBatis-Plus如果你不想手写大量CRUD SQL用MyBatis-Plus确实能省很多时间。IDEIDEA或Eclipse都可以IDEA对SpringBoot支持更完善。有一个常见误区觉得SpringBoot 3.x更“新”所以必须用3.x。其实对电影网站这种常规项目3.x和2.7.x在业务代码上差别不大但3.x要求JDK17起步部分老的第三方starter可能还没适配。如果只是为了把项目跑通并重点研究业务逻辑没必要在版本上冒险。像Spring Boot 2.7.x搭配MyBatis-Plus是相对成熟稳定的组合。如果你的电脑已经装了JDK17或更高版本也可以直接用SpringBoot3.x。这时候要注意依赖坐标可能不同比如MyBatis-Plus需要引入mybatis-plus-spring-boot3-starter。javax.servlet相关包名在3.x里变成jakarta.servlet。如果网上搜到的是SpringBoot2的代码复制时容易遇到包名不存在的报错。2.2 前端环境Node、Vite、Vue3和组件库Vue3现在主流搭配是Vite构建工具。Vite启动很快开发体验明显好于Webpack。基础环境建议Node.js16.0以上建议18或20稳定性更好。Vue3.x。构建工具Vite。HTTP库Axios。UI组件库Element Plus或Naive UI。Element Plus资料多、表格和表单组件完善很适合后台管理页面。路由Vue Router 4。状态管理Pinia它是Vue3官方推荐的状态管理库。前端项目不需要一开始就引入所有依赖。创建完项目后先加上Vue Router、Axios和一套UI组件库就行。Pinia可以在真正需要共享用户状态时再加不用提前堆一堆依赖。2.3 前后端双工程结构应该怎么规划前后端分离项目建议在同一个根目录下维护两个子目录比如movie-system/ ├── backend/ # SpringBoot后端 │ ├── src/main/java │ └── src/main/resources ├── frontend/ # Vue3前端 │ ├── src │ ├── index.html │ └── package.json └── README.md后端代码内部通常按包名划分职责我习惯这样分com.example.movie ├── common/ # 统一返回结果、异常处理、状态码 ├── config/ # 跨域配置、MyBatis-Plus配置、静态资源映射 ├── controller/ # 接口层 ├── entity/ # 实体类 ├── mapper/ # MyBatis-Plus的Mapper接口 ├── service/ # 业务逻辑层 ├── utils/ # JWT工具类等 └── MovieApplication.java前端src目录下面建议按页面和功能拆分src/ ├── api/ # 接口封装movie.js、user.js、admin.js ├── router/ # 路由配置 ├── stores/ # Pinia状态 ├── views/ # 页面组件首页、电影详情、后台管理 ├── components/ # 通用组件 ├── utils/ # axios实例、token处理 └── App.vue这个结构没有标准答案但要做到“谁负责什么”尽量明确。页面组件只负责渲染和交互请求通过api目录统一发后端接口只负责业务逻辑不要在Controller里写一大串SQL逻辑。2.4 版本不同引起的典型坑位我见过不少刚接触前后端分离的人项目跑不起来并不是因为代码逻辑错而是版本组合出了问题。常见现象包括SpringBoot版本太高导致自动配置类路径找不到启动报错后查遍代码也没发现问题。JDK和SpringBoot主版本不匹配比如JDK8跑SpringBoot3.x项目直接启动失败。Node版本过低运行npm create vite时提示不支持。MySQL 8.0的驱动写法是com.mysql.cj.jdbc.Driver如果你的配置还是旧的com.mysql.jdbc.Driver会报驱动类不存在。本机多个JDK之间切换时IDEA里Project SDK和Maven用的Java版本不一致导致编译报错。处理版本问题没有捷径最好的方式是先创建项目确认能启动一个空项目之后再引入业务代码。如果启动报错优先看控制台第一行是“编译错误”还是“连接超时”还是“依赖下载失败”这个判断比盲目百度更高效。3. 打通最小可运行闭环别急着写全部页面3.1 创建后端工程并准备基础依赖我先说最小闭环的目标你打开前端页面能看到后端返回的电影列表。为了达成这个目标需要先有后端工程、数据库表、一个真实接口以及能消费接口的前端页面。创建后端工程有两种方式一种是在IDEA里通过Spring Initializr生成另一种是直接访问Spring Initializr网站下载。注意这时候不需求把MySQL、MyBatis、JWT全部勾选可以先只引入最核心的依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 根据实际引入的稳定版本选择SpringBoot2项目通常用 mybatis-plus-boot-starter -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version填写你确认可用的版本/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies如果你使用SpringBoot3.x需要确认依赖坐标和包名差异。示例里标“填写你确认可用的版本”意思是不要盲目复制数字最好以当时Maven仓库里能正常拉取到的最新稳定版为准。原生的SpringBoot starter依赖可以交给SpringBoot父工程管理版本单独引入的MyBatis-Plus最好自己锁一个稳定版本。3.2 准备数据库表和初始数据电影网站的核心表不要一开始设计得很复杂。先有一个movie表就能跑通最基础的数据链路。CREATE TABLE movie ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, title VARCHAR(200) NOT NULL COMMENT 电影名称, cover_url VARCHAR(500) DEFAULT NULL COMMENT 海报地址, category VARCHAR(100) DEFAULT NULL COMMENT 分类比如动作、科幻, director VARCHAR(100) DEFAULT NULL COMMENT 导演, actors VARCHAR(500) DEFAULT NULL COMMENT 主演多个用逗号分隔, region VARCHAR(100) DEFAULT NULL COMMENT 地区, release_date DATE DEFAULT NULL COMMENT 上映日期, rating DECIMAL(3,1) DEFAULT NULL COMMENT 评分, summary TEXT COMMENT 简介, status TINYINT DEFAULT 1 COMMENT 上架状态1上架 0下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT电影表;字段命名建议使用下划线MyBatis-Plus里可以开启驼峰映射这样Java实体类直接用releaseDate也能和数据库release_date对应。不要把图片以BLOB方式直接塞进数据库。数据库只存图片的URL地址图片文件单独放到后端某个目录或对象存储中。电影表建好后可以手动插入几条完整的示例数据便于前端调试。3.3 写一个真实接口比如电影分页列表如果只是为了验证闭环最简单的方式是先写一个查询电影列表的接口。Entity实体类可以用一个简单的Java类表示Data TableName(movie) public class Movie { private Long id; private String title; private String coverUrl; private String category; private String director; private String actors; private String region; private LocalDate releaseDate; private BigDecimal rating; private String summary; private Integer status; private LocalDateTime createTime; }Controller层提供一个GET接口。为了后续扩展方便建议直接做成分页参数RestController RequestMapping(/api/movie) public class MovieController { Resource private MovieService movieService; GetMapping(/list) public ResultPageMovie list( RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize) { LambdaQueryWrapperMovie wrapper new LambdaQueryWrapper(); wrapper.eq(Movie::getStatus, 1) .orderByDesc(Movie::getCreateTime); PageMovie page movieService.page(new Page(pageNum, pageSize), wrapper); return Result.success(page); } }这里我用了Result这样一个统一返回类实际项目中很常见。返回结构大致是{ code: 200, message: success, data: { records: [], total: 0 } }先不要纠结接口写得好不好能用就行。等后端跑起来后用浏览器直接访问http://localhost:8080/api/movie/list如果能看到JSON说明后端这个链路正常了。3.4 创建前端项目并连接后端接口前端部分可以使用Vite快速创建npm create vitelatest frontend -- --template vue cd frontend npm install npm run dev如果你需要路由和HTTP请求再安装依赖npm install vue-router4 axios element-plus然后把开发服务器代理到后端端口这一步是为了避免接口调试时被浏览器跨域拦截。在vite.config.js里加入代理import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { host: 0.0.0.0, port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })配置完成后前端代码统一请求/api/...前缀Vite会自动把请求转发到http://localhost:8080。这样开发阶段可以避免跨域问题不需要在后端写比较宽松的CORS配置。前端页面先别急着做复杂布局。使用最简单的onMounted钩子请求接口script setup import { ref, onMounted } from vue import request from ../utils/request const movieList ref([]) onMounted(async () { const res await request.get(/movie/list, { params: { pageNum: 1, pageSize: 10 } }) movieList.value res.data.records }) /script template div v-foritem in movieList :keyitem.id {{ item.title }} /div /templateVue3的组合式API里ref用来声明响应式数据onMounted相当于原来的mounted生命周期钩子。这里正好能体会到Vue3和Vue2写法上的差异相关逻辑可以按功能组织而不是强行拆到options对象里。当浏览器页面能显示数据库里的电影名称时最小闭环就算通了。接下来再去扩展页面和功能心态会稳很多。4. 把核心业务补完整登录、评论收藏、后台维护4.1 用户注册登录和JWT鉴权流程电影网站的很多业务需要登录后才能操作例如收藏电影、发表评论。常见的做法是用JWT做无状态登录。流程大概是这样用户提交用户名、密码进行注册。后端把密码加密后存储。推荐使用Spring Security的BCryptPasswordEncoder或者SpringBoot自带的加密工具。用户登录成功后后端生成一个包含用户ID和过期时间的Token返回给前端。前端把Token保存到localStorage或Pinia中并在Axios请求拦截器里自动加上Authorization: Bearer token。后端通过拦截器或过滤器校验Token如果Token无效或过期则返回401状态码。前端收到401状态码后清除本地登录状态并跳转登录页。这套逻辑不需要做得很重。对于电影网站这种项目你不需要把Spring Security的所有过滤器链都配一遍用SpringBoot拦截器配合JWT工具类足够。关键是理解“状态由Token携带”和“后端受保护接口必须做校验”这两件事。如果被问到为什么不用Session可以从前后端分离部署角度解释前端页面和后端服务可能不在同一台服务器上使用Session存在跨域和集群共享问题而JWT把用户信息放在客户端后端通过签名验证即可服务端可以保持无状态。但也要知道JWT的缺点签发后很难主动让其失效所以登录过期时间不能设置太长业务上需要禁用用户时通常还要结合用户状态字段来判断。4.2 基于用户状态的评论与收藏模块最小闭环跑通后评论和收藏模块是添加用户体系的自然延伸。数据库设计上建议单独建评论表和收藏表不要在电影表里存评论内容CREATE TABLE comment ( id BIGINT NOT NULL AUTO_INCREMENT, movie_id BIGINT NOT NULL COMMENT 电影ID, user_id BIGINT NOT NULL COMMENT 评论用户ID, content VARCHAR(500) NOT NULL COMMENT 评论内容, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT电影评论表; CREATE TABLE favorite ( id BIGINT NOT NULL AUTO_INCREMENT, movie_id BIGINT NOT NULL, user_id BIGINT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT电影收藏表;实现评论列表时前端需要展示用户名或头像所以后台查询不能只查comment表还需要关联user表把用户名映射出来。这时可以编写SQL联查也可以在实体中增加一个userName字段由Mapper填充。收藏功能有一个高频问题重复收藏。通常做法是在收藏表给movie_id和user_id加上唯一索引这样数据库层面就能挡住重复提交。接口设计时要注意评论内容来自用户输入后端不能直接把内容原样拼接SQL返回必须使用参数绑定方式防止SQL注入。这不是某个模块独有的问题而是所有涉及用户输入的接口都必须注意的规范。4.3 后台管理电影维护、海报上传与上架下架后台管理模块建议单独使用一套前端页面比如/admin路径管理员登录后进入。业务功能一般包括管理员登录。新增/编辑电影。上传电影海报。将电影设置为上架或下架状态。查看和删除用户评论。管理用户状态。技术上难度不大但有几个点容易踩坑第一上传照片的后端接口如果只接收文件返回给前端的是一个可访问的图片URL。后端需要把文件保存到一个固定目录并且配置静态资源映射这样前端才能用图片地址访问。第二不要直接把原文件名保存下来否则不同用户上传同名文件会互相覆盖。建议用UUID或时间戳重新生成文件名。例如20250112103000-随机数.jpg。第三上架下架不等于删除。页面要把上架下架逻辑处理好但管理后台最好保留数据避免误删核心记录。通常电影表里一个status字段就足够实现。第四后台管理的接口必须做权限区分不能只靠前端隐藏入口。普通用户如果直接调用后台新增接口应该被后端拦截器拒绝。如果时间不够至少也要按管理员角色做鉴权。4.4 前后端接口设计约定和返回结构多个业务模块开发完成后要回头统一接口风格否则页面越写越乱。建议遵循下面几条路径统一以/api开头例如/api/movie/list、/api/user/login。请求方式语义清晰查询用GET新增用POST更新用PUT删除用DELETE。统一返回结构。不用有些接口返回对象直接嵌套有些又只返回一个布尔值。错误码要有区分度。业务参数错误、未登录、无权限、系统异常分别使用不同code或HTTP状态码。接口参数尽量使用DTO接收而不是把所有参数都塞成Map。统一返回结构之后前端Axios拦截器也容易做统一处理。例如当code表示未登录时自动跳转登录页页面里就不用每个接口重复写一段弹登录提示的逻辑。5. 参数边界和性能优化先看这些再谈扩展5.1 分页参数和统一返回格式的细节开发中很多人会直接查询所有电影记录再在前端分页数据量小时没问题数据量稍大后就不行了。电影网站系统至少要做到后端分页接口接收pageNum和pageSize返回当前页记录和总条数。分页参数要注意边界pageNum至少从1开始如果用户传0或负数后端要修正。不要指望前端一定传正确。pageSize不能无限大。最好是限制最大100防止有人一次性拉走全表数据。查询结果中的总条数total要返回不然前端无法正确显示总页数。排序字段如果由前端传入必须做好白名单不能直接把字段名拼进SQL。拼SQL容易出SQL注入问题而且不好排查。列表字段也不要使用select *。后台程序连自己的表虽然不至于崩溃但输出一切不需要的字段会浪费传输和内存尤其是summary这类长文本。建议在查询时只查询列表需要的字段点击详情后再加载完整内容。5.2 文件上传目录、静态资源映射和大小限制电影海报和评论头像都会涉及文件上传。本地上传方案可以参考这样的流程后端保存文件时最终路径比如是/upload/movie/20250112103000-abc.jpg然后通过WebMvcConfigurer配置静态资源映射Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceHandler(file: uploadDir /); }开发环境下这样处理很方便但部署到服务器时要注意上传目录要放在系统磁盘中一个独立路径不要放在Java的临时目录。不要把上传路径写死在代码里最好放到配置文件。如果要长期保存需要定期备份。如果有多台服务器或将来迁移环境本地文件存储会非常麻烦应该考虑使用对象存储服务。SpringBoot上传文件默认有大小限制。如果上传大尺寸海报时发现超出限制不能只看后端日志还要检查前端请求有没有被网关或代理限制。如果只是后端单机调试可以先统一设置spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB5.3 缓存、搜索和并发量并不是越复杂越好到一个阶段后很多人会想把项目填充一些中间件进去比如Redis、Elasticsearch。这件事要克制。一个电影网站在学习阶段不会有多少真实并发引入Redis确实能让项目看起来更成熟但前提是你要真的想清楚缓存了什么、如何失效。比较适合加缓存的场景是首页热门电影列表这个数据短时间内不会频繁变化又可能被所有人访问。在Redis里缓存一份JSON比每次请求都查MySQL要合理。按关键词搜索电影数据量不大时用MySQL的like %关键词%完全够用。只有电影数据量大到几十万上百万条或者需要对中文分词做模糊匹配时才需要考虑Elasticsearch。所以普通项目里不要硬上搜索引擎很多同学把ES加进来后最后一个最基本的功能没写好反而在讲项目时漏洞百出。如果你确实想展示工程能力更稳妥的方向是加上接口参数校验、全局异常处理、日志记录、统一鉴权。这些内容面试官能看懂也更能体现代码习惯。5.4 低配置环境下的运行边界电影网站系统对硬件要求不高。如果一个项目只跑在本地普通4核8G或2核4G的机器完全能跑。但低配置下要注意几个边界不要在代码里写定时任务去同时扫描大量电影信息也不要在启动时做特别耗时的数据初始化。如果使用IDEA同时打开前后端两个工程又开着MySQL和多个浏览器页面内存会明显吃紧这种情况可以关掉不用的插件。前后端项目同时启动时如果电脑风扇很响先看是哪个进程占用高是MySQL、Node还是Java进程。学习阶段的并发数不必追求很高。课程设计里写“支持高并发”很容易被评委追问要根据实际环境给自己留好表述余地。6. 部署上线与联调排错6.1 本地开发和服务器部署的差别开发环境可以启动两个服务Vite开发服务器占用5173端口SpringBoot后端占8080端口通过代理转发请求。但部署到Linux服务器时通常不会再同时跑开发服务器而是把Vue项目构建成静态文件由Nginx提供访问把接口反向代理到SpringBoot服务。服务器端还需要注意数据库连接地址不能写localhost时碰巧连到服务器本机以外的库要以实际环境为准。后端配置文件里也建议区分application-dev.yml和application-prod.yml本地开发和服务器部署使用不同的数据库账号、日志级别和上传路径。6.2 前端打包、后端构建和Nginx的方式前端执行npm run build执行后会自动生成dist目录。这个目录就是所有静态文件。你可以把dist目录复制到服务器某个路径比如/var/www/movie然后配置Nginx。后端构建mvn clean package -DskipTests构建后生成一个可执行的Jar包通过Java命令运行java -jar movie-backend-0.0.1-SNAPSHOT.jar生产环境建议不要让Java进程直接占用当前终端可以使用nohup或systemd等方式管理日志也需要输出到文件里。正常退出程序不能直接把终端关掉否则SpringBoot进程会被终止。Nginx配置示例server { listen 80; server_name your-domain.com; root /var/www/movie; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这里要注意如果前端静态资源和后端接口部署在同一台服务器上Nginx处理/api前缀的接口时proxy_pass后面的地址是否带路径会影响最终转发结果。到底是保留/api还是去掉取决于后端接口是否本来就以/api开头。这个细节非常容易导致“前端能打开页面但请求报404”。建议自己在配置好Nginx后用curl测试真实请求路径再去猜前端代码问题。6.3 高频报错跨域、404、401和中文乱码先看跨域。使用Vite代理的开发环境下一般不会遇到但如果你直接用前端地址访问后端接口比如后端在8080前端在5173浏览器会因为同源策略拒绝请求。解决办法两个一个是开发阶段像前面那样配置代理一个是在后端配置全局CORS。很多人两个方案都做结果带了“Access-Control-Allow-Origin”响应头又说重复问题反而复杂化。再看404。页面打开正常、接口返回404常见原因是路径不对。有几种情况前端请求/api/movie/list后端Controller映射却是/movie/list忘记类上的/api前缀。请求使用POST后端接口是GET。后端路径带路径参数前端没有传对。路由使用了history模式Nginx没有配置try_files回退到index.html导致前端刷新后出现404。再看401或403。这通常和登录状态有关。先确认请求头有没有携带Token然后确认Token有没有过期最后看后端拦截器是否把登录接口也拦截了。有些人的登录接口一直报401是因为拦截器注册时没有放行登录接口。中文乱码则要区分阶段。如果从前端传到后端后数据库里正常只是接口返回乱码很可能是字符集问题如果数据库里就已经是乱码那大概率是MySQL连接参数或建表字符集问题。建议使用MySQL8和utf8mb4连接URL中配置characterEncodingutf8同时确保后端返回的Content-Type包含UTF-8。6.4 面对“接口通了页面没数据”时的排查顺序这类问题最让人烦躁因为不是程序启动报错而是返回结果不对或页面空白。我的经验是先按下面顺序排查打开浏览器开发者工具看Network请求是否发出状态码是多少。查看请求返回的JSON内容是空数组、报错信息还是字段对不上。如果JSON有数据但前端不显示确认Vue绑定字段名和返回字段名是否一致。字段不一致是最常见的“页面没数据”原因。检查日志看后端是否真的执行了查询。查看SQL日志看拼接出来的SQL和条件是否符合预期。如果分页查询没问题再检查当前页渲染时有没有因为一条记录字段为空导致页面报错把整个列表卡住。不要把精力一开始就放在改代码上。先确认问题是出在前端渲染、后端数据还是网络请求再决定改哪里。这样才能避免把“字段没对上”误判成“后端接口坏了”。6.5 如果要把项目继续做深优先考虑什么方向如果你已经完成了上面大部分功能但仍然想继续扩展我建议优先考虑这些方向一是把图片存储从本地目录切换到对象存储。这样前端地址稳定后端也不担心重启丢文件。二是增加管理端日志。谁在什么时间修改了哪部电影、删除了哪条评论这些操作都记录下来。对后台系统来说这个比做一个炫酷图表更实在。三是用Pinia管理用户的登录状态和权限。比如管理员登录后导航菜单多加载一个“系统管理”入口普通用户登录后不显示后台菜单。四是把列表查询抽成统一封装。比如搜索条件、排序条件、分页参数通过一个通用查询对象传递避免每个Controller都写重复的分页逻辑。说到底一个电影网站系统是不是做得完整核心不在于用了多少热门框架而在于你能不能把数据流讲清楚电影数据从后台录入到数据库接口把数据返回给VueVue根据用户输入搜索或筛选列表用户登录后收藏和评论管理员在后台维护内容。把这条链路做扎实了不管页面里是否有没有多少动画效果项目本身已经达到合格标准了。
返回列表