
简介本资源是一套面向计算机专业本科生毕业设计与课程实践的完整小区报修系统实现方案基于Spring Boot后端与Vue前端技术栈解决传统物业报修流程低效、信息不透明、反馈滞后等实际问题适用于智慧社区管理类课题开发与部署验证。压缩包共694个文件含317个Java后端逻辑代码、104个Vue组件及页面、78个JS交互脚本、40个XML配置与Mapper映射、5个YML环境配置以及SQL建表语句、部署说明文档.docx、多环境启动脚本.bat和前后端配置文件.env.development等整体仅2.15MB结构清晰、开箱即用。已有44人学习下载资源附带系统架构图、用例图、E-R图等标准软件工程图表覆盖系统管理、用户权限、报修全流程、维修工具调度、评价反馈等七大核心模块提供从数据库设计到前后端联调、本地一键启动的全链路支持。1. 项目概述与核心价值最近在社区里看到不少朋友在讨论物业管理和社区服务数字化的话题尤其是“小区报修”这个场景。作为一个前后端都摸爬滚打过的开发者我恰好完整地设计并实现过一个基于SpringBoot和Vue的小区报修系统从数据库设计、接口开发到前端交互、服务器部署算是踩遍了所有的坑也积累了不少实战心得。今天就来和大家详细拆解一下这个项目的设计与实现我会把代码结构、数据库设计的关键考量、以及部署时那些“教科书上不会写”的细节都分享出来。无论你是想学习如何将SpringBoot和Vue组合成一个完整的全栈项目还是正打算为自家小区或公司内部开发一个类似的工单管理系统这篇文章都能给你提供一份可以直接“抄作业”的详细指南。这个系统的核心目标很明确取代传统低效的电话、微信群报修模式。想象一下业主在手机上提交报修单物业客服在线受理并派单给维修工维修工接单、处理、完成后上传照片业主在线确认并评价——整个流程线上化、可视化责任清晰效率倍增。它本质上是一个轻量级的工单流转与协同平台技术栈上我们选择了非常经典的组合SpringBoot负责构建稳定、高效的后端RESTful APIVue.js作为前端框架构建用户友好的交互界面MySQL作为关系型数据库存储核心业务数据。接下来我会从设计思路、技术细节、代码实现到部署上线一步步带你走完全程。2. 系统整体架构与设计思路拆解2.1 为什么选择SpringBoot Vue这套技术栈在做技术选型时我主要考虑了四个维度开发效率、生态成熟度、团队技能匹配度以及项目维护成本。SpringBoot Vue的组合在这几个方面表现都非常均衡。后端选择SpringBoot的理由约定大于配置SpringBoot的自动配置和起步依赖Starter让搭建一个Web服务变得极其简单。你不需要再为复杂的XML配置头疼专注于业务逻辑开发即可。对于报修系统这种业务逻辑明确但并发量初期不会特别高的内部系统SpringBoot的开发效率优势巨大。生态完整且稳定Spring生态拥有几乎涵盖所有企业级应用需要的组件如Spring Security安全控制、Spring Data JPA数据持久化、Spring Boot Admin应用监控等。这意味着你在实现权限管理、数据库操作、日志监控等功能时有大量经过验证的最佳实践和社区支持可以借鉴。易于集成和测试内嵌的Tomcat服务器使得应用可以打包成一个独立的JAR文件运行简化了部署。同时它对RESTful API的支持非常友好配合Swagger可以自动生成API文档极大方便了前后端联调。前端选择Vue.js的理由渐进式与易上手Vue的学习曲线相对平缓对于后端开发人员或者新手前端来说更容易掌握。其核心库只关注视图层可以与其它库或现有项目整合也便于按需引入路由Vue Router、状态管理Vuex/Pinia等更高级的功能。组件化开发报修系统的前端页面有大量可复用的部分例如报修单卡片、用户信息展示组件、图片上传组件等。Vue强大的单文件组件.vue文件能力使得我们可以将这些UI和逻辑封装成独立的组件提高代码的复用性和可维护性。活跃的生态系统Element Plus、Vant等基于Vue的UI组件库非常成熟提供了大量开箱即用的高质量组件如表单、表格、弹窗能让我们快速搭建出美观且交互一致的管理后台和移动端界面。数据交互设计前后端完全分离我们采用典型的前后端分离架构。前端Vue应用独立部署通过Axios库调用后端SpringBoot提供的RESTful API接口进行数据交互数据格式统一为JSON。这种架构的好处是前后端可以并行开发通过API文档进行契约后端只需关注数据逻辑和API稳定性前端则可以自由选择技术栈和优化用户体验。2.2 核心业务流程与功能模块设计在动代码之前清晰地梳理业务流程是至关重要的。小区报修的核心业务流程可以抽象为一条工单的生命周期提交报修业主通过小程序或H5页面填写报修问题如水管漏水、地点、期望时间并可上传现场图片。客服受理物业客服人员在管理后台看到新报修单进行审核确认信息无误后将工单状态改为“已受理”。工单派发客服根据报修类型电工、水工、保洁等和维修工的空闲状态将工单派发给特定的维修人员。维修处理维修工在自己的手机端接收到派工通知前往处理。处理过程中可以更新进度处理完成后上传维修后的照片并填写处理说明将工单状态置为“已完成”。业主确认与评价业主收到完成通知查看处理结果和照片进行确认。确认后可以对本次服务进行满意度评价。工单归档已完成且已评价的工单进入历史档案供后续查询和统计分析。基于这个流程我们将系统划分为以下几个核心功能模块用户权限模块实现业主、客服、维修工、管理员等不同角色的登录、认证和权限控制。这是系统安全的基石。报修单管理模块工单的CRUD增删改查核心包括提交、查询支持按状态、时间、类型筛选、详情查看、状态流转。工单流转模块驱动工单状态变化的引擎包括客服的受理与派单、维修工的接单与完成操作。消息通知模块当工单状态发生变化时如新报修、已派单、已完成通过站内信、短信或小程序模板消息通知相关用户。评价反馈模块业主对已完成工单进行评分和文字评价。数据统计模块为管理员提供仪表盘展示报修量、完成率、平均处理时长、满意度等关键指标。2.3 数据库设计核心考量数据库设计直接决定了系统的性能、扩展性和数据一致性。我们使用MySQL在设计表结构时我主要遵循了以下几个原则范式与反范式的平衡在满足第三范式以减少数据冗余的同时为了查询性能在个别地方做了适当的反范式设计。例如在repair_order报修单表中除了存业主ID (user_id)还会冗余存储业主的姓名和楼栋房号这样在列表查询时就不需要每次都去关联用户表。状态字段的设计工单状态status是核心字段。我使用TINYINT类型存储状态码如0-待受理1-已受理2-已派单3-处理中4-已完成5-已评价6-已关闭并在后端使用枚举类Enum进行映射这样既节省存储空间又保证了程序的可读性。图片/文件存储策略报修和维修过程都需要上传图片。绝对不建议将图片以BLOB形式直接存入数据库这会让数据库体积暴增严重影响性能。标准的做法是将图片文件上传到对象存储服务如阿里云OSS、腾讯云COS或服务器的特定目录在数据库中只保存文件的访问路径URL。索引的合理创建对高频查询和作为关联条件的字段建立索引如user_id、status、create_time。但索引不是越多越好它会降低写操作的速度。需要根据实际查询SQL进行分析。注意在设计“派单”逻辑时涉及到维修工的选择。这里有一个常见的坑如何避免一个维修工同时被派过多工单我们可以在worker维修工表中增加一个current_order_count当前工单数字段并在派单时通过数据库事务Transactional来保证“查询空闲工人”和“更新其工单数”这两个操作的原子性防止超派。3. 后端SpringBoot核心实现详解3.1 项目结构与依赖配置我习惯使用Spring Initializr或IDE的集成功能快速初始化项目。核心依赖包括spring-boot-starter-web: 提供Web MVC支持。spring-boot-starter-data-jpa: 使用JPA进行数据持久化配合Hibernate。spring-boot-starter-security: 处理认证和授权这是一个重点后面细说。mysql-connector-java: MySQL驱动。spring-boot-starter-validation: 用于接口参数校验。knife4j-spring-boot-starter: 集成Swagger生成漂亮的API文档。hutool-all: 一个非常实用的Java工具包可以简化很多日常操作。项目采用典型的分层架构src/main/java/com/example/repair/ ├── RepairApplication.java // 启动类 ├── config/ // 配置类安全、跨域等 ├── controller/ // 控制器层接收请求返回响应 ├── service/ // 业务逻辑层 │ └── impl/ // 业务逻辑实现类 ├── repository/ // 数据访问层JPA Repository接口 ├── entity/ // 实体类与数据库表映射 ├── dto/ // 数据传输对象用于前后端交互 ├── vo/ // 视图对象用于接口返回 └── utils/ // 工具类在application.yml中需要配置数据库连接、JPA属性如ddl-auto: update在开发时自动更新表结构生产环境务必改为validate或none、服务器端口等。3.2 用户认证与权限控制Spring Security JWT这是系统的安全大门必须做得扎实。我采用“Spring Security JWTJSON Web Token”的方案替代传统的Session更适合前后端分离的无状态API。1. 核心流程登录用户提交用户名密码后端验证通过后使用JJWT库生成一个JWT令牌Token其中包含用户ID、角色等信息并设置一个过期时间如2小时。令牌返回将JWT通过响应体或Header返回给前端。后续请求前端在后续的每个请求的Header中携带此Token格式Authorization: Bearer token。请求拦截后端配置一个JWT认证过滤器JwtAuthenticationFilter拦截所有请求从Header中解析Token验证其有效性和过期时间并从中提取用户信息存入SecurityContext供后续权限判断使用。2. 关键实现细节密码存储绝对不要明文存储密码使用Spring Security提供的BCryptPasswordEncoder对密码进行单向哈希加密后存入数据库。登录时用同样的编码器对输入的密码进行编码然后与数据库中的密文比对。权限注解在Controller的方法上使用PreAuthorize(“hasRole(‘ADMIN’)”)或PreAuthorize(“hasAuthority(‘repair:create’)”)这样的注解可以非常精细地控制接口访问权限。自定义UserDetailsService你需要实现这个接口的loadUserByUsername方法根据用户名可能是手机号从数据库加载用户信息和其拥有的权限列表并封装成Spring Security认识的UserDetails对象。实操心得JWT的“无状态”既是优点也是缺点。因为它无法在服务端主动失效所以设置一个合理的较短过期时间如2小时非常重要。同时可以实现一个简单的“令牌黑名单”机制当用户修改密码或主动登出时将尚未过期的Token加入黑名单可以存Redis在过滤器校验时额外检查一下以增强安全性。3.3 报修单业务逻辑与API设计这是业务的核心。我们围绕RepairOrder实体来构建。1. 实体与DTO设计// RepairOrder.java (Entity) Entity Data public class RepairOrder { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; private String orderNo; // 报修单号可按规则生成如BX20240520001 private Long userId; // 报修用户ID private String userNickname; // 冗余报修人姓名 private String userPhone; // 冗余报修人电话 private String location; // 报修地点如“3栋2单元1001” private String description; // 问题描述 Enumerated(EnumType.ORDINAL) private OrderStatus status; // 状态使用枚举 private String imageUrls; // 图片URL多个用逗号分隔 private Long workerId; // 指派维修工ID private String workerName; // 冗余维修工姓名 private String repairNotes; // 维修说明 private String finishImageUrls; // 维修后图片 private Integer rating; // 评分 1-5 private String comment; // 评价内容 CreationTimestamp private LocalDateTime createTime; private LocalDateTime handleTime; // 受理时间 private LocalDateTime finishTime; // 完成时间 } // 使用DTO接收前端请求和返回数据避免暴露实体全部字段2. 核心API接口示例POST /api/repair-orders业主提交报修单。需要处理图片上传先上传到OSS得到URL再和表单数据一起提交。GET /api/repair-orders分页查询报修单。根据不同角色业主、客服、维修工返回不同的数据业主只能看自己的客服和维修工看分配给自己的。这里会大量用到JPA的Specification或QueryDSL来构建动态查询条件。PUT /api/repair-orders/{id}/accept客服受理工单。将状态从“待受理”改为“已受理”。PUT /api/repair-orders/{id}/assign客服派单。需要接收维修工ID参数更新worker_id和状态。PUT /api/repair-orders/{id}/complete维修工完成工单。更新状态、维修说明和上传完工图片。PUT /api/repair-orders/{id}/rate业主评价工单。3. 事务管理对于涉及多个数据库更新操作的业务比如派单更新工单状态更新维修工当前任务数一定要在Service方法上添加Transactional注解保证原子性避免产生数据不一致。3.4 图片上传与存储方案图片上传是一个独立且重要的功能点。我建议单独提供一个文件上传接口。1. 接口设计 (FileUploadController):PostMapping(/upload/image) public ResultString uploadImage(RequestParam(file) MultipartFile file) { // 1. 校验文件大小、类型jpg, png、安全性简单校验文件头 // 2. 生成唯一文件名UUID 时间戳防止覆盖 String fileName UUID.randomUUID() “_” System.currentTimeMillis() “.” FileUtil.extName(file.getOriginalFilename()); // 3. 上传到云存储或本地 String fileUrl storageService.upload(file.getInputStream(), fileName); // 4. 返回文件的完整访问URL return Result.success(fileUrl); }2. 存储服务实现 (StorageService):本地存储简单适合内网或测试。使用Files.copy将文件流保存到服务器磁盘的某个目录如/upload/repair-images/。需要配置静态资源映射让外部能通过HTTP访问到这些图片。缺点扩容麻烦备份困难不适合分布式部署。对象存储推荐使用阿里云OSS、腾讯云COS等。SDK集成简单可靠性高自带CDN加速。你需要先在云服务商创建Bucket获取AccessKey和SecretKey然后在项目中配置。上传文件到云端后你会获得一个公网可访问的URL直接存这个URL到数据库即可。注意事项无论哪种方式都要注意限制上传文件的大小在application.yml中配置spring.servlet.multipart.max-file-size并对文件后缀和内容进行基本的安全检查防止上传恶意文件。对于云存储建议为上传的图片生成缩略图在前端列表展示时使用缩略图以提升加载速度。4. 前端Vue.js实现与关键交互4.1 前端项目初始化与组件规划使用Vue CLI或Vite快速搭建项目。我习惯采用以下结构src/ ├── api/ // 所有后端API请求封装使用axios ├── assets/ // 静态资源 ├── components/ // 公共组件如UploadImage.vue, OrderCard.vue ├── router/ // 路由配置 ├── store/ // 状态管理Vuex或Pinia ├── views/ // 页面组件 │ ├── user/ // 用户相关页面 │ ├── repair/ // 报修相关页面 │ └── admin/ // 管理后台页面 ├── utils/ // 工具函数如时间格式化、请求拦截器 └── App.vueUI组件库我选择Element Plus因为它为管理后台类应用提供了丰富的组件且文档和社区都非常完善。4.2 用户登录与Token管理前端安全的核心是妥善管理JWT Token。登录逻辑在登录页面调用/api/auth/login接口成功后从响应中拿到token和userInfo。Token存储不要用localStorage虽然方便但存在XSS攻击风险。更安全的做法是存储在httpOnly的Cookie中但这需要后端配合设置。一个折中且常见的方案是存储在sessionStorage中页面关闭即失效相对安全。同时将userInfo存入Vuex/Pinia状态管理库供全局使用。请求拦截器axios这是关键。你需要配置axios的请求拦截器在每次请求前自动从sessionStorage中读取token并添加到请求头的Authorization字段中。// request.js import axios from ‘axios’; const service axios.create({ baseURL: process.env.VUE_APP_BASE_API }); service.interceptors.request.use( config { const token sessionStorage.getItem(‘token’); if (token) { config.headers[‘Authorization’] ‘Bearer ’ token; } return config; }, error Promise.reject(error) );响应拦截器同样重要。在响应拦截器中判断如果返回的HTTP状态码是401未授权则说明token已过期或无效此时应自动跳转到登录页面并清空本地存储的token和用户信息。4.3 报修单列表与表单交互1. 报修单列表页这是一个典型的“查询表单表格分页”组合。使用Element Plus的el-form、el-table和el-pagination组件可以快速搭建。查询表单中包含状态筛选、时间范围选择等字段。点击查询时将参数组合调用后端分页查询API。表格列展示报修单号、问题描述、状态使用el-tag根据状态显示不同颜色、报修人、时间等。状态列可以做成过滤器将数字状态码转换为中文。操作列根据当前用户角色和工单状态动态渲染操作按钮。例如对于“待受理”的工单客服可以看到“受理”按钮维修工对于“已派单”的工单可以看到“开始处理”按钮。这需要前端有基本的权限判断逻辑。2. 提交报修表单页表单验证使用Element Plus的el-form的rules属性定义非空、手机号格式、图片数量等规则。图片上传使用el-upload组件配置为手动上传:auto-upload“false”。用户选择图片后先调用我们后端的/api/upload/image接口上传获得URL再将URL填入表单的imageUrls数组字段中。最后提交整个报修表单时将图片URL数组作为字段之一提交。地理位置可以集成高德或腾讯地图的JavaScript API让用户在地图上点选或搜索楼栋提升体验。3. 工单详情与状态流转详情页是一个只读视图展示所有信息。关键在于状态流转按钮的逻辑。例如当客服点击“派单”按钮时弹出一个抽屉el-drawer或对话框el-dialog里面是一个维修工选择列表可以通过另一个接口获取空闲维修工列表选择后调用派单API。4.4 状态管理与组件通信对于这种中型应用状态管理是必须的。我推荐使用PiniaVuex的下一代它更简单、类型安全。用户状态创建一个useUserStore用于存储登录后的token、userInfo、roles等。登录、登出、获取用户信息等动作都封装为Store的actions。全局状态例如可以创建一个useAppStore来管理侧边栏折叠状态、主题色等。组件通信对于父子组件用props和$emit对于兄弟或远房组件优先考虑通过共同的父组件传递或者使用Pinia Store来共享状态。尽量避免使用EventBus在Vue 3中其模式已不再推荐。5. 数据库设计与关键表结构这里详细给出几个核心表的设计你可以直接用于创建数据库。5.1 用户表 (sys_user)这是所有用户的基表通过user_type字段区分角色。CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT ‘登录账号手机号’, password varchar(100) NOT NULL COMMENT ‘加密后的密码’, nickname varchar(50) DEFAULT NULL COMMENT ‘用户昵称/真实姓名’, phone varchar(20) NOT NULL COMMENT ‘手机号’, avatar varchar(500) DEFAULT NULL COMMENT ‘头像URL’, user_type tinyint NOT NULL DEFAULT ‘1’ COMMENT ‘用户类型1-业主2-客服3-维修工4-管理员’, building_info varchar(200) DEFAULT NULL COMMENT ‘业主专属楼栋房号如3-2-1001’, skill varchar(200) DEFAULT NULL COMMENT ‘维修工专属技能如电工,水工’, current_order_count int DEFAULT ‘0’ COMMENT ‘维修工专属当前负责工单数’, status tinyint DEFAULT ‘1’ COMMENT ‘账号状态0-禁用1-正常’, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username), UNIQUE KEY uk_phone (phone), KEY idx_user_type (user_type) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘系统用户表’;5.2 报修单表 (repair_order)系统的核心业务表。CREATE TABLE repair_order ( id bigint NOT NULL AUTO_INCREMENT, order_no varchar(30) NOT NULL COMMENT ‘报修单号规则生成’, user_id bigint NOT NULL COMMENT ‘报修人ID’, user_nickname varchar(50) DEFAULT NULL COMMENT ‘冗余报修人姓名’, user_phone varchar(20) DEFAULT NULL COMMENT ‘冗余报修人电话’, location varchar(200) NOT NULL COMMENT ‘报修地点’, description text NOT NULL COMMENT ‘问题描述’, status tinyint NOT NULL DEFAULT ‘0’ COMMENT ‘状态0-待受理1-已受理2-已派单3-处理中4-已完成5-已评价6-已关闭’, category varchar(50) DEFAULT NULL COMMENT ‘报修分类水电,门窗,保洁等’, image_urls text COMMENT ‘报修图片URLJSON数组或逗号分隔’, worker_id bigint DEFAULT NULL COMMENT ‘指派维修工ID’, worker_name varchar(50) DEFAULT NULL COMMENT ‘冗余维修工姓名’, repair_notes text COMMENT ‘维修说明’, finish_image_urls text COMMENT ‘维修后图片URL’, rating tinyint DEFAULT NULL COMMENT ‘评分1-5’, comment varchar(500) DEFAULT NULL COMMENT ‘评价内容’, expected_time datetime DEFAULT NULL COMMENT ‘期望上门时间’, create_time datetime DEFAULT CURRENT_TIMESTAMP, handle_time datetime DEFAULT NULL COMMENT ‘客服受理时间’, assign_time datetime DEFAULT NULL COMMENT ‘派单时间’, finish_time datetime DEFAULT NULL COMMENT ‘维修完成时间’, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user_id (user_id), KEY idx_worker_id (worker_id), KEY idx_status (status), KEY idx_create_time (create_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘报修工单表’;5.3 系统操作日志表 (sys_log)用于记录关键操作便于审计和排查问题。CREATE TABLE sys_log ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint DEFAULT NULL COMMENT ‘操作用户ID’, username varchar(50) DEFAULT NULL COMMENT ‘操作用户名’, operation varchar(100) DEFAULT NULL COMMENT ‘操作描述’, method varchar(200) DEFAULT NULL COMMENT ‘请求方法’, params text COMMENT ‘请求参数’, ip varchar(50) DEFAULT NULL COMMENT ‘操作IP’, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT ‘操作时间’, PRIMARY KEY (id), KEY idx_create_time (create_time), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘系统操作日志表’;设计心得在repair_order表中冗余存储user_nickname、user_phone、worker_name等字段是一种典型的“空间换时间”策略。虽然增加了少量存储但在查询工单列表时避免了多表关联查询JOIN在大数据量下能显著提升查询性能。这种反范式设计在读多写少的业务场景中非常有效。6. 系统部署与上线实战开发完成只是第一步让系统稳定跑在服务器上才是终点。我推荐使用Docker Docker Compose进行部署它能解决环境不一致的“魔鬼”问题。6.1 后端SpringBoot应用打包与Docker化打包在项目根目录使用Maven命令mvn clean package -DskipTests打包会在target目录生成一个可执行的JAR文件如repair-system-0.0.1-SNAPSHOT.jar。编写Dockerfile在项目根目录创建Dockerfile。# 使用官方的OpenJDK 11作为基础镜像 FROM openjdk:11-jre-slim # 设置工作目录 WORKDIR /app # 将Maven打包好的jar文件复制到容器内 COPY target/repair-system-*.jar app.jar # 暴露应用端口与application.yml中server.port一致 EXPOSE 8080 # 指定容器启动时执行的命令 ENTRYPOINT [“java”, “-jar”, “-Dspring.profiles.activeprod”, “app.jar”]注意这里通过-Dspring.profiles.activeprod指定使用生产环境配置文件application-prod.yml你需要在这个文件里配置生产环境的数据库连接、Redis地址等。构建镜像在Dockerfile所在目录执行docker build -t repair-backend:latest .6.2 前端Vue应用打包与Nginx配置打包在前端项目目录执行npm run buildVue CLI或npm run buildVite会在dist目录生成静态文件。编写Nginx配置文件创建nginx.conf。server { listen 80; server_name your-domain.com; # 你的域名或服务器IP location / { root /usr/share/nginx/html; # 静态文件目录 index index.html index.htm; try_files $uri $uri/ /index.html; # 支持Vue Router的history模式 } # 配置API代理解决前端跨域问题 location /api/ { proxy_pass http://backend: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; } # 配置上传文件的代理如果图片存在后端服务器本地 location /upload/ { proxy_pass http://backend:8080/upload/; } }编写前端DockerfileFROM nginx:alpine COPY dist/ /usr/share/nginx/html/ COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 806.3 使用Docker Compose编排所有服务这是最优雅的一步。创建一个docker-compose.yml文件将MySQL、Redis、后端、前端全部定义在一起。version: ‘3.8’ services: mysql: image: mysql:8.0 container_name: repair-mysql environment: MYSQL_ROOT_PASSWORD: your_strong_root_password # 务必修改 MYSQL_DATABASE: repair_system volumes: - mysql_data:/var/lib/mysql # 数据持久化 - ./init.sql:/docker-entrypoint-initdb.d/init.sql # 可选的初始化SQL ports: - “3306:3306” networks: - repair-network redis: image: redis:alpine container_name: repair-redis ports: - “6379:6379” networks: - repair-network backend: build: ./backend # Dockerfile所在目录 container_name: repair-backend depends_on: - mysql - redis environment: - SPRING_PROFILES_ACTIVEprod - DB_HOSTmysql # 使用服务名连接 - REDIS_HOSTredis ports: - “8080:8080” networks: - repair-network frontend: build: ./frontend # Dockerfile所在目录 container_name: repair-frontend depends_on: - backend ports: - “80:80” networks: - repair-network volumes: mysql_data: networks: repair-network: driver: bridge一键部署在docker-compose.yml文件所在目录执行docker-compose up -d。所有服务就会按依赖顺序启动并运行在同一个自定义网络中容器间可以通过服务名如mysql,backend互相访问。6.4 生产环境关键配置与优化数据库连接池在生产环境的application-prod.yml中务必配置合适的连接池参数如HikariCP根据预估的并发量设置maximum-pool-size。JVM参数在Dockerfile的ENTRYPOINT中或docker-compose.yml的environment里可以设置JVM内存参数如-Xms512m -Xmx1024m。日志配置Logback或Log4j2将日志输出到文件并按日期、大小滚动归档。不要只打印到控制台。健康检查Spring Boot Actuator提供了/actuator/health端点可以在docker-compose.yml中为backend服务配置健康检查确保容器状态正常。备份与监控定期备份MySQL数据。使用Prometheus Grafana监控服务器和应用的各项指标CPU、内存、JVM、接口响应时间等。7. 开发与部署中的常见问题与排查在实际开发和部署过程中你几乎一定会遇到下面这些问题。我把我的踩坑经验和解决方案记录下来希望能帮你节省大量时间。7.1 跨域问题CORS这是前后端分离项目第一个拦路虎。浏览器出于安全考虑会阻止前端页面向不同域名、端口或协议的接口发起请求。解决方案在后端SpringBoot应用中全局配置CORS。创建一个配置类即可。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(“/**”) // 对所有接口 .allowedOriginPatterns(“*”) // 允许所有源生产环境应指定具体前端地址 .allowedMethods(“GET”, “POST”, “PUT”, “DELETE”, “OPTIONS”) .allowedHeaders(“*”) .allowCredentials(true) // 允许携带Cookie .maxAge(3600); } }注意如果使用了Spring Security上述配置可能失效需要在Security配置链中额外添加.cors()配置。更简单的做法是在生产环境通过Nginx反向代理让前端和后端API在同一个域名下从而彻底避免跨域。7.2 前端路由在刷新后404这是因为Vue Router使用了history模式当你直接访问一个非根路径如/repair/list或刷新页面时这个路径会被发送到服务器Nginx而服务器上并没有这个实际的文件于是返回404。解决方案在Nginx配置中见6.2节添加关键的一行try_files $uri $uri/ /index.html;。它的作用是当请求的文件或目录不存在时将请求重定向到index.html由Vue应用内部的路由来处理。7.3 图片上传大小限制默认情况下SpringBoot对上传文件大小有限制通常1MB。上传大图片时会报错。解决方案在application.yml中增加配置spring: servlet: multipart: max-file-size: 10MB # 单个文件最大大小 max-request-size: 20MB # 单次请求总文件最大大小同时Nginx作为反向代理也可能有大小限制需要在Nginx配置中增加client_max_body_size 20m;。7.4 数据库连接超时或连接数耗尽在并发稍高或慢查询较多时可能出现。排查与解决检查连接池配置确保maximum-pool-size设置合理通常为CPU核心数 * 2 磁盘数。监控慢查询在MySQL中开启慢查询日志slow_query_logON定期分析并优化耗时长的SQL语句。为常用查询字段添加索引。检查代码中的连接泄漏确保所有数据库操作都在Transactional注解的方法内或正确关闭了EntityManager/Connection。7.5 部署后前端访问后端API 502 Bad Gateway这通常是Nginx无法连接到后端SpringBoot服务。排查步骤检查后端容器是否运行docker-compose ps查看backend服务状态。检查后端日志docker-compose logs backend查看是否有启动错误。检查网络确保docker-compose.yml中所有服务在同一个自定义网络repair-network内并且前端Nginx配置中的proxy_pass地址正确应使用Docker服务名http://backend:8080而不是localhost:8080。检查端口映射确认后端应用在容器内监听的端口默认8080与Dockerfile中EXPOSE的端口以及docker-compose.yml中映射的端口一致。7.6 性能优化小技巧前端懒加载对于Vue的路由使用() import(‘…’)语法实现组件懒加载减少首屏加载体积。接口防抖与节流对于搜索框输入联想等频繁触发的接口在前端使用防抖debounce或节流throttle函数控制请求频率。数据库查询优化列表查询一定要分页使用JPA的Pageable。避免SELECT *只查询需要的字段。复杂查询或统计报表考虑使用数据库的视图View或定期跑任务将结果存入统计表用空间换时间。缓存策略对于不常变但频繁访问的数据如小区楼栋信息、维修工列表可以引入Redis做缓存。Spring Boot Cache抽象层可以很方便地集成Redis。这个项目从设计到上线的全过程涉及了全栈开发的方方面面。技术本身没有太多高深莫测的东西关键在于如何将各个模块有机地组合起来并处理好其中的细节和边界情况。我最深的体会是清晰的业务流程设计比盲目敲代码重要十倍而Docker化部署则是将开发成果转化为稳定服务的最省心方式。希望这份超详细的拆解能帮你少走弯路顺利搭建起自己的报修系统。如果在实际操作中遇到任何问题欢迎在评论区交流。本文还有配套的精品资源点击获取