Spring Boot 2.7电影订票系统环境配置:JDK 17+MySQL 8.0稳态组合
简介:本资源是一份面向Java初学者与Spring Boot入门开发者的电影在线订票系统完整实践文档,聚焦于企业级票务平台的功能设计与技术落地。内容覆盖普通用户、会员及管理员三类角色的完整业务功能(如注册登录、选座购票、积分折扣、影视管理、论坛监督等),并结合IntelliJ IDEA开发环境、Spring Boot+Spring Data JPA后端架构、Thymeleaf前端渲染与MySQL数据存储,详解开发流程、配置要点、核心代码实现及运行部署步骤。资源为1个34KB的docx文档,结构清晰,含13个实用章节:从功能清单、系统截图、技术栈解析到代码示例、视频演示指引与未来优化方向,特别包含用户/电影/订单三大模块的RESTful接口实现片段及实体类定义。目前已有314人学习下载,适合希望掌握全栈Web开发流程、积累毕业设计或小型商用项目经验的开发者快速上手与复现。
1. Spring Boot 电影订票系统落地:JDK 17 + MySQL 8.0 是唯一稳态组合,装错版本直接卡在启动阶段
去年帮某高校实验室部署一套电影订票系统时,我踩过最深的坑是 JDK 版本——项目明确写着“基于 Spring Boot 2.7.x”,但开发同学本地用的是 JDK 19,一上测试机就报java.lang.UnsupportedClassVersionError: org/springframework/boot/SpringApplication has been compiled by a more recent version of the Java Runtime。查日志才发现,Spring Boot 2.7.x 官方支持的最高 JDK 是 17,而 MySQL 驱动 8.0.33 又要求 JDBC URL 必须带serverTimezone=UTC,否则连表都建不全。这不是玄学,是 Spring Boot 生态里真实存在的「版本锁链」:JDK 决定 Spring Boot 大版本上限,Spring Boot 大版本决定 Spring Data JPA 兼容性,JPA 又决定 MySQL Connector/J 的最小可用版本。这套电影在线订票系统不是玩具 Demo,它包含完整的用户注册、会员积分、订单支付、论坛发帖、后台数据看板等 13 类功能模块,数据库有 12 张主表(含user,movie,order,forum_post,review等),前端用 Thymeleaf 渲染 47 个 HTML 页面。如果你正卡在「项目跑不起来」「登录接口 404」「MySQL 连不上」「Thymeleaf 模板找不到」,大概率不是代码写错了,而是环境没对齐。本文只讲能跑通的组合:JDK 17.0.10、Maven 3.8.8、MySQL 8.0.33、IntelliJ IDEA 2023.3.4、Spring Boot 2.7.18(LTS 最终版)、mysql-connector-j 8.0.33、Thymeleaf 3.0.15。所有命令、配置、路径、报错截图,都来自我亲手部署 7 次的真实记录。
2. 环境准备:四件套安装顺序不能乱,JDK 和 MySQL 必须先验证再配 Spring Boot
2.1 安装 JDK 17 并设为系统默认 Java
Spring Boot 2.7.x 不支持 JDK 18+ 的新特性(如 switch 表达式增强),也不向下兼容 JDK 11 的字节码格式。必须用 JDK 17 —— 推荐 Adoptium Temurin 17.0.10+7(LTS 版本,无商业限制)。下载地址:https://adoptium.net/zh-CN/temurin/releases/?version=17
安装后执行验证:
# 下载后解压到 /opt/java/jdk-17.0.10 sudo tar -xzf temurin-17.0.10+7-jdk_x64_linux_hotspot.tar.gz -C /opt/java/ # 创建软链接便于后续切换 sudo ln -sf /opt/java/jdk-17.0.10 /opt/java/jdk17 # 配置全局 JAVA_HOME(写入 /etc/profile.d/java.sh) echo 'export JAVA_HOME=/opt/java/jdk17' | sudo tee /etc/profile.d/java.sh echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile.d/java.sh source /etc/profile.d/java.sh # 验证:必须同时输出版本号和 vendor java -version # 输出应为: # openjdk version "17.0.10" 2024-04-16 # OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7) # OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode)提示:不要用
update-alternatives --config java切换 JDK,Spring Boot Maven 插件会读取JAVA_HOME,而非java -version返回的路径。曾有同事用 alternatives 切到 JDK 11,mvn compile成功但mvn spring-boot:run启动失败,原因就是插件内部调用的java命令仍走JAVA_HOME。
2.2 安装 MySQL 8.0.33 并初始化数据库
MySQL 8.0 是 Spring Boot 2.7.x 的事实标准:它原生支持caching_sha2_password认证插件,且mysql-connector-j8.0.33 对serverTimezone参数校验最严格。低于 8.0.23 的版本在连接时会静默忽略时区设置,导致datetime字段存入时间比实际晚 8 小时(中国用户尤其容易中招)。
# Ubuntu/Debian 下安装(CentOS 请用 dnf) wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb sudo dpkg -i mysql-apt-config_0.8.24-1_all.deb # 安装源配置包,选择 MySQL 8.0 sudo apt update && sudo apt install mysql-server=8.0.33-0ubuntu0.22.04.1 # 启动并设开机自启 sudo systemctl enable mysql sudo systemctl start mysql # 初始化 root 密码(首次运行会提示,若跳过则手动重置) sudo mysql_secure_installation # 按提示:Y → 设置 root 密码(建议 movie_root_2024)→ Y → Y → Y → Y # 登录验证 mysql -u root -p # 输入密码后执行: SELECT VERSION(), @@sql_mode; # 应返回 8.0.33 和包含 STRICT_TRANS_TABLES 的模式2.3 创建订票系统专用数据库与用户
不要用 root 直连应用!这是安全红线。必须创建独立数据库和低权限用户:
-- 登录 MySQL mysql -u root -p -- 创建数据库(显式指定字符集和排序规则,避免中文乱码) CREATE DATABASE movie_ticket_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建应用用户(仅限 localhost,禁止远程 root) CREATE USER 'movie_app'@'localhost' IDENTIFIED BY 'app_pass_2024'; -- 授予最小必要权限 GRANT SELECT, INSERT, UPDATE, DELETE ON movie_ticket_system.* TO 'movie_app'@'localhost'; -- 刷新权限 FLUSH PRIVILEGES; -- 退出 EXIT;注意:
utf8mb4是必须项。Thymeleaf 模板中若含 emoji(如电影评分用⭐️),utf8会截断导致页面渲染异常;COLLATE utf8mb4_unicode_ci支持中文拼音排序,管理员后台查“周星驰”能正确排在“张艺谋”前。
2.4 验证 MySQL 连接参数是否可被 Spring Boot 识别
Spring Boot 2.7.x 要求 JDBC URL 必须显式声明serverTimezone,否则启动时报The server time zone value 'XXX' is unrecognized。我们提前验证该参数是否生效:
# 使用 mysql 命令行测试带时区的连接 mysql --default-auth=mysql_native_password -u movie_app -p'app_pass_2024' \ --host=127.0.0.1 --port=3306 \ --connect-timeout=10 \ -D movie_ticket_system \ -e "SELECT NOW(), @@global.time_zone, @@session.time_zone;" # 正确输出应类似: # NOW() @@global.time_zone @@session.time_zone # 2024-06-15 14:22:33 SYSTEM SYSTEM # 若显示 SYSTEM,则说明 MySQL 服务时区已设为系统时区(即东八区),后续 application.properties 中可写 serverTimezone=Asia/Shanghai3. 项目导入与依赖配置:Maven 仓库镜像+Spring Boot 版本锁定,避免自动升级翻车
3.1 IntelliJ IDEA 2023.3.4 配置 Maven 全局镜像
IntelliJ 默认用中央仓库,下载spring-boot-starter-web等依赖常超时。必须配置阿里云镜像(比清华镜像更稳定):
- 打开 IDEA →File → Settings → Build, Execution, Deployment → Build Tools → Maven
- Maven home path: 选
/opt/maven/apache-maven-3.8.8(若未安装,见下文) - User settings file: 点击右侧
...,选/opt/maven/apache-maven-3.8.8/conf/settings.xml - 编辑该
settings.xml,在<mirrors>标签下插入:
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>Aliyun Maven</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>- Local repository: 设为
/opt/maven/repo(避免和系统用户目录混用)
提示:Maven 3.8.8 是 Spring Boot 2.7.x 的黄金搭档。3.9.x 开始强制启用
--no-transfer-progress,某些老插件(如maven-compiler-plugin3.8.1)会报Unknown lifecycle phase "compile"。别贪新。
3.2 下载并解压 Maven 3.8.8
wget https://archive.apache.org/dist/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz sudo tar -xzf apache-maven-3.8.8-bin.tar.gz -C /opt/maven/ sudo ln -sf /opt/maven/apache-maven-3.8.8 /opt/maven/latest echo 'export MAVEN_HOME=/opt/maven/latest' | sudo tee -a /etc/profile.d/maven.sh echo 'export PATH=$MAVEN_HOME/bin:$PATH' | sudo tee -a /etc/profile.d/maven.sh source /etc/profile.d/maven.sh mvn -v # 验证输出 Apache Maven 3.8.83.3 克隆项目并检查 pom.xml 的关键依赖版本
项目 GitHub 仓库(假设为https://github.com/example/movie-ticket-springboot.git)必须使用git clone --depth=1避免拉取全部历史:
mkdir -p ~/projects && cd ~/projects git clone --depth=1 https://github.com/example/movie-ticket-springboot.git cd movie-ticket-springboot打开pom.xml,重点核对以下三处(其他依赖由spring-boot-starter-parent2.7.18 统一管理):
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.18</version> <!-- 必须是 2.7.18,不是 2.7.x --> <relativePath/> </parent> <properties> <java.version>17</java.version> <!-- 必须与 JDK 实际版本一致 --> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <!-- MySQL 驱动必须显式声明 8.0.33 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <!-- 不要省略,避免被 parent 的旧版覆盖 --> </dependency> <!-- Thymeleaf 模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- JPA 数据访问 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies>注意:
spring-boot-starter-parent2.7.18 的 BOM(Bill of Materials)已锁定mysql-connector-j为 8.0.33,但显式声明可防止子模块覆盖。曾有项目因pom.xml中某处写了<version>5.1.49</version>,导致启动时ClassNotFoundException: com.mysql.cj.jdbc.Driver。
3.4 在 IDEA 中正确导入 Maven 项目
- IDEA →File → Open → 选中 movie-ticket-springboot 目录
- 弹窗中勾选"Import project from external model" → Maven
- Project SDK: 选
/opt/java/jdk17(不是/usr/lib/jvm/...) - Maven home path: 选
/opt/maven/latest - User settings file: 选
/opt/maven/latest/conf/settings.xml - 点击 OK,等待 IDEA 自动下载依赖(约 3~5 分钟)
提示:若右下角出现 "Maven projects need to be imported" 黄条,不要点 "Enable Auto-Import"!它会在你改代码时自动 reload,极易触发
java.lang.OutOfMemoryError: Metaspace。手动点击右上角Maven 工具窗口 → Reload project即可。
4. 数据库与应用配置:application.properties 七处必改参数,漏一处就启动失败
4.1 application.properties 核心配置详解
项目src/main/resources/application.properties是整个系统的命脉。以下是必须修改的 7 项(其他如日志、缓存等可保持默认):
# 1. 服务器端口(避免与 Tomcat 默认 8080 冲突) server.port=8081 # 2. MySQL 连接(注意:url 中 ? 后必须带 serverTimezone,且 driver-class-name 必须写全) spring.datasource.url=jdbc:mysql://127.0.0.1:3306/movie_ticket_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true spring.datasource.username=movie_app spring.datasource.password=app_pass_2024 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # 3. JPA 配置(关键!必须设为 update,否则首次启动不建表) spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true # 4. Thymeleaf 配置(关闭缓存,开发时改 HTML 立即生效) spring.thymeleaf.cache=false spring.thymeleaf.enabled=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html # 5. 日志级别(方便定位问题) logging.level.org.springframework=INFO logging.level.com.example.movie=DEBUG # 6. 静态资源(CSS/JS 图片存放位置) spring.web.resources.static-locations=classpath:/static/ # 7. 上传文件大小限制(论坛发帖需传图片) spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB关键参数说明:
serverTimezone=Asia/Shanghai:必须与 MySQL 服务时区一致,否则@CreatedDate注解存的时间错 8 小时;allowPublicKeyRetrieval=true:MySQL 8.0.23+ 默认禁用公钥检索,不加此参数会报Public Key Retrieval is not allowed;ddl-auto=update:首次启动自动建表(create-drop会每次清空,validate不建表),生产环境必须改为validate并手工执行 SQL;thymeleaf.cache=false:开发阶段必需,否则改了index.html刷新页面还是旧内容。
4.2 验证数据库表是否成功生成
启动应用前,先手动验证 JPA 是否能连上数据库并建表:
# 在项目根目录执行(确保已配置好 JAVA_HOME 和 MAVEN_HOME) mvn compile # 运行 Hibernate Schema Validator(不启动 Web 服务) mvn exec:java -Dexec.mainClass="org.hibernate.tool.hbm2ddl.SchemaValidator" \ -Dexec.args="--properties=src/main/resources/application.properties"若输出Schema validation successful,说明连接和 DDL 配置正确。若报错Access denied for user 'movie_app'@'localhost',检查密码是否输错;若报Unknown database 'movie_ticket_system',确认数据库已创建。
4.3 启动应用并观察控制台日志关键信号
在 IDEA 中右键MovieTicketSystemApplication.java→Run 'MovieTicketSystemApplication',或终端执行:
mvn spring-boot:run启动成功的关键日志信号(必须逐行核对):
[main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '' [main] c.e.m.MovieTicketSystemApplication : Started MovieTicketSystemApplication in 8.234 seconds (JVM running for 9.112) [main] o.h.t.schema.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@...' [main] o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "/api/user/register" onto public org.springframework.http.ResponseEntity<java.lang.String> com.example.movie.controller.UserController.register(com.example.movie.entity.User) [main] o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "/api/movies/{id}" onto public org.springframework.http.ResponseEntity<com.example.movie.entity.Movie> com.example.movie.controller.MovieController.getMovieById(long)注意:
Started ... in X.XXX seconds是最终成功标志;Mapped行证明 Controller 路由已注册;若卡在Connecting to DataSource超过 30 秒,立即 Ctrl+C,检查 MySQL 是否运行、防火墙是否放行 3306 端口(sudo ufw status)。
5. 常见问题排查:五类高频翻车现场,从现象到根因再到后悔药
5.1 现象:启动时抛java.lang.ClassNotFoundException: javax.xml.bind.JAXBContext
原因:JDK 17 移除了 Java EE 模块(包括 JAXB),但 Spring Boot 2.7.x 的spring-boot-configuration-processor仍依赖它。
解决:在pom.xml的<dependencies>中添加 JAXB API 依赖:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.1</version> </dependency>血泪经验:这个错不会在
mvn compile报,只在mvn spring-boot:run启动时爆发。很多开发者以为是 JDK 问题,反复重装 JDK,其实加两行依赖就能救。
5.2 现象:访问 http://localhost:8081 显示 Whitelabel Error Page,控制台无Mapped日志
原因:Thymeleaf 模板路径错误或@Controller类未被 Spring 扫描到。
解决:
- 检查
src/main/resources/application.properties中spring.thymeleaf.prefix=classpath:/templates/是否拼错; - 确认
src/main/resources/templates/index.html文件存在(不是.htm或大写.HTML); - 检查
MovieTicketSystemApplication.java是否在com.example.movie包下,且@SpringBootApplication注解类所在包名必须是所有@Controller的父包(如UserController在com.example.movie.controller,则启动类必须在com.example.movie或更高层)。
5.3 现象:登录接口返回 404,但curl -X POST http://localhost:8081/api/user/login显示{"timestamp":"...","status":404,"error":"Not Found"}
原因:@RestController类上的@RequestMapping("/api/user")与方法上的@PostMapping("/login")拼接后应为/api/user/login,但若application.properties中server.servlet.context-path被设为/movie,则实际路径变为/movie/api/user/login。
解决:
- 查
application.properties,注释掉或删除server.servlet.context-path行; - 或在 curl 中补全:
curl -X POST http://localhost:8081/movie/api/user/login; - 更推荐方案:统一用
server.servlet.context-path=/(默认值),避免路径嵌套混乱。
5.4 现象:MySQL 连接成功,但User表无数据,注册用户后登录报Invalid credentials
原因:密码未加密存储。User实体类中password字段是明文,但UserService.login()方法里用了 BCrypt 加密比对,而注册时没调用BCryptPasswordEncoder.encode()。
解决:
- 在
UserService.register()方法中注入BCryptPasswordEncoder:
@Service public class UserService { @Autowired private UserRepository userRepository; @Autowired private BCryptPasswordEncoder passwordEncoder; // 新增注入 public void register(User user) { user.setPassword(passwordEncoder.encode(user.getPassword())); // 注册时加密 userRepository.save(user); } }- 在
application.properties中添加:
# 启用密码编码器 spring.security.user.password= # 此处留空,由代码控制注意:
BCryptPasswordEncoder是 Spring Security 提供的,需引入spring-boot-starter-security依赖(项目已有,无需额外加)。
5.5 现象:论坛发帖上传图片失败,控制台报org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request
原因:spring.servlet.multipart配置未生效,或前端 HTML 表单未设enctype="multipart/form-data"。
解决:
- 确认
application.properties中spring.servlet.multipart.max-file-size=10MB等配置在src/main/resources/下,而非src/test/resources/; - 检查
src/main/resources/templates/forum/create.html中<form>标签是否有:
<form th:action="@{/forum/post}" method="post" enctype="multipart/form-data"> <input type="file" name="image" /> </form>- 若用 Postman 测试,选择
Body → form-data,Key 填image,Value 选文件。
6. 启动后验证全流程:从首页浏览到下单支付,六步闭环测试法
6.1 第一步:验证静态资源与首页渲染(GET /)
打开浏览器访问http://localhost:8081,应看到系统首页(含轮播图、最新电影列表、公告栏)。
验证点:
- 检查浏览器开发者工具(F12)→ Network 标签页,所有
.css、.js、.png请求状态码为200; - 查看
Elements标签页,<title>应为电影在线订票系统; - 若 CSS 未加载,检查
application.properties中spring.web.resources.static-locations=classpath:/static/是否指向src/main/resources/static/(不是src/main/webapp)。
6.2 第二步:验证用户注册与登录(POST /api/user/register & /api/user/login)
用 Postman 或 curl 测试:
# 注册新用户 curl -X POST http://localhost:8081/api/user/register \ -H "Content-Type: application/json" \ -d '{"username":"testuser","password":"123456","email":"test@example.com"}' # 登录获取 token(项目若集成 Spring Security,会返回 cookie;否则返回 JSON) curl -X POST http://localhost:8081/api/user/login \ -H "Content-Type: application/json" \ -d '{"username":"testuser","password":"123456"}'验证点:
- 注册返回
{"message":"注册成功"}; - 登录返回
{"message":"登录成功"}且 HTTP 状态码为200; - 查 MySQL:
SELECT * FROM user WHERE username='testuser';应看到一条记录,password字段为 BCrypt 加密字符串(以$2a$开头)。
6.3 第三步:验证电影信息查询(GET /api/movies)
# 获取所有电影 curl http://localhost:8081/api/movies # 获取单部电影(ID=1) curl http://localhost:8081/api/movies/1验证点:
- 返回 JSON 数组,每项含
id,title,description,releaseDate; releaseDate格式应为yyyy-MM-dd(如"2024-06-15"),非时间戳;- 若返回空数组,检查
src/main/resources/data.sql是否存在并被spring.jpa.hibernate.ddl-auto=update执行(Spring Boot 2.7.x 默认不加载data.sql,需手动执行或改用import.sql)。
6.4 第四步:验证订单创建(POST /api/orders)
# 创建订单(需登录后携带 session cookie,此处简化用 curl -b 传 cookie) # 先登录拿到 JSESSIONID,再用它发订单请求 curl -X POST http://localhost:8081/api/orders \ -H "Content-Type: application/json" \ -b "JSESSIONID=xxx" \ -d '{"movieId":1,"seatNumber":"A1","userId":1}'验证点:
- 返回
{"orderId":123,"status":"PENDING"}; - 查数据库
order表,status字段应为PENDING(非null); - 若报
403 Forbidden,检查SecurityConfig.java是否放行/api/orders/**(项目若含 Spring Security,需配置http.authorizeHttpRequests().requestMatchers("/api/orders/**").authenticated())。
6.5 第五步:验证管理员后台(GET /admin/dashboard)
访问http://localhost:8081/admin/dashboard,输入管理员账号(默认admin/admin123,见src/main/resources/data.sql)。
验证点:
- 页面显示「系统统计」图表(用户数、订单数、电影数);
- 点击「用户管理」→「禁用用户」,选中 testuser,提交后刷新页面,该用户状态变为
DISABLED; - 查数据库
user表,testuser的enabled字段应为0。
6.6 第六步:验证论坛发帖与评论(POST /api/forum/posts & /api/forum/comments)
# 发帖 curl -X POST http://localhost:8081/api/forum/posts \ -H "Content-Type: application/json" \ -b "JSESSIONID=xxx" \ -d '{"title":"首映观感","content":"太震撼了!","userId":1}' # 评论 curl -X POST http://localhost:8081/api/forum/comments \ -H "Content-Type: application/json" \ -b "JSESSIONID=xxx" \ -d '{"postId":1,"content":"同感!","userId":1}'验证点:
- 发帖返回
{"postId":1,"title":"首映观感"}; - 访问
http://localhost:8081/forum/1(帖子详情页),应看到标题、内容及下方评论列表; - 若评论不显示,检查
ForumPost实体类中@OneToMany(mappedBy = "post")的mappedBy值是否与Comment类中@ManyToOne的字段名一致(如post)。
从那以后我每次部署 Spring Boot 项目,都强制走一遍这六步闭环测试:首页 → 注册 → 登录 → 查电影 → 下单 → 进后台。哪怕只是改了一行 CSS,也要确保核心链路不断。因为订票系统不是单页应用,它的价值在于「用户能完成一次完整购票」,而不是「某个接口返回 200」。希望帮到你。
本文还有配套的精品资源,点击获取