ARTICLE DETAIL

资讯详情

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

Spring Boot+Vue全栈实战:民宿管理系统设计与实现

Spring Boot+Vue全栈实战:民宿管理系统设计与实现 简介本资源是一套完整的Java毕业设计实战项目面向计算机相关专业本科生及Java初学者解决毕业设计选题难、系统开发流程不清晰、前后端协同实践不足等实际问题。项目采用Spring Boot Vue.js全栈架构涵盖民宿预订核心业务全流程包括用户/管理员双角色登录、民宿信息CRUD、订单全生命周期管理、第三方支付集成、用户评价与搜索过滤等功能模块。压缩包共1284个文件含54个Java后端控制器与实体类、4个Vue前端组件、514个JS交互逻辑文件、166个PNG/GIF图标资源、118个HTML页面及70个CSS样式文件整体大小为40.52MB结构规范、注释完整便于理解MVC分层与前后端分离开发模式。已有910人学习下载配套演示视频直观展示系统运行效果源码可直接导入IDE运行调试是掌握企业级Web应用开发的优质教学案例。1. 项目概述从零到一构建一个现代化的民宿管理系统最近几年身边不少朋友都投身到了民宿行业从城市里的共享公寓到山野间的特色小屋生意做得风生水起。但聊得深了就会发现一个普遍痛点管理太乱了。房态靠手写表格、订单靠微信沟通、财务靠月底对账效率低不说还容易出错。一个朋友甚至因为记错房态导致两拨客人“撞车”赔礼道歉又打折损失不小。这让我意识到一个趁手的数字化管理系统对民宿主来说绝不是锦上添花而是雪中送炭。于是我花了些时间用 Spring Boot 和 Vue 前后端分离的架构完整地实现了一套民宿管理系统。这不仅仅是一个毕业设计级别的项目更是一个可以实际跑起来的、功能完备的管理工具。它涵盖了从房源上架、订单处理、客户沟通到财务统计的全流程。如果你正在寻找一个 Java 全栈的实战项目来练手或者你本身就是一位民宿经营者想了解如何用技术提升管理效率那么这套系统的设计思路和实现细节应该能给你带来不少启发。接下来我就把这个项目的“里里外外”拆解清楚包括为什么选这些技术、具体怎么做的以及开发过程中踩过的那些“坑”。2. 技术选型与整体架构设计做项目尤其是全栈项目技术选型是第一步也是最关键的一步。它决定了项目的开发效率、维护成本以及未来的扩展性。对于这个民宿管理系统我的核心思路是后端稳健高效前端灵活现代前后端通过清晰的接口契约进行通信。2.1 后端技术栈为什么是 Spring Boot后端我毫不犹豫地选择了Spring Boot。这不是盲目跟风而是基于几个非常实际的考量快速启动约定大于配置Spring Boot 的自动配置和起步依赖Starter让我几乎不用在繁琐的 XML 或基础配置上花费时间。比如要集成 MyBatis 操作数据库只需要引入mybatis-spring-boot-starter要开发 Web API引入spring-boot-starter-web即可。这让我能迅速搭建起项目骨架把精力集中在业务逻辑上。生态成熟社区活跃Spring 家族是整个 Java 企业级开发的事实标准生态极其完善。无论是数据库访问MyBatis/JPA、安全框架Spring Security、缓存Redis、消息队列还是任务调度都有成熟、稳定的 Spring Boot Starter 与之集成。这意味着项目中遇到的绝大多数通用问题都能在社区找到经过验证的解决方案。易于部署和监控Spring Boot 应用可以打包成一个可执行的 JAR 文件内嵌了 Tomcat 等 Servlet 容器部署时只需要java -jar命令即可运行非常适合云原生环境。同时配合 Spring Boot Actuator可以轻松暴露应用的健康状态、指标等信息方便后期运维监控。在数据库方面我选择了MySQL。民宿系统的数据关系比较明确用户、房源、订单、评论等且对事务一致性有要求比如下单扣减库存关系型数据库是更稳妥的选择。MySQL 性能不错、成本低、资料多是这类项目的标配。持久层框架我用了MyBatis-Plus。它是 MyBatis 的增强工具在保留 MyBatis 所有特性的基础上提供了强大的 CRUD 通用接口和条件构造器。最让我心动的是它的代码生成器可以一键生成实体类、Mapper 接口、Service 层甚至 Controller 层的模板代码极大地提升了开发效率避免了大量重复的“增删改查”编码工作。2.2 前端技术栈为什么是 Vue.js前端选择了Vue.js主要是看中了它的“渐进式”和“易上手”。渐进式框架灵活性强你可以从一个简单的页面开始只用 Vue 的核心库然后根据需求逐步引入路由Vue Router、状态管理Vuex/Pinia等。这对于一个功能模块可能逐步增加的管理系统来说非常友好。学习曲线平缓开发体验好相比于 React 和 AngularVue 的模板语法更接近原生 HTML对于后端开发人员或者初学者来说更容易理解和上手。其响应式系统和组合式 APIComposition API也让逻辑组织和复用变得非常清晰。丰富的生态系统UI 库方面我选择了Element Plus。它为 Vue 3 设计提供了丰富、美观且实用的组件如表格、表单、对话框、日期选择器等能够快速搭建出专业的管理后台界面。对于图表展示我引入了ECharts它可以轻松绘制出房源预订趋势、收入统计等可视化图表。2.3 前后端分离架构与 API 设计整个系统采用典型的前后端分离架构。后端 Spring Boot 项目专注于提供 RESTful API处理业务逻辑和数据持久化前端 Vue 项目则负责页面渲染和用户交互通过 Axios 库调用后端 API。这种架构的好处显而易见职责清晰前后端开发可以并行进行只需提前定义好 API 接口文档我使用了Swagger/OpenAPI来自动生成和可视化接口文档。技术栈灵活后端可以独立升级或替换技术组件不影响前端前端也可以根据需求选择不同的框架或构建工具。易于扩展未来可以方便地开发移动端 App通过调用同一套 API或者引入微服务架构。在 API 设计上我遵循了 RESTful 风格力求 URL 清晰、HTTP 方法语义明确GET-获取POST-创建PUT-更新DELETE-删除。例如GET /api/rooms获取房源列表GET /api/rooms/{id}获取特定房源详情POST /api/orders创建一个新订单PUT /api/orders/{id}/status更新订单状态注意在实际开发中API 路径的前缀如/api和版本管理如/api/v1/rooms需要在项目初期就规划好这关系到后期接口的维护和兼容性。3. 核心功能模块设计与实现细节民宿管理系统的核心是业务。我将系统划分为几个关键模块每个模块都对应着民宿运营中的一个实际场景。3.1 房源管理模块民宿的“商品”中心这是系统的基石。一个房源Room包含的信息非常多远不止一个名字和一张图片。数据库设计 我设计了一张核心的room表包含基础信息如标题、描述、地址、户型、可住人数、床型、面积等。此外还有几个关键字段price_per_night每晚单价。这里我选择了以“分”为单位存储整数避免浮点数计算带来的精度问题。status房源状态0-待审核1-可预订2-已下架3-维修中。这是一个典型的枚举值在代码中我会用常量类来管理。facility_ids设施ID列表。这里我用了 JSON 格式的字符串来存储如[1,3,5]对应一个独立的facility设施表。这样设计比用多张关联表更灵活查询时可以通过 JSON 函数处理或者在后端反序列化成列表。后端实现 在 Spring Boot 中我创建了Room实体类使用 MyBatis-Plus 的TableName注解映射表名。Service 层提供了复杂的查询方法例如分页查询、按条件过滤城市、价格区间、入住日期、关键词等。这里的一个难点是“按入住日期过滤可订房源”这需要关联查询order表排除那些在目标日期段内已有有效订单的房源。前端实现 前端使用 Element Plus 的el-table展示房源列表配合分页组件。添加/编辑房源是一个复杂的表单我使用了el-form并进行了大量的表单验证规则配置。对于图片上传使用了el-upload组件将图片上传到后端或直接到云存储如 OSS后端返回图片的访问 URL 存入数据库。实操心得房源图片的管理是个大学问。我建议不要将图片以二进制形式直接存数据库而是存文件服务器或对象存储的 URL。这样前端可以直接用img src加载性能好。同时要做好图片的压缩和缩略图生成列表页用小图详情页再加载原图。3.2 订单管理模块业务流程的核心订单Order是连接用户、房源和资金的纽带状态流转是重中之重。状态机设计 我定义了一个订单的生命周期通常包括待支付-已支付/待确认-已确认-入住中-已完成-已取消。每个状态之间的转换都是有条件的。例如只有“待支付”的订单用户可以取消房东可以拒绝“待确认”的订单使其变为“已取消”“已确认”的订单在入住日期当天自动变为“入住中”。我在Order实体类中有一个status字段并在 Service 层编写了状态变更的方法如confirmOrder(Long orderId),cancelOrder(Long orderId, String reason)。在这些方法内部会校验当前状态是否允许变更为目标状态。库存房态扣减 这是保证业务正确性的关键。当用户成功创建订单支付成功后系统需要锁定对应房源在入住日期范围内的“库存”。我最初的做法是查询房源在那些日期是否可订如果可订则更新房态。但这里存在并发问题两个用户同时查询同一房源同一时间段可能都看到可订然后都成功下单造成超售。解决方案是使用乐观锁或分布式锁乐观锁在room表增加一个version字段。更新房态时带上查询时的 version 值。SQL 类似UPDATE room SET status?, versionversion1 WHERE id? AND version?。如果更新影响行数为0说明版本冲突操作失败。分布式锁推荐对于高并发场景我使用了 Redis 的SETNX命令实现一个简单的分布式锁锁的 key 可以是lock:room:{roomId}:{date}。在扣减库存前先获取锁操作完成后释放锁。这样可以确保同一房源同一日期的库存操作是串行的。前端实现 订单列表页提供了强大的筛选功能房东可以按状态、日期、房客姓名等筛选。对于每一个订单都提供符合其当前状态的操作按钮如“确认订单”、“办理入住”、“取消订单”。点击后调用相应的 API。3.3 用户与权限管理模块系统涉及多方角色平台管理员、民宿房东、普通房客。他们的权限截然不同。角色与权限设计 我采用了经典的 RBAC基于角色的访问控制模型。有三张核心表user用户、role角色、permission权限。user和role是多对多关系role和permission也是多对多关系。超级管理员拥有所有权限可以管理所有房源、订单、用户。房东可以管理自己名下的房源、处理自己房源的订单、查看自己房源的财务数据。房客可以浏览房源、下单、管理自己的订单、发表评论。后端实现 我集成了Spring Security和JWTJSON Web Token来实现认证和授权。登录用户提交用户名密码后端验证通过后生成一个 JWT Token其中包含用户ID、角色等信息返回给前端。鉴权前端在后续的请求头中携带此 Token通常放在Authorization: Bearer token。后端通过一个过滤器Filter拦截请求验证 Token 的有效性并从中提取用户信息存入 SecurityContext。授权在需要权限控制的 API 方法上使用PreAuthorize(“hasRole(‘LANDLORD’)”)或PreAuthorize(“hasAuthority(‘room:write’)”)这样的注解进行声明式控制。Spring Security 会自动判断当前用户是否具备所需权限。前端实现 前端根据登录用户的角色动态渲染侧边栏菜单和页面内的操作按钮。用户信息包括 Token可以存储在 Vuex/Pinia 中或者更简单地存储在localStorage中。Axios 可以配置请求拦截器自动为每个请求加上 Token 头。3.4 评论与财务统计模块评论模块相对直接主要涉及review表关联order_id和user_id。关键点在于业务规则只有状态为“已完成”的订单用户才能发表评论每条订单只能评论一次。前端展示评论时需要做好防 XSS 过滤避免用户输入恶意脚本。财务统计模块是给房东看的“仪表盘”。核心是复杂的统计查询。今日/本月数据今日预订数、今日收入、本月总收入。这需要根据order表的create_time和total_price字段结合status只统计已支付及之后的订单进行聚合查询。收入趋势图使用 ECharts 绘制折线图展示近30天或自定义时间段的每日收入。后端 API 需要接收时间范围参数返回按天分组聚合的数据。房源收入排行统计每个房源在一定时期内的订单总额进行排序。SQL 会涉及到order表和room表的关联查询与分组聚合。这些统计查询对数据库有一定压力尤其是数据量变大后。我的优化策略是为常用查询字段加索引如order表的create_time,status,room_id。定时任务预计算对于一些实时性要求不高的汇总数据如昨日总收入可以使用 Spring Boot 的Scheduled注解在每天凌晨跑一个定时任务将结果计算好存入一张statistics_daily表。前端查询时直接读这张表速度极快。缓存使用 Redis 缓存一些热点统计结果设置合理的过期时间。4. 开发环境搭建与关键配置详解光说不练假把式下面我把这个项目从零跑起来的关键步骤和配置细节分享一下。4.1 后端 Spring Boot 项目初始化与配置我使用 start.spring.io 或 IDEA 自带的 Spring Initializr 来生成项目骨架。依赖选择Spring Web用于构建 Web API。MyBatis Framework或直接选MyBatis-Plus。MySQL Driver数据库驱动。Lombok简化实体类代码强烈推荐。Spring Security安全框架。Spring Boot Actuator监控管理。Springdoc OpenAPI用于替代旧的 Springfox Swagger生成 OpenAPI 3.0 文档。关键的application.yml配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/bnb_management?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL调试用 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除字段名 logic-delete-value: 1 # 逻辑已删除值 logic-not-delete-value: 0 # 逻辑未删除值 # JWT配置 jwt: secret: yourSuperSecretKeyHereMakeItLongAndComplex # 密钥务必复杂且保密 expiration: 86400000 # token有效期单位毫秒这里是24小时 # SpringDoc OpenAPI 配置 springdoc: api-docs: path: /api-docs swagger-ui: path: /swagger-ui.html operations-sorter: method注意数据库密码和 JWT Secret 是敏感信息绝对不应该硬编码在配置文件中。在生产环境中必须使用环境变量、配置中心或密钥管理服务来注入。4.2 前端 Vue 项目初始化与配置使用 Vue CLI 或 Vite 创建项目。我更喜欢 Vite因为它启动和热更新更快。npm create vuelatest bnb-management-frontend创建过程中选择需要的特性TypeScript, Vue Router, Pinia (状态管理), ESLint。安装主要依赖cd bnb-management-frontend npm install element-plus axios echarts npm install --save-dev sass # 如果要用SCSS全局引入 Element Plus 和 Axios在main.ts中import { createApp } from vue import App from ./App.vue import router from ./router import ElementPlus from element-plus import element-plus/dist/index.css import * as ElementPlusIconsVue from element-plus/icons-vue const app createApp(App) // 注册所有图标 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } app.use(router) app.use(ElementPlus) app.mount(#app)创建一个utils/request.ts文件来封装 Axios配置基础 URL、请求超时、请求/响应拦截器用于自动添加 Token 和统一处理错误。4.3 数据库建表与样例数据这里给出核心的room表和order表的建表语句示例CREATE TABLE room ( id bigint NOT NULL AUTO_INCREMENT COMMENT 房源ID, title varchar(200) NOT NULL COMMENT 房源标题, description text COMMENT 房源描述, city varchar(50) NOT NULL COMMENT 所在城市, address varchar(200) NOT NULL COMMENT 详细地址, price_per_night int NOT NULL COMMENT 每晚价格单位分, max_guests int NOT NULL COMMENT 最多入住人数, status tinyint NOT NULL DEFAULT 1 COMMENT 状态0-待审核1-可预订2-已下架3-维修中, landlord_id bigint NOT NULL COMMENT 房东用户ID, facility_ids json DEFAULT NULL COMMENT 设施ID列表JSON数组, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted tinyint NOT NULL DEFAULT 0 COMMENT 逻辑删除, PRIMARY KEY (id), KEY idx_city (city), KEY idx_landlord (landlord_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT房源表; CREATE TABLE order ( id bigint NOT NULL AUTO_INCREMENT COMMENT 订单ID, order_no varchar(32) NOT NULL COMMENT 订单号唯一, room_id bigint NOT NULL COMMENT 房源ID, guest_id bigint NOT NULL COMMENT 房客用户ID, check_in_date date NOT NULL COMMENT 入住日期, check_out_date date NOT NULL COMMENT 退房日期, total_nights int NOT NULL COMMENT 入住晚数, total_price int NOT NULL COMMENT 订单总价分, status tinyint NOT NULL COMMENT 订单状态, guest_remark varchar(500) DEFAULT NULL COMMENT 房客备注, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_room_id (room_id), KEY idx_guest_id (guest_id), KEY idx_check_in (check_in_date), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单表;建议在开发初期就插入一些样例数据方便前后端联调。可以使用INSERT语句或者编写一个简单的 Spring Boot 单元测试来初始化数据。5. 典型业务场景的代码实现与联调让我们聚焦两个最核心的业务场景“房客下单”和“房东确认订单”看看前后端代码如何配合。5.1 场景一房客下单流程前端实现 (Vue Element Plus)房源详情页房客浏览房源选择入住和退房日期。前端需要验证日期有效性不能过去退房入住并实时计算总价单价 * 晚数。点击预订弹出一个表单对话框让房客填写入住人信息、备注等。提交订单前端收集所有数据房源ID、日期、总价、备注等调用后端 APIPOST /api/orders。template el-button typeprimary clickhandleBooking立即预订/el-button el-dialog v-modelbookingDialogVisible title确认订单 el-form :modelorderForm :rulesrules el-form-item label入住日期 propcheckInDate... /el-form-item el-form-item label退房日期 propcheckOutDate... /el-form-item el-form-item label总价{{ totalPrice }} 元/el-form-item el-form-item label入住人姓名 propcontactName... /el-form-item /el-form template #footer el-button clickbookingDialogVisible false取消/el-button el-button typeprimary clicksubmitOrder提交订单/el-button /template /el-dialog /template script setup import { ref, reactive } from vue; import { ElMessage } from element-plus; import axios from /utils/request; const bookingDialogVisible ref(false); const orderForm reactive({ roomId: null, checkInDate: , checkOutDate: , contactName: , remark: }); const totalPrice ref(0); const submitOrder async () { try { const response await axios.post(/api/orders, orderForm); if (response.data.code 200) { ElMessage.success(订单创建成功); bookingDialogVisible.value false; // 跳转到订单支付页面或订单列表页 } else { ElMessage.error(response.data.msg); } } catch (error) { ElMessage.error(网络错误或服务器异常); } }; /script后端实现 (Spring Boot Controller Service)RestController RequestMapping(/api/orders) public class OrderController { Autowired private OrderService orderService; PostMapping PreAuthorize(hasRole(GUEST)) // 只有房客角色可以创建订单 public ApiResponseOrderVO createOrder(Valid RequestBody CreateOrderDTO createOrderDTO) { // 从SecurityContext中获取当前登录用户ID Long userId SecurityUtils.getCurrentUserId(); OrderVO order orderService.createOrder(createOrderDTO, userId); return ApiResponse.success(order); } } Service Slf4j public class OrderServiceImpl implements OrderService { Autowired private RoomMapper roomMapper; Autowired private OrderMapper orderMapper; Autowired private RedisTemplateString, String redisTemplate; Transactional(rollbackFor Exception.class) // 开启事务 Override public OrderVO createOrder(CreateOrderDTO dto, Long guestId) { // 1. 参数校验日期合法性等Valid已做基础校验 // 2. 验证房源是否存在且状态可订 Room room roomMapper.selectById(dto.getRoomId()); if (room null || room.getStatus() ! RoomStatus.AVAILABLE.getCode()) { throw new BusinessException(房源不存在或不可预订); } // 3. 检查入住日期冲突核心 if (orderMapper.countConflictOrders(dto.getRoomId(), dto.getCheckInDate(), dto.getCheckOutDate()) 0) { throw new BusinessException(您选择的日期已被预订请重新选择); } // 4. 生成唯一订单号雪花算法或时间戳随机数 String orderNo generateOrderNo(); // 5. 计算总价这里简化实际可能涉及清洁费、服务费等 int totalNights (int) ChronoUnit.DAYS.between(dto.getCheckInDate(), dto.getCheckOutDate()); int totalPrice room.getPricePerNight() * totalNights; // 6. 构建订单实体并保存 Order order new Order(); order.setOrderNo(orderNo); order.setRoomId(dto.getRoomId()); order.setGuestId(guestId); order.setCheckInDate(dto.getCheckInDate()); order.setCheckOutDate(dto.getCheckOutDate()); order.setTotalNights(totalNights); order.setTotalPrice(totalPrice); order.setStatus(OrderStatus.PENDING_PAYMENT.getCode()); // 初始状态待支付 orderMapper.insert(order); // 7. 可以在这里发送消息通知房东如集成WebSocket或邮件 log.info(订单创建成功订单号{}, orderNo); // 8. 返回前端需要的视图对象 return convertToVO(order, room); } private String generateOrderNo() { // 示例时间戳 随机数 return ORD System.currentTimeMillis() (int)((Math.random()*91)*1000); } }5.2 场景二房东确认订单与房态更新后端 Service 层关键方法Override Transactional public void confirmOrder(Long orderId) { Order order orderMapper.selectById(orderId); if (order null || !order.getStatus().equals(OrderStatus.PENDING_CONFIRMATION.getCode())) { throw new BusinessException(订单不存在或当前状态不可确认); } // 获取当前登录用户房东并验证该订单的房源是否属于此房东 Long landlordId SecurityUtils.getCurrentUserId(); Room room roomMapper.selectById(order.getRoomId()); if (!room.getLandlordId().equals(landlordId)) { throw new BusinessException(无权操作此订单); } // 更新订单状态 order.setStatus(OrderStatus.CONFIRMED.getCode()); orderMapper.updateById(order); // 更新房源状态不房态是由订单日期锁定的房源本身状态可能一直是“可预订”。 // 但可以记录一条房态锁定日志或者在实际业务中这里可能触发一个“房态同步”事件。 log.info(房东 {} 确认了订单 {}, landlordId, orderId); }实操心得订单状态和房态库存的同步是一个需要仔细设计的点。在我的实现里房态是动态计算的查询某个房源在某个日期段是否可订本质是查这个日期段内该房源是否有“已确认”、“已支付”、“入住中”的订单。这种设计避免了维护一个静态的“房态日历表”更灵活但查询会稍复杂。另一种方案是预生成房态日历在订单状态变更时同步更新查询更快但维护逻辑复杂。需要根据业务量权衡。6. 部署上线与性能优化考量开发完成最终要部署到服务器上。我通常会选择一台 Linux 服务器如 CentOS 或 Ubuntu。6.1 后端部署打包在项目根目录执行mvn clean package -DskipTests会在target目录生成一个*.jar文件。上传将 jar 包上传到服务器例如/app/bnb-management/目录。运行使用nohup或 systemd 服务来启动应用确保进程在后台稳定运行。cd /app/bnb-management/ nohup java -jar bnb-management-backend-1.0.0.jar --spring.profiles.activeprod app.log 21 使用 Nginx 反向代理让 Nginx 监听 80/443 端口将请求转发到后端 Spring Boot 应用的 8080 端口。这样可以做负载均衡、静态文件服务、SSL 卸载等。server { listen 80; server_name your-domain.com; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 前端静态文件配置见下文 }6.2 前端部署构建在前端项目目录执行npm run build会生成一个dist文件夹里面是优化压缩后的静态文件HTML, JS, CSS。上传将dist文件夹内的所有内容上传到服务器例如/usr/share/nginx/html/bnb-frontend/。Nginx 配置配置 Nginx 来托管这些静态文件并处理前端路由History 模式。server { listen 80; server_name your-domain.com; root /usr/share/nginx/html/bnb-frontend; index index.html; location / { try_files $uri $uri/ /index.html; # 支持Vue Router的history模式 } # 后端API代理配置见上文 }6.3 性能与安全优化点数据库连接池Spring Boot 默认使用 HikariCP配置spring.datasource.hikari.*来优化连接数。API 响应缓存对于不常变的数据如城市列表、设施列表可以在 Controller 方法上使用Cacheable注解将其缓存到 Redis。静态资源 CDN将图片、CSS、JS 等静态资源上传到 OSS 并配置 CDN 加速大幅减轻服务器压力提升用户访问速度。接口限流与防刷对于登录、发送验证码等接口使用 Guava RateLimiter 或 Redis 实现简单的限流防止恶意请求。SQL 注入与 XSS 防护使用 MyBatis 的#{}预编译方式可防 SQL 注入。前端对用户输入进行转义后端也可以使用过滤器或工具类进行 XSS 过滤。日志与监控配置好日志框架Logback将日志按级别输出到文件。结合 Spring Boot Actuator 和 Prometheus Grafana搭建应用监控看板。7. 开发中遇到的典型问题与解决方案在实际编码和联调过程中不可能一帆风顺。下面记录了几个让我印象深刻的“坑”和填坑方法。7.1 跨域问题 (CORS)当前端运行在localhost:5173后端运行在localhost:8080时浏览器会因为同源策略阻止前端请求后端 API报 CORS 错误。解决方案在后端 Spring Boot 应用中配置全局 CORS 规则。Configuration public class WebConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) // 针对所有/api开头的接口 .allowedOriginPatterns(*) // 生产环境应替换为具体的前端域名 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }注意在生产环境中allowedOriginPatterns应该设置为确切的前端域名如https://your-domain.com而不是*以增强安全性。7.2 前端路由刷新 404 问题当使用 Vue Router 的 History 模式时如果你直接访问一个深链接如/room/123或刷新页面Nginx 会去服务器上找/room/123这个文件显然找不到返回 404。解决方案正如前面部署部分提到的在 Nginx 配置中对于非静态文件请求都回退到index.html。location / { try_files $uri $uri/ /index.html; }7.3 日期时间处理的一致性问题前后端、数据库之间传递日期时间经常遇到时区不一致、格式不对的问题。解决方案约定使用 ISO 8601 格式如”2023-10-27T10:00:0008:00″或简单的yyyy-MM-dd格式在 JSON 中传输。在后端统一将数据库连接时区设置为东八区serverTimezoneAsia/Shanghai在实体类字段上使用JsonFormat注解指定序列化格式。public class Order { JsonFormat(pattern “yyyy-MM-dd”) private LocalDate checkInDate; JsonFormat(pattern “yyyy-MM-dd HH:mm:ss”) private LocalDateTime createTime; }7.4 文件上传大小限制Spring Boot 默认对文件上传大小有限制通常为 1MB上传大图片时会失败。解决方案在application.yml中调整配置。spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB7.5 第三方依赖冲突在引入多个 Starter 时可能会发生依赖的库版本冲突导致应用启动失败或运行时异常。解决方案使用mvn dependency:tree命令查看依赖树找到冲突的库。然后在pom.xml中通过exclusions排除掉不需要的传递性依赖或者使用dependencyManagement统一管理版本。整个项目从构思到实现就像完成一次精密的搭建。选择 Spring Boot 和 Vue 这套组合让全栈开发变得清晰而高效。后端提供坚实、稳定的 API 服务前端构建出交互流畅的管理界面。过程中最大的收获不是写完了多少行代码而是对一个真实业务系统的完整生命周期有了更深的体会从需求分析、数据库设计、接口定义到具体编码、调试、部署上线以及过程中对并发安全、数据一致性、用户体验的不断权衡和优化。如果你能跟着这个思路把每个模块都亲手实现一遍遇到问题去搜索、去解决那么你对 Java 全栈开发的理解一定会迈上一个坚实的台阶。这个项目代码和演示视频我已经整理好希望能成为一个有价值的参考起点。本文还有配套的精品资源点击获取
返回列表