资讯动态

Spring Boot + Vue 3 酒店管理系统全栈开发实战:从环境搭建到生产部署

发布时间:2026/9/2 17:09:36 来源:尧图企业网站定制
在实际 Java Web 项目开发中一个完整的、前后端分离的管理系统是检验技术综合运用能力的绝佳场景。酒店客房管理系统正是这样一个典型项目它涵盖了用户管理、客房信息维护、订单处理、数据统计等核心业务模块非常适合用于学习 Spring Boot 后端开发与 Vue 3 前端框架的集成。很多开发者拿到源码后往往卡在环境配置、依赖版本、前后端联调等环节导致项目无法成功运行。本文将围绕一个基于 Spring Boot 和 Vue 3 的酒店客房管理系统从零开始详细拆解其搭建过程、核心代码逻辑、常见问题排查以及生产环境部署的注意事项目标是让你不仅能成功运行项目更能理解其背后的设计思路和工程实践。1. 理解项目架构与技术选型在动手搭建之前必须先理清整个项目的技术栈和架构设计。这决定了后续环境准备、代码编写和问题排查的方向。1.1 为什么选择 Spring Boot Vue 3Spring Boot 以其“约定大于配置”的理念极大地简化了传统 Spring 应用的初始搭建和开发过程。它内嵌了 Tomcat 等 Web 服务器无需部署 WAR 包通过一个main方法就能启动一个独立的、生产级别的应用。对于酒店客房管理系统这类需要快速迭代、包含复杂业务逻辑的后台服务Spring Boot 提供了完善的 Web、数据访问、安全、缓存等模块支持。Vue 3 作为现代前端框架其组合式 API 提供了更好的逻辑复用和类型推断能力配合 TypeScript 使用能构建出更健壮、可维护性更高的前端应用。前后端分离的架构使得后端可以专注于提供 RESTful API前端则独立开发、部署两者通过 HTTP 协议进行数据交互职责清晰便于团队协作。1.2 项目核心模块划分一个典型的酒店客房管理系统通常包含以下模块后端 (Spring Boot)实体层 (Entity/Model)对应数据库表如User、Room、Order。数据访问层 (Repository/DAO)使用 Spring Data JPA 或 MyBatis-Plus 进行数据库操作。业务逻辑层 (Service)封装核心业务规则如客房预订逻辑、价格计算。控制层 (Controller)接收前端 HTTP 请求调用 Service返回 JSON 数据。配置与工具类数据库连接、跨域配置、权限拦截、工具函数等。前端 (Vue 3)视图组件 (Components)如登录页、客房列表页、订单表单页。状态管理 (Pinia)集中管理用户登录状态、客房数据等应用级状态。路由管理 (Vue Router)定义页面路径与组件的映射关系。HTTP 客户端 (Axios)封装与后端 API 的通信。UI 组件库如 Element Plus用于快速构建界面。1.3 开发环境与工具准备在开始编码前请确保你的本地开发环境已就绪。以下是推荐的环境清单工具/环境推荐版本说明JDK11 或 17Spring Boot 3.x 需要 JDK 17Spring Boot 2.x 兼容 JDK 8/11。建议使用 JDK 17 以获得长期支持。Maven3.6用于管理 Java 项目依赖、构建和打包。Node.js18Vue 3 的运行和构建环境。同时会安装 npm 包管理器。IDEIntelliJ IDEA / VS CodeIDEA 用于后端 Java 开发VS Code 用于前端 Vue 开发。数据库MySQL 5.7 / 8.0项目的主要数据存储。也可根据项目源码适配 PostgreSQL。Git最新版用于版本控制和获取项目源码。注意版本兼容性是项目能否成功启动的关键。如果项目源码未明确说明建议优先使用上述推荐版本避免因版本过高或过低导致依赖冲突。2. 后端 Spring Boot 项目搭建与配置我们将从创建一个标准的 Spring Boot 项目开始逐步集成必要的依赖和配置。2.1 使用 Spring Initializr 初始化项目最便捷的方式是使用 start.spring.io 或 IDE 内置的 Spring Initializr 创建项目。选择参数Project: Maven ProjectLanguage: JavaSpring Boot: 选择稳定版本如 3.1.x 或 2.7.x需与源码匹配Project Metadata:Group:com.example(可改为你的组织名如com.hotel)Artifact:hotel-managementName:hotel-managementPackage name:com.example.hotelmanagementPackaging: JarJava: 17添加依赖根据酒店管理系统的需求通常需要添加以下依赖Spring Web: 构建 RESTful API。Spring Data JPA: 简化数据库操作。MySQL Driver: 连接 MySQL 数据库。Lombok: 通过注解减少 getter/setter 等样板代码。Spring Boot DevTools: 开发时热加载。Validation: 参数校验。生成项目后使用 IDE 导入 Maven 项目。2.2 核心配置文件详解项目根目录下的application.properties或application.yml是 Spring Boot 的核心配置文件。对于酒店管理系统典型配置如下# application.yml server: port: 8080 # 后端服务端口 spring: application: name: hotel-management datasource: url: jdbc:mysql://localhost:3306/hotel_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # 开发环境可用 update生产环境务必改为 validate 或 none show-sql: true # 开发时显示 SQL 语句 properties: hibernate: format_sql: true # 格式化输出的 SQL jackson: time-zone: GMT8 # 处理 JSON 时间序列化时的时区问题 date-format: yyyy-MM-dd HH:mm:ss # 自定义配置如 JWT 密钥生产环境应从环境变量或配置中心读取 jwt: secret: your-jwt-secret-key-here-must-be-very-long-and-secure expiration: 86400000 # token 过期时间毫秒例如 24 小时关键配置解释spring.datasource.url: 指定数据库连接地址和参数。serverTimezoneAsia/Shanghai是解决中文时区问题的关键。spring.jpa.hibernate.ddl-auto:update模式会在应用启动时根据实体类自动更新表结构适合开发。生产环境必须禁用此功能应使用validate仅校验或通过 Flyway/Liquibase 管理数据库变更。spring.jpa.show-sql: 开发时开启便于调试 SQL。jwt.secret: 用于生成和验证 JWT Token 的密钥必须足够复杂且保密。2.3 数据库设计与实体类映射假设系统需要用户表、客房表、订单表。以下以Room客房实体为例// src/main/java/com/example/hotelmanagement/entity/Room.java package com.example.hotelmanagement.entity; import lombok.Data; import javax.persistence.*; import java.math.BigDecimal; Entity Table(name room) Data // Lombok 注解自动生成 getter, setter, toString, equals, hashCode public class Room { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(nullable false, unique true) private String roomNumber; // 房号如 101 Column(nullable false) private String type; // 房型如 “标准间”、“豪华套房” Column(nullable false) private BigDecimal price; // 价格使用 BigDecimal 避免精度丢失 Column(nullable false) private String status; // 状态如 “空闲”、“已预订”、“入住中”、“维修中” private String description; // 客房描述 private String imageUrl; // 客房图片链接 // 省略构造方法Lombok Data 会生成 }关键点Entity和Table将类映射到数据库表。Id和GeneratedValue定义主键及其生成策略。Column定义字段属性如是否可为空、是否唯一。金额字段使用BigDecimal这是金融计算的最佳实践避免使用float或double导致的精度问题。使用Lombok的Data注解可以极大减少样板代码。2.4 实现数据访问层与业务逻辑层1. 仓库接口 (Repository): Spring Data JPA 只需定义接口无需实现。// src/main/java/com/example/hotelmanagement/repository/RoomRepository.java package com.example.hotelmanagement.repository; import com.example.hotelmanagement.entity.Room; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; Repository public interface RoomRepository extends JpaRepositoryRoom, Long { // 根据房号查询 Room findByRoomNumber(String roomNumber); // 根据状态查询客房列表 ListRoom findByStatus(String status); // 根据房型和状态查询 ListRoom findByTypeAndStatus(String type, String status); }2. 服务层 (Service): 服务层封装业务逻辑是系统的核心。// src/main/java/com/example/hotelmanagement/service/RoomService.java package com.example.hotelmanagement.service; import com.example.hotelmanagement.entity.Room; import com.example.hotelmanagement.repository.RoomRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; Service public class RoomService { Autowired private RoomRepository roomRepository; public ListRoom findAll() { return roomRepository.findAll(); } public OptionalRoom findById(Long id) { return roomRepository.findById(id); } Transactional // 确保保存操作在事务中执行 public Room saveOrUpdate(Room room) { // 这里可以加入业务校验例如房号是否已存在 if (room.getId() null) { Room existing roomRepository.findByRoomNumber(room.getRoomNumber()); if (existing ! null) { throw new RuntimeException(房号 room.getRoomNumber() 已存在); } } return roomRepository.save(room); } Transactional public void deleteById(Long id) { // 删除前可检查是否有关联订单等业务规则 roomRepository.deleteById(id); } public ListRoom findAvailableRooms() { return roomRepository.findByStatus(空闲); } }3. 控制层 (Controller): 控制层负责接收 HTTP 请求调用服务并返回 JSON 响应。// src/main/java/com/example/hotelmanagement/controller/RoomController.java package com.example.hotelmanagement.controller; import com.example.hotelmanagement.entity.Room; import com.example.hotelmanagement.service.RoomService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; RestController RequestMapping(/api/rooms) // API 路径前缀 public class RoomController { Autowired private RoomService roomService; GetMapping public ResponseEntityListRoom getAllRooms() { return ResponseEntity.ok(roomService.findAll()); } GetMapping(/{id}) public ResponseEntityRoom getRoomById(PathVariable Long id) { return roomService.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } PostMapping public ResponseEntityRoom createRoom(Valid RequestBody Room room) { // Valid 会触发实体类上的校验注解如NotBlank Room savedRoom roomService.saveOrUpdate(room); return ResponseEntity.ok(savedRoom); } PutMapping(/{id}) public ResponseEntityRoom updateRoom(PathVariable Long id, Valid RequestBody Room room) { if (!roomService.findById(id).isPresent()) { return ResponseEntity.notFound().build(); } room.setId(id); // 确保更新的是指定ID的对象 Room updatedRoom roomService.saveOrUpdate(room); return ResponseEntity.ok(updatedRoom); } DeleteMapping(/{id}) public ResponseEntityVoid deleteRoom(PathVariable Long id) { if (!roomService.findById(id).isPresent()) { return ResponseEntity.notFound().build(); } roomService.deleteById(id); return ResponseEntity.noContent().build(); } GetMapping(/available) public ResponseEntityListRoom getAvailableRooms() { return ResponseEntity.ok(roomService.findAvailableRooms()); } }至此一个具备 CRUD 功能的客房管理后端 API 就完成了。你可以通过http://localhost:8080/api/rooms来测试接口。3. 前端 Vue 3 项目搭建与页面开发后端 API 就绪后我们开始构建前端用户界面。3.1 使用 Vite 创建 Vue 3 项目Vite 是现在 Vue 项目推荐的构建工具速度远快于传统的 Webpack。# 在合适目录下执行 npm create vuelatest hotel-management-frontend按照提示选择项目特性推荐添加TypeScript、Vue Router、Pinia、ESLint。 创建完成后进入项目并安装依赖cd hotel-management-frontend npm install # 安装 UI 库和 HTTP 客户端 npm install element-plus axios npm install --save-dev types/node # 解决 TypeScript 路径别名问题3.2 配置 Axios 与 API 封装为了统一管理 API 请求我们创建一个axios实例并封装请求拦截器用于添加 Token和响应拦截器用于统一处理错误。// src/utils/request.ts import axios from axios; import { ElMessage } from element-plus; import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from axios; import { useUserStore } from /stores/user; // 假设使用 Pinia 管理用户状态 const service: AxiosInstance axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || http://localhost:8080/api, // 从环境变量读取 timeout: 10000, // 请求超时时间 }); // 请求拦截器 service.interceptors.request.use( (config: AxiosRequestConfig) { const userStore useUserStore(); if (userStore.token) { // 如果存在 token则在请求头中携带 config.headers config.headers || {}; config.headers[Authorization] Bearer ${userStore.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 res.code ! 200) { ElMessage.error(res.message || Error); return Promise.reject(new Error(res.message || Error)); } return res; // 直接返回 data 部分 }, (error) { console.error(Response Error:, error); if (error.response) { // 有响应但状态码不在 2xx 范围 switch (error.response.status) { case 401: ElMessage.error(未授权请重新登录); // 清除 token 并跳转到登录页 const userStore useUserStore(); userStore.logout(); window.location.href /login; break; case 403: ElMessage.error(拒绝访问); break; case 404: ElMessage.error(请求的资源不存在); break; case 500: ElMessage.error(服务器内部错误); break; default: ElMessage.error(error.response.data?.message || 请求失败: ${error.response.status}); } } else if (error.request) { // 请求已发出但没有收到响应 ElMessage.error(网络错误请检查网络连接); } else { // 请求配置出错 ElMessage.error(请求配置错误); } return Promise.reject(error); } ); export default service;然后在.env.development和.env.production中配置后端 API 地址# .env.development VITE_API_BASE_URLhttp://localhost:8080/api3.3 实现客房列表页面使用 Element Plus 的表格组件来展示客房列表。!-- src/views/RoomListView.vue -- template div classroom-list div classheader h2客房管理/h2 el-button typeprimary clickhandleCreate新增客房/el-button /div el-table :dataroomList border stylewidth: 100% el-table-column proproomNumber label房号 width120 / el-table-column proptype label房型 width150 / el-table-column propprice label价格(元) width120 template #defaultscope {{ scope.row.price.toFixed(2) }} /template /el-table-column el-table-column propstatus label状态 width100 template #defaultscope el-tag :typegetStatusTagType(scope.row.status) {{ scope.row.status }} /el-tag /template /el-table-column el-table-column propdescription label描述 / el-table-column label操作 width200 fixedright template #defaultscope el-button sizesmall clickhandleEdit(scope.row)编辑/el-button el-button sizesmall typedanger clickhandleDelete(scope.row.id)删除/el-button /template /el-table-column /el-table !-- 新增/编辑对话框 -- el-dialog v-modeldialogVisible :titledialogTitle width500px el-form :modelform :rulesrules refformRef label-width80px el-form-item label房号 proproomNumber el-input v-modelform.roomNumber placeholder请输入房号 / /el-form-item el-form-item label房型 proptype el-select v-modelform.type placeholder请选择房型 el-option label标准间 value标准间 / el-option label大床房 value大床房 / el-option label豪华套房 value豪华套房 / /el-select /el-form-item el-form-item label价格 propprice el-input-number v-modelform.price :min0 :precision2 :step10 / /el-form-item el-form-item label状态 propstatus el-select v-modelform.status placeholder请选择状态 el-option label空闲 value空闲 / el-option label已预订 value已预订 / el-option label入住中 value入住中 / el-option label维修中 value维修中 / /el-select /el-form-item el-form-item label描述 propdescription el-input v-modelform.description typetextarea :rows3 / /el-form-item /el-form template #footer span classdialog-footer el-button clickdialogVisible false取消/el-button el-button typeprimary clicksubmitForm确认/el-button /span /template /el-dialog /div /template script setup langts import { ref, reactive, onMounted } from vue; import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from element-plus; import request from /utils/request; import type { Room } from /types/room; // 定义好的 TypeScript 类型 const roomList refRoom[]([]); const dialogVisible ref(false); const dialogTitle ref(); const formRef refFormInstance(); const form reactivePartialRoom({ roomNumber: , type: , price: 0, status: 空闲, description: , }); const rules: FormRules { roomNumber: [{ required: true, message: 请输入房号, trigger: blur }], type: [{ required: true, message: 请选择房型, trigger: change }], price: [{ required: true, message: 请输入价格, trigger: blur }], status: [{ required: true, message: 请选择状态, trigger: change }], }; // 获取客房列表 const fetchRooms async () { try { const response await request.get(/rooms); roomList.value response.data || response; // 根据后端返回格式调整 } catch (error) { console.error(获取客房列表失败:, error); } }; // 状态标签样式 const getStatusTagType (status: string) { const map: Recordstring, success | info | warning | danger { 空闲: success, 已预订: warning, 入住中: info, 维修中: danger, }; return map[status] || info; }; // 打开新增对话框 const handleCreate () { dialogTitle.value 新增客房; Object.keys(form).forEach(key { (form as any)[key] ; }); form.status 空闲; form.price 0; dialogVisible.value true; }; // 打开编辑对话框 const handleEdit (row: Room) { dialogTitle.value 编辑客房; Object.assign(form, row); dialogVisible.value true; }; // 提交表单新增/编辑 const submitForm async () { if (!formRef.value) return; await formRef.value.validate(async (valid) { if (valid) { try { const url form.id ? /rooms/${form.id} : /rooms; const method form.id ? put : post; await request({ url, method, data: form }); ElMessage.success(form.id ? 更新成功 : 创建成功); dialogVisible.value false; fetchRooms(); // 刷新列表 } catch (error) { console.error(操作失败:, error); } } }); }; // 删除客房 const handleDelete (id: number) { ElMessageBox.confirm(确定要删除这条客房信息吗, 提示, { confirmButtonText: 确定, cancelButtonText: 取消, type: warning, }).then(async () { try { await request.delete(/rooms/${id}); ElMessage.success(删除成功); fetchRooms(); } catch (error) { console.error(删除失败:, error); } }).catch(() {}); }; onMounted(() { fetchRooms(); }); /script style scoped .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } /style这个页面实现了客房的增删改查功能并与后端 API 进行了对接。通过类似的模式可以继续开发用户管理、订单管理等其他页面。4. 前后端联调与项目运行代码编写完成后最关键的一步是让前后端协同工作。4.1 启动后端服务确保 MySQL 服务已启动并创建了配置文件中的数据库如hotel_db。在 IDE 中找到HotelManagementApplication主类直接运行main方法。观察控制台日志确认没有错误并看到类似Tomcat started on port(s): 8080的日志。打开浏览器访问http://localhost:8080/api/rooms如果返回空数组[]或提示Whitelabel Error Page因为没数据说明后端 API 服务已正常启动。可以通过 Postman 等工具测试 POST、PUT 等接口。4.2 启动前端开发服务器在终端中进入前端项目根目录 (hotel-management-frontend)。运行npm run dev。控制台会输出本地开发服务器地址通常是http://localhost:5173。打开该地址应该能看到 Vue 应用的默认页面。4.3 解决跨域问题在开发阶段前端运行在localhost:5173后端运行在localhost:8080端口不同浏览器会因同源策略而阻止请求。有两种主流解决方案方案一后端配置 CORS推荐在 Spring Boot 后端添加一个全局 CORS 配置类。// src/main/java/com/example/hotelmanagement/config/WebConfig.java package com.example.hotelmanagement.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 WebConfig { Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) // 允许跨域的路径 .allowedOrigins(http://localhost:5173) // 允许的前端地址 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) // 允许的请求方法 .allowedHeaders(*) // 允许的请求头 .allowCredentials(true); // 允许携带凭证如 Cookie } }; } }方案二前端代理Vite 配置在前端项目的vite.config.ts中配置代理将 API 请求转发到后端。// vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { proxy: { /api: { target: http://localhost:8080, // 后端地址 changeOrigin: true, // rewrite: (path) path.replace(/^\/api/, ) // 如果后端路径没有 /api 前缀可以重写 } } } })配置后前端代码中请求/api/rooms会被 Vite 开发服务器代理到http://localhost:8080/api/rooms从而避免跨域。注意方案一更接近生产环境因为生产环境前后端可能部署在同一域名下或由 Nginx 反向代理。方案二仅用于开发环境。4.4 功能验证流程登录/认证如果系统有登录功能先完成登录流程确保 Token 能被正确存储和携带。数据列表访问客房列表页确认能成功从后端获取并展示数据。数据操作尝试新增、编辑、删除一条客房记录观察前端提示和后端数据库变化是否一致。表单验证测试表单的必填项、格式校验如价格不能为负数是否生效。错误处理尝试触发一些错误如删除不存在的记录查看前端拦截器是否能正确捕获并显示错误信息。5. 常见问题排查与解决方案在搭建和运行过程中你可能会遇到以下典型问题。5.1 后端启动失败问题现象可能原因检查与解决APPLICATION FAILED TO START1. 数据库连接失败。2. 端口被占用。3. 依赖冲突或缺失。1. 检查application.yml中的数据库 URL、用户名、密码确认 MySQL 服务已启动。2. 检查 8080 端口是否被其他程序占用可修改server.port。3. 运行mvn clean compile检查依赖或尝试删除本地 Maven 仓库~/.m2/repository重新下载。BeanCreationException1. Bean 注入失败。2. 配置类扫描路径问题。1. 检查Service,Repository,Autowired注解使用是否正确包路径是否在SpringBootApplication主类所在包或其子包下。2. 确认ComponentScan注解如有配置正确。JPA相关错误1. 实体类与数据库表映射错误。2.ddl-auto策略导致。1. 检查实体类字段名、类型与数据库表是否匹配。2. 开发环境可暂时设为create-drop或update但生产环境必须改为validate或none并通过 SQL 脚本管理表结构。5.2 前端编译或运行错误问题现象可能原因检查与解决npm install失败1. 网络问题。2. Node.js 版本不兼容。3.package-lock.json冲突。1. 切换 npm 镜像源npm config set registry https://registry.npmmirror.com。2. 使用nvm管理 Node.js 版本确保版本符合要求。3. 删除node_modules和package-lock.json重新执行npm install。Vue组件无法导入1. 路径别名未配置。2. TypeScript 类型声明缺失。1. 检查vite.config.ts和tsconfig.json中的paths配置。2. 为第三方库安装类型声明包如types/node。页面空白或控制台报4041. 路由配置错误。2. 静态资源路径错误。3. 代理配置未生效。1. 检查router/index.ts中的路由定义和组件导入。2. 使用import.meta.env.BASE_URL处理基础路径。3. 确认vite.config.ts中的代理配置正确并重启开发服务器。5.3 前后端联调问题问题现象可能原因检查与解决前端请求后端返回4041. 后端 API 路径错误。2. 后端 Controller 未正确映射。3. 跨域请求被浏览器拦截。1. 核对前端请求的 URL 和后端RequestMapping定义的路径是否完全一致包括大小写。2. 在后端控制台查看映射日志或访问/actuator/mappings需引入 actuator 依赖查看所有端点。3. 按4.3节配置 CORS 或代理。前端请求返回401/4031. 未登录或 Token 过期。2. Token 未正确携带或格式错误。3. 后端权限拦截器配置问题。1. 检查登录流程确保成功获取 Token 并存储如 localStorage 或 Pinia。2. 检查 Axios 请求拦截器是否正确在请求头中添加了Authorization: Bearer token。3. 检查后端 Security 或自定义拦截器的配置确保对应接口路径未被错误拦截。请求成功但数据不显示1. 前端组件数据绑定错误。2. 后端返回的数据结构与前端期望不符。3. 控制台有 JavaScript 错误。1. 使用 Vue Devtools 检查组件的数据和状态。2. 在浏览器开发者工具的 Network 面板查看 API 返回的实际 JSON 结构并与前端代码中定义的 TypeScript 接口或变量进行比对。3. 解决控制台报错可能是未定义的变量或方法。6. 项目打包与生产环境部署建议本地开发完成后需要将项目部署到服务器。6.1 后端打包与运行打包在项目根目录执行mvn clean package -DskipTests。成功后会在target目录生成hotel-management-0.0.1-SNAPSHOT.jar。运行将 JAR 包上传至服务器使用命令运行# 最简单方式前台运行关闭终端即停止 java -jar hotel-management-0.0.1-SNAPSHOT.jar # 后台运行并将日志输出到文件 nohup java -jar hotel-management-0.0.1-SNAPSHOT.jar app.log 21 # 指定配置文件生产环境推荐 java -jar hotel-management-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod需要提前在服务器安装好对应版本的 JDK。6.2 前端打包与部署打包在前端项目根目录执行npm run build。产物会生成在dist目录。部署将dist目录下的所有文件放到任何静态文件服务器如 Nginx、Apache或对象存储如 OSS上。Nginx 配置示例同时代理前端静态文件和后端 APIserver { listen 80; server_name your-domain.com; # 你的域名 # 前端静态文件 location / { root /path/to/your/dist; index index.html; try_files $uri $uri/ /index.html; # 支持 Vue Router 的 history 模式 } # 反向代理后端 API location /api/ { proxy_pass http://localhost:8080; # 后端服务地址 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }6.3 生产环境关键检查清单将项目部署到生产环境前务必完成以下检查数据库[ ] 使用独立的、高权限的生产数据库账号而非root。[ ] 关闭 JPA 的ddl-auto设为validate或none使用 Flyway/Liquibase 管理数据库变更。[ ] 对敏感配置如数据库密码、JWT 密钥进行加密或从环境变量读取。应用配置[ ] 创建application-prod.yml配置生产环境的数据库、日志级别、端口等。[ ] 确保日志已配置并输出到文件便于排查问题。[ ] 关闭开发工具如spring-boot-devtools和调试信息。安全[ ] 实现完整的用户认证与授权如使用 Spring Security JWT。[ ] 对用户输入进行严格的校验和过滤防止 SQL 注入和 XSS 攻击。[ ] API 接口根据需要实施限流和防刷策略。运维[ ] 使用进程管理工具如 systemd, Supervisor来管理 JAR 包进程实现开机自启和自动重启。[ ] 设置监控和告警关注应用 CPU、内存、磁盘和关键接口响应时间。[ ] 制定数据库备份策略。通过以上步骤你不仅能够成功搭建并运行一个 Spring Boot Vue 3 的酒店客房管理系统更能掌握全栈开发的核心流程、联调技巧和部署要点。这个项目可以作为深入学习微服务、分布式缓存、消息队列等更高级技术的基础框架。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价