Spring Boot + Vue 3 + MySQL 全栈电影评论网站开发实战

发布时间:2026/8/3 13:01:08
Spring Boot + Vue 3 + MySQL 全栈电影评论网站开发实战 在实际 Java Web 项目中一个完整的电影评论网站是检验全栈开发能力的经典场景。它要求开发者不仅要串联起 Java 后端、Vue 前端、Spring Boot 框架和 MySQL 数据库还要处理用户认证、数据交互、前后端分离部署等一系列工程问题。很多同学在毕业设计或入门全栈时虽然能分别找到 Java、Vue、Spring Boot、MySQL 的教程但将它们有机整合成一个可运行、可演示、可答辩的项目时常常在环境配置、接口联调、数据结构和部署环节遇到阻碍。本文将以一个电影评论网站为蓝本带你从零开始使用 Spring Boot 构建 RESTful API 后端使用 Vue 3 构建 SPA 前端并完成数据库设计、前后端联调及基础部署。整个过程会详细解释每一步的技术选型理由、配置关键点和常见排错路径确保你不仅能跑通项目更能理解每个环节背后的设计逻辑。1. 项目整体架构与技术栈选型在开始编码之前明确项目的技术边界和组件职责至关重要。一个清晰的分层架构能避免后期代码混乱和调试困难。1.1 为什么选择 Spring Boot Vue MySQL 组合对于电影评论网站这类信息展示与用户交互并重的项目Spring Boot Vue MySQL 是一个经过大量实践验证的稳健组合。Spring Boot 提供了快速构建 RESTful 服务的脚手架其自动配置和起步依赖能极大简化后端开发Vue 作为渐进式前端框架数据驱动视图的特性非常适合构建动态交互的评论界面MySQL 作为关系型数据库在存储结构化的电影信息、用户数据和评论内容方面具有天然优势且事务支持能保证数据一致性。这种前后端分离的架构使得后端可以专注于业务逻辑和数据安全前端可以专注于用户体验和界面渲染两者通过 HTTP API 进行清晰的数据交换。1.2 系统核心模块与数据流设计一个基础的电影评论网站通常包含以下核心模块用户模块注册、登录、登出、个人信息管理。电影模块电影信息的增删改查CRUD、分类浏览、搜索。评论模块对电影的评论发布、查看、删除通常用户只能删除自己的评论。交互模块对电影或评论的点赞、收藏。数据流向遵循典型的前后端分离模式用户在 Vue 前端页面进行操作如点击提交评论 - Vue 通过 Axios 等库发送 HTTP 请求到 Spring Boot 后端定义的 API 接口 - Spring Boot 控制器Controller接收请求调用服务层Service处理业务逻辑 - 服务层调用数据访问层Repository与 MySQL 数据库交互 - 处理结果沿原路返回最终由 Vue 更新页面视图。2. 后端开发Spring Boot 与 MySQL 集成后端是整个应用的数据和逻辑核心。我们将从数据库设计开始逐步构建 Spring Boot 项目。2.1 数据库设计与建表根据核心模块我们设计四张主要表user用户表、movie电影表、comment评论表、like点赞表。这里使用 MySQL 8.0。首先创建数据库CREATE DATABASE IF NOT EXISTS movie_review_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE movie_review_db;接着创建表结构。注意字段类型、索引和约束的设计。-- 用户表 CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名唯一, password varchar(255) NOT NULL COMMENT 加密后的密码, email varchar(100) DEFAULT NULL COMMENT 邮箱, avatar varchar(500) DEFAULT NULL COMMENT 头像URL, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT用户表; -- 电影表 CREATE TABLE movie ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, title varchar(200) NOT NULL COMMENT 电影标题, director varchar(100) DEFAULT NULL COMMENT 导演, actors varchar(500) DEFAULT NULL COMMENT 主演, release_year int DEFAULT NULL COMMENT 上映年份, description text COMMENT 剧情简介, poster_url varchar(500) DEFAULT NULL COMMENT 海报图片URL, avg_rating decimal(3,1) DEFAULT 0.0 COMMENT 平均评分, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_title (title), KEY idx_release_year (release_year) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT电影表; -- 评论表 CREATE TABLE comment ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, movie_id bigint NOT NULL COMMENT 关联电影ID, user_id bigint NOT NULL COMMENT 关联用户ID, content text NOT NULL COMMENT 评论内容, rating tinyint DEFAULT NULL COMMENT 用户评分1-5, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_movie_id (movie_id), KEY idx_user_id (user_id), CONSTRAINT fk_comment_movie FOREIGN KEY (movie_id) REFERENCES movie (id) ON DELETE CASCADE, CONSTRAINT fk_comment_user FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT评论表; -- 点赞表可扩展为收藏 CREATE TABLE user_like ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, user_id bigint NOT NULL COMMENT 用户ID, target_type tinyint NOT NULL COMMENT 点赞目标类型1-电影2-评论, target_id bigint NOT NULL COMMENT 点赞目标ID, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_user_target (user_id,target_type,target_id), -- 防止重复点赞 KEY idx_target (target_type,target_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT用户点赞表;设计要点说明使用utf8mb4字符集以支持完整的 Unicode包括 Emoji 表情评论中可能出现。为频繁查询的字段如movie.title,comment.movie_id建立索引提升查询性能。使用外键约束保证数据完整性ON DELETE CASCADE表示主表记录删除时关联的从表记录自动删除。user_like表设计了联合唯一索引确保一个用户对同一目标只能点赞一次。movie.avg_rating字段通过触发器或应用层逻辑更新这里为了简化可由服务层计算。2.2 初始化 Spring Boot 项目与依赖配置使用 Spring Initializr或 IDE 如 IntelliJ IDEA 内置的创建工具生成项目。关键依赖选择Spring Web: 用于构建 RESTful API。Spring Data JPA: 简化数据库操作。MySQL Driver: 连接 MySQL 数据库。Lombok: 简化实体类代码可选但推荐。Spring Security: 用于用户认证和授权本文为简化先使用基于 Session 的简单认证生产环境需更完善方案。生成的pom.xml关键依赖部分如下dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies在application.yml或application.properties中配置数据库连接和 JPA 属性。这里使用 YAML 格式spring: datasource: url: jdbc:mysql://localhost:3306/movie_review_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: your_username # 替换为你的数据库用户名 password: your_password # 替换为你的数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # 开发环境可用 update生产环境建议设为 validate 或 none并通过 SQL 脚本管理表结构 show-sql: true # 开发时显示 SQL便于调试 properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true # 格式化输出的 SQL server: port: 8080 # 后端服务端口注意ddl-auto: update在开发初期很方便但存在覆盖数据的风险。生产环境务必使用validate仅验证表结构或none并通过 Flyway/Liquibase 等工具进行版本化数据库迁移。2.3 实体类Entity与数据访问层Repository编写根据数据库表创建对应的 JPA 实体类。使用 Lombok 注解减少 getter/setter 等样板代码。User实体类示例package com.example.moviereview.entity; import lombok.Data; import javax.persistence.*; import java.time.LocalDateTime; Entity Table(name user) Data public class User { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(name username, nullable false, unique true, length 50) private String username; Column(name password, nullable false) private String password; Column(name email, length 100) private String email; Column(name avatar, length 500) private String avatar; Column(name create_time, updatable false) private LocalDateTime createTime; Column(name update_time) private LocalDateTime updateTime; PrePersist protected void onCreate() { createTime LocalDateTime.now(); updateTime LocalDateTime.now(); } PreUpdate protected void onUpdate() { updateTime LocalDateTime.now(); } }Movie和Comment实体类结构类似需定义好关联关系。例如在Comment实体中Entity Table(name comment) Data public class Comment { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; ManyToOne(fetch FetchType.LAZY) JoinColumn(name movie_id, nullable false) private Movie movie; ManyToOne(fetch FetchType.LAZY) JoinColumn(name user_id, nullable false) private User user; Column(name content, nullable false, columnDefinition TEXT) private String content; Column(name rating) private Integer rating; // 1-5 Column(name create_time, updatable false) private LocalDateTime createTime; PrePersist protected void onCreate() { createTime LocalDateTime.now(); } }接着为每个实体创建对应的 Repository 接口继承JpaRepository即可获得基础的 CRUD 方法。package com.example.moviereview.repository; import com.example.moviereview.entity.Movie; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; Repository public interface MovieRepository extends JpaRepositoryMovie, Long { // 可以自定义查询方法 ListMovie findByTitleContaining(String keyword); ListMovie findByReleaseYearOrderByCreateTimeDesc(Integer year); }2.4 服务层Service与控制器Controller实现服务层封装业务逻辑控制器处理 HTTP 请求和响应。以电影查询和评论发布为例。首先创建MovieServicepackage com.example.moviereview.service; import com.example.moviereview.entity.Movie; import com.example.moviereview.repository.MovieRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.Optional; Service public class MovieService { Autowired private MovieRepository movieRepository; public PageMovie getAllMovies(Pageable pageable) { return movieRepository.findAll(pageable); } public OptionalMovie getMovieById(Long id) { return movieRepository.findById(id); } public ListMovie searchMoviesByTitle(String keyword) { return movieRepository.findByTitleContaining(keyword); } public Movie saveOrUpdateMovie(Movie movie) { return movieRepository.save(movie); } public void deleteMovie(Long id) { movieRepository.deleteById(id); } }然后创建MovieController提供 REST APIpackage com.example.moviereview.controller; import com.example.moviereview.entity.Movie; import com.example.moviereview.service.MovieService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; import java.util.Map; RestController RequestMapping(/api/movies) public class MovieController { Autowired private MovieService movieService; GetMapping public ResponseEntityMapString, Object getMovies( RequestParam(value page, defaultValue 0) int page, RequestParam(value size, defaultValue 10) int size, RequestParam(value sortBy, defaultValue createTime) String sortBy, RequestParam(value direction, defaultValue desc) String direction) { Sort sort direction.equalsIgnoreCase(asc) ? Sort.by(sortBy).ascending() : Sort.by(sortBy).descending(); Pageable pageable PageRequest.of(page, size, sort); PageMovie moviePage movieService.getAllMovies(pageable); MapString, Object response new HashMap(); response.put(movies, moviePage.getContent()); response.put(currentPage, moviePage.getNumber()); response.put(totalItems, moviePage.getTotalElements()); response.put(totalPages, moviePage.getTotalPages()); return ResponseEntity.ok(response); } GetMapping(/{id}) public ResponseEntityMovie getMovieById(PathVariable Long id) { return movieService.getMovieById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } GetMapping(/search) public ResponseEntityListMovie searchMovies(RequestParam String keyword) { ListMovie movies movieService.searchMoviesByTitle(keyword); return ResponseEntity.ok(movies); } // 后续可添加需要权限的 POST, PUT, DELETE 接口 }评论相关的CommentService和CommentController逻辑类似但发布评论时需要关联当前登录用户。这里涉及用户认证为简化演示我们先假设通过某种方式如拦截器能从请求中获取用户ID。一个简单的实现是在请求头中传递用户标识仅用于学习生产环境必须使用安全的认证机制如 JWT。2.5 处理跨域请求CORS由于前端Vue和后端Spring Boot通常运行在不同端口如 8080 和 3000浏览器会因同源策略阻止请求。需要在 Spring Boot 后端配置 CORS。创建一个配置类package com.example.moviereview.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; Configuration public class CorsConfig { Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { Override public void addCorsMappings(CorsRegistry registry) { // 开发环境允许所有来源生产环境需指定具体前端域名 registry.addMapping(/api/**) .allowedOrigins(http://localhost:3000) // Vue 开发服务器地址 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true); // 如果前端需要传递 Cookie 或 Authorization 头此项应为 true } }; } }至此一个具备基础 CRUD 功能的 Spring Boot 后端 API 服务已经搭建完成。可以通过mvn spring-boot:run或运行主类启动应用并使用 Postman 或浏览器测试GET http://localhost:8080/api/movies等接口。3. 前端开发Vue 3 项目构建与界面实现前端负责呈现电影列表、详情页、评论表单和用户交互。我们将使用 Vue 3 的 Composition API 和 Vue Router、Axios 等常用库。3.1 初始化 Vue 项目与安装依赖使用 Vue CLI 或 Vite 创建项目。这里推荐使用 Vite因其更轻量快速。# 使用 npm npm create vuelatest movie-review-frontend # 按照提示选择项目特性推荐加入 TypeScript, Vue Router, Pinia (状态管理) cd movie-review-frontend npm install # 安装额外依赖Axios (HTTP请求), Element Plus (UI组件库可选) npm install axios npm install element-plus element-plus/icons-vue项目结构大致如下movie-review-frontend/ ├── public/ ├── src/ │ ├── assets/ │ ├── components/ # 可复用组件 │ ├── router/ # 路由配置 │ ├── stores/ # Pinia 状态管理 │ ├── views/ # 页面组件 │ ├── App.vue │ ├── main.ts │ └── vite-env.d.ts ├── index.html ├── package.json └── vite.config.ts3.2 配置 Axios 与 API 调用封装在src目录下创建utils/request.ts文件封装 Axios 实例统一处理请求基地址、超时、请求/响应拦截器。// src/utils/request.ts import axios from axios; import { ElMessage } from element-plus; import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from axios; // 创建 axios 实例 const service: AxiosInstance axios.create({ baseURL: http://localhost:8080/api, // 后端 API 基地址 timeout: 10000, // 请求超时时间 }); // 请求拦截器 service.interceptors.request.use( (config: AxiosRequestConfig) { // 在发送请求之前做些什么例如添加 token // const token localStorage.getItem(token); // if (token) { // config.headers[Authorization] Bearer ${token}; // } return config; }, (error) { // 对请求错误做些什么 console.error(Request Error:, error); return Promise.reject(error); } ); // 响应拦截器 service.interceptors.response.use( (response: AxiosResponse) { // 对响应数据做点什么 const res response.data; // 这里根据后端统一的响应格式处理例如 { code: 200, data: ..., message: success } // if (res.code ! 200) { // ElMessage.error(res.message || Error); // return Promise.reject(new Error(res.message || Error)); // } return res; }, (error) { // 对响应错误做点什么 console.error(Response Error:, error); ElMessage.error(error.message || Network Error); return Promise.reject(error); } ); export default service;然后创建src/api/目录按模块组织 API 函数。例如movie.ts// src/api/movie.ts import request from /utils/request; // 获取电影列表分页 export function getMovieList(params: any) { return request({ url: /movies, method: get, params, // { page, size, sortBy, direction } }); } // 根据ID获取电影详情 export function getMovieDetail(id: number) { return request({ url: /movies/${id}, method: get, }); } // 搜索电影 export function searchMovies(keyword: string) { return request({ url: /movies/search, method: get, params: { keyword }, }); }3.3 构建核心页面组件使用 Vue 3 的script setup语法和 Composition API 编写页面。电影列表页 (src/views/MovieListView.vue)template div classmovie-list h1电影列表/h1 !-- 搜索框 -- el-input v-modelsearchKeyword placeholder搜索电影... keyup.enterhandleSearch stylewidth: 300px; margin-bottom: 20px; template #append el-button clickhandleSearch搜索/el-button /template /el-input !-- 电影卡片列表 -- el-row :gutter20 el-col :span6 v-formovie in movieList :keymovie.id el-card :body-style{ padding: 0px } shadowhover img :srcmovie.posterUrl || /default-poster.jpg classposter / div stylepadding: 14px; h3{{ movie.title }}/h3 p导演{{ movie.director }}/p p年份{{ movie.releaseYear }}/p p评分el-rate v-modelmovie.avgRating disabled show-score text-color#ff9900 score-template{value} //p div classbottom el-button typetext clickgoToDetail(movie.id)查看详情/el-button /div /div /el-card /el-col /el-row !-- 分页 -- el-pagination current-changehandlePageChange :current-pagecurrentPage :page-sizepageSize layoutprev, pager, next, jumper :totaltotal stylemargin-top: 20px; /el-pagination /div /template script setup langts import { ref, onMounted } from vue; import { useRouter } from vue-router; import { getMovieList, searchMovies } from /api/movie; import type { Movie } from /types; // 需要定义 Movie 类型 const router useRouter(); const movieList refMovie[]([]); const searchKeyword ref(); const currentPage ref(1); const pageSize ref(12); const total ref(0); const fetchMovies async (page 1) { try { const params { page: page - 1, size: pageSize.value, sortBy: createTime, direction: desc }; const res await getMovieList(params); movieList.value res.movies; total.value res.totalItems; currentPage.value page; } catch (error) { console.error(获取电影列表失败:, error); } }; const handleSearch async () { if (!searchKeyword.value.trim()) { fetchMovies(); return; } try { const res await searchMovies(searchKeyword.value); movieList.value res; total.value res.length; currentPage.value 1; } catch (error) { console.error(搜索失败:, error); } }; const handlePageChange (page: number) { fetchMovies(page); }; const goToDetail (id: number) { router.push(/movie/${id}); }; onMounted(() { fetchMovies(); }); /script style scoped .poster { width: 100%; height: 300px; object-fit: cover; } /style电影详情与评论页 (src/views/MovieDetailView.vue)需要展示电影信息和评论列表并提供发布评论的表单。其逻辑类似需要调用getMovieDetail和评论相关的 API。3.4 路由配置与状态管理在src/router/index.ts中配置路由import { createRouter, createWebHistory } from vue-router; import MovieListView from /views/MovieListView.vue; import MovieDetailView from /views/MovieDetailView.vue; // ... 导入其他视图 const routes [ { path: /, name: Home, redirect: /movies, }, { path: /movies, name: MovieList, component: MovieListView, }, { path: /movie/:id, name: MovieDetail, component: MovieDetailView, props: true, // 将路由参数 id 作为 prop 传入组件 }, // ... 其他路由如登录页、用户中心等 ]; const router createRouter({ history: createWebHistory(), routes, }); export default router;对于用户登录状态、全局提示等可以使用 Pinia 进行状态管理。创建一个userStore// src/stores/user.ts import { defineStore } from pinia; import { ref } from vue; export const useUserStore defineStore(user, () { const token ref(localStorage.getItem(token) || ); const userInfo ref(JSON.parse(localStorage.getItem(userInfo) || {})); const setToken (newToken: string) { token.value newToken; localStorage.setItem(token, newToken); }; const setUserInfo (info: any) { userInfo.value info; localStorage.setItem(userInfo, JSON.stringify(info)); }; const logout () { token.value ; userInfo.value {}; localStorage.removeItem(token); localStorage.removeItem(userInfo); }; return { token, userInfo, setToken, setUserInfo, logout }; });4. 前后端联调与项目运行前后端分别开发完成后需要进行联调确保数据能正确流动。4.1 启动后端服务确保 MySQL 服务已启动并且movie_review_db数据库及表已创建。在 Spring Boot 项目的application.yml中确认数据库连接信息正确。在项目根目录运行mvn spring-boot:run或通过 IDE 启动MovieReviewApplication主类。观察控制台日志确认无报错且看到类似Tomcat started on port(s): 8080的信息。4.2 启动前端开发服务器进入 Vue 项目根目录movie-review-frontend。运行npm run dev。Vite 通常会启动在http://localhost:3000具体看终端输出。浏览器访问http://localhost:3000应能看到电影列表页。4.3 联调测试与常见问题问题1前端访问后端 API 出现 CORS 错误现象浏览器控制台报错Access-Control-Allow-Origin。检查确认后端CorsConfig中allowedOrigins包含前端地址如http://localhost:3000。检查后端是否已重启使配置生效。解决调整 CORS 配置或在前端开发服务器配置代理在vite.config.ts中配置proxy。问题2前端请求成功但数据为空现象网络请求返回 200但data为空。检查检查后端控制器方法是否正确返回数据。使用 Postman 直接测试后端接口GET http://localhost:8080/api/movies。检查数据库movie表中是否有测试数据。可以在后端启动时通过CommandLineRunner或data.sql脚本初始化一些数据。检查前端 Axios 响应拦截器是否对数据做了额外处理导致结构不对。问题3图片等静态资源无法加载现象电影海报显示为裂图。检查movie.posterUrl字段存储的是完整的 URL 还是相对路径。如果是相对路径需要确保该路径对应的图片文件存在于后端服务的静态资源目录或专门的静态文件服务器如 Nginx下。解决开发阶段可以将图片放在后端的src/main/resources/static/目录下然后通过http://localhost:8080/图片名.jpg访问。或者使用完整的网络图片 URL。问题4分页参数传递错误现象点击分页器数据没有变化或报错。检查前端传递给后端的page参数。Spring Data JPA 的PageRequest.of(page, size)中page是从 0 开始的而 Element Plus 分页组件的current-page是从 1 开始的。需要在前端做转换如page: page - 1。5. 项目部署与生产环境考量毕业设计答辩通常需要演示因此需要将项目部署到可公开访问的服务器或本地稳定运行。5.1 后端打包与运行打包在 Spring Boot 项目根目录执行mvn clean package -DskipTests会在target目录生成movie-review-0.0.1-SNAPSHOT.jar。运行确保目标服务器已安装 Java 运行环境JRE 8 或 11。使用命令java -jar movie-review-0.0.1-SNAPSHOT.jar启动。可通过--server.port8081指定端口。生产数据库将application.yml中的数据库连接信息改为生产环境的 MySQL 地址、用户名和密码。建议使用application-prod.yml配置文件并通过--spring.profiles.activeprod激活。进程管理使用nohup或 systemd 等服务管理工具保持后端进程常驻。5.2 前端构建与部署构建在 Vue 项目根目录执行npm run build生成静态文件在dist目录。部署可以将dist目录下的文件放置到 Nginx 或 Apache 的 Web 根目录。上传到对象存储如阿里云 OSS并配置静态网站托管。使用 Docker 容器化部署。API 地址配置构建前需将src/utils/request.ts中的baseURL改为生产环境的后端 API 地址如http://your-server-ip:8080/api。更好的做法是通过环境变量注入。5.3 生产环境检查清单在将项目用于演示或上线前请对照以下清单进行检查检查项开发环境常见状态生产环境要求与建议数据库连接本地 localhost弱密码使用强密码限制访问 IP考虑连接池配置如 HikariCPCORS 配置允许localhost:*严格指定前端域名如https://your-domain.com日志输出控制台输出show-sql: true关闭 SQL 日志日志输出到文件并配置日志级别和滚动策略异常处理可能暴露堆栈信息给前端全局异常处理器返回友好的错误信息记录详细日志到后端用户认证可能简单或未实现实现完整的认证如 JWT、密码加密存储、会话管理静态资源本地文件或开发服务器使用 CDN 或专用静态资源服务器配置缓存API 文档无或简单注释使用 Swagger/OpenAPI 生成接口文档便于前后端协作和答辩展示配置管理写在application.yml敏感信息密码、密钥使用环境变量或配置中心性能未优化数据库查询考虑索引、分页前端图片懒加载、组件按需引入6. 毕业设计扩展方向与答辩准备一个基础的电影评论网站完成后可以从以下方向进行扩展提升项目复杂度和技术深度为答辩加分。6.1 功能扩展建议用户系统增强邮箱验证、第三方登录微信、GitHub、个人中心、修改密码。电影数据接入公开电影 API如 TMDB自动获取电影信息、海报和演职员表。评论系统支持回复、点赞、举报、敏感词过滤、富文本编辑。推荐系统基于用户历史评分或浏览记录实现简单的协同过滤或内容推荐。管理后台使用 Vue 或 React 构建独立的管理端实现对电影、评论、用户的管理。实时功能使用 WebSocket 实现新评论通知、在线人数统计。6.2 技术深度挖掘缓存优化使用 Redis 缓存热门电影数据、用户会话减轻数据库压力。搜索优化集成 Elasticsearch实现电影标题、简介、演员等多字段全文检索。文件上传实现用户头像、电影海报上传至云存储如阿里云 OSS、七牛云。微服务化尝试将用户服务、电影服务、评论服务拆分为独立的 Spring Boot 应用通过 Spring Cloud 组件进行通信。容器化部署编写 Dockerfile 将前后端分别容器化使用 Docker Compose 一键部署。6.3 答辩要点与文档整理毕业设计答辩时除了演示系统清晰的讲述和文档同样重要。项目介绍简明扼要说明项目背景、目标用户、核心功能。技术架构图绘制一张清晰的架构图展示前端、后端、数据库、缓存等组件及其关系。核心代码讲解准备 1-2 个核心功能的代码片段如用户登录的认证流程、电影评论的发布与关联查询解释其中的技术难点和解决方案。数据库设计展示 E-R 图解释表结构设计和关系说明索引和约束的作用。遇到的问题与解决方案准备 2-3 个在开发中遇到的实际问题如跨域、分页、N1 查询问题以及你是如何排查和解决的。项目总结与展望总结项目的收获、不足以及未来可以改进和扩展的方向。将以上内容整理成毕业设计论文或报告时确保结构完整包含需求分析、系统设计、数据库设计、详细实现、系统测试等章节并附上核心代码和运行截图。通过以上步骤你不仅完成了一个可运行、可演示的电影评论网站更掌握了从需求分析到部署上线的全链路开发流程。在实际操作中务必理解每个配置和代码块的作用而不是简单复制粘贴这样才能在遇到问题时快速定位并解决真正提升工程能力。