ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringBoot2+Vue3智慧社区管理系统实战:从数据库设计到部署上线

SpringBoot2+Vue3智慧社区管理系统实战:从数据库设计到部署上线 最近在社区开源平台放了一套智慧社区管理系统的完整源码技术栈是 SpringBoot2 Vue3 MyBatis-Plus MySQL8.0 这个前后端分离的标准组合同步附带了数据库脚本、接口文档和部署说明。整套系统并不是那种只为了应付演示的玩具项目小区档案、房产信息、业主绑定、物业缴费、报修工单、车位管理、公告发布这些业务模块都做了闭环。发出去之后经常有人私信问这套系统的核心表到底怎么设计的MyBatis-Plus 的分页和条件构造器在实际项目中怎么用才顺手MySQL8.0 升级之后有没有遇到连接问题Vue3 后台管理页面的登录态和权限控制是怎么搭的这篇文章就把我在开发这套系统过程中踩过的坑、做过取舍的地方、以及真正跑通全流程的关键细节一次性说清楚写给我自己复盘也写给打算拿这套系统做毕业设计或者转行练手的朋友。1. 智慧社区管理系统的业务全貌先想清楚要管什么1.1 五个核心模块拆解从小区档案到物业缴费在做任何系统之前我习惯先把业务对象列出来。智慧社区管理系统表面上看是一个后台管理平台但真正落到业务层面它管理的是**物理空间小区/楼栋/房屋和住在空间里的人业主/家属/租户**之间的关系。整套系统我最终拆成了五个核心模块。第一个是小区资源档案模块。这里的小区不是简单的名称字段而是一个树形结构小区下有楼栋楼栋下有单元单元下有房屋。每套房屋有面积、户型、朝向、当前居住状态自住/出租/空置。这个树形结构是整个系统的地基因为后面的缴费、报修、车辆绑定最终都要关联到具体的房屋上。我见过很多初学朋友的数据库设计直接一张表把所有字段塞进去结果写后面的业务逻辑时到处 join维护成本极高。第二个是业主与住户管理模块。业主和房屋之间是多对多的关系一个人可以在一个小区拥有多套房产也可以同时是业主和家属。在数据库层面我用了单独的关联表来维护而不是在房屋表里直接加一个 owner_id 字段。至于租户系统里我不做太重的合同管理只记录一个居住人信息这个设计思路是核心目标是让物业知道这套房子现在谁在住、怎么联系得上而不是做一套 ERP。第三个是物业缴费模块。这是整个系统里最容易写乱的部分。一笔物业费的状态流转是生成账单 → 未缴费 → 已缴费 →如果逾期生成滞纳金。我把费用类型分成了物业费、停车费、水费代收、垃圾清运费用一张表加费用类型字段来处理而不是每一种费用建一张表。缴费动作落地之后要回写房屋的状态比如说某套房连续欠费三个月系统会在业主信息列表里自动打上欠费标红标记。这里我用定时任务处理逾期状态变更每天早上跑一次而不是在查询接口里临时算逾期性能差别很大。第四个是报修工单模块。业主提交报修 → 物业派单 → 师傅接单 → 维修完成 → 业主评价。这个流程需要一个状态机来控制待派单、已派单、维修中、已完成、已评价、已取消。比较关键的是派单逻辑物业管理员的角色可以把工单指派给某个维修师傅师傅登录系统后只能看到自己的待办工单。我在工单表里设计了 assignee_id 字段查询时直接按这个字段过滤不需要额外的授权判断逻辑。第五个是车辆与通行管理模块。关联到房屋的车辆登记、访客车辆临时放行、车位信息管理。车辆进场出场这部分我在系统里只做到了登记和记录层面没有对接硬件的道闸。如果你要接真实的门禁设备预留了 plate_number 和 entry_time 两个字段后面做接口对接时把设备回调写入这两列就行。1.2 技术栈选型复盘SpringBoot2 Vue3 的组合逻辑这套技术栈不是我拍脑袋定的每层选择都有明确理由。SpringBoot2 在当前环境下依然是最稳妥的选择。版本我锁在 2.7.x而不是直接上 SpringBoot3核心原因是生态兼容性MyBatis-Plus 和大量企业级中间件对 SpringBoot3 的适配在早期并不完善而且 Java8 的开发者群体依然庞大基于 JDK8 的 SpringBoot2 项目拿下来就能跑不需要额外处理模块化路径和 Jakarta 命名空间变化。SpringBoot 2.7 虽然已经进入维护末期但对这类管理系统绰绰有余稳定性经过了太多年验证。前端选择 Vue3 而不是 Vue2一方面是因为组合式 API 在组织复杂业务逻辑时确实比 Options API 更清爽。社区管理后台的页面复杂度不低一个缴费记录页要同时处理搜索条件、表格数据、分页状态、弹窗表单、批量操作用 setup 函数把所有逻辑收敛在一起比到处散落 data/methods/computed 要好维护很多。另一方面Element Plus 已经足够成熟Vite 的冷启动速度对日常开发体验的提升也是实打实的。MyBatis-Plus 在这个项目里是胜负手。它和 Spring Data JPA 的核心区别在于JPA 把实体关系管理做到极致适合领域驱动设计但在 SQL 调优和多表关联查询时容易被自动生成的 SQL 坑到MyBatis-Plus 本质上还是 MyBatisSQL 写在自己手里同时又提供了单表 CRUD 的自动封装。社区管理系统的业务大量集中在单表操作上比如查询某栋楼下的所有房屋、按状态查工单、分页查缴费记录这些场景用 BaseMapper 内置方法基本覆盖了真正的复杂统计 SQL 我手动写在 XML 里质量可控。MySQL8.0 主要是为了 utf8mb4 字符集和新版窗口函数。社区系统的地址、业主姓名、备注信息里经常出现生僻字和表情符号utf8mb4 是刚需。窗口函数在统计报表场景里非常好用比如分析每栋楼的缴费率排名一条 ROW_NUMBER() 就能解决在 MySQL5.7 里写起来要痛苦得多。2. 后端工程搭建分层规范、统一响应与权限设计2.1 后端工程目录的划分思路很多朋友在搭建 SpringBoot 工程时喜欢把全部代码平铺在几个包下面短时间看着还行一旦业务模块变多就开始混乱。我在这套系统里采用了按技术层横向划分 按业务模块纵向分包的混合结构既保证了技术的统一性又让业务边界清晰。横向的技术层包名是 controller、service、mapper、entity、dto、config、common。纵向的业务模块包则在 controller 和 service 内部再次拆分子包比如 controller 下拆成 community、repair、payment、car、notice。这样做的好处是找某个功能的 Controller 只需要先进 controller 包再点具体业务模块不会出现几十个 Controller 文件堆在一起的局面。Mapper 层我坚持只放数据库操作业务逻辑全部下沉到 Service 层Controller 层只做参数接收、常量校验、响应封装不写任何 SQL 逻辑。这条红线守住了代码基本不会烂。配置文件的组织也容易被忽略。我没有把所有配置塞进一个 application.yml而是拆成了三个环境application-dev.yml本地开发数据库地址指向本机、application-prod.yml部署环境数据库地址指向服务器、application-common.yml通用配置比如 JWT 过期时间、文件上传大小。打包时通过 --spring.profiles.activeprod 指定环境避免每次换环境都去改 yml 里的数据库密码。2.2 统一响应体、全局异常与分页返回结构前后端分离项目里统一的响应格式是最基础也最容易出错的部分。我在项目里定义了一个泛型响应类 RT所有接口返回的都是这个结构。它有四个核心字段code 表示业务状态码200 成功500 系统错误401 未登录403 无权限message 是给前端展示的提示信息data 是实际数据timestamp 是时间戳。这样前端 Axios 拦截器里只需要判断 code 200 就正常处理数据其他情况统一弹提示不需要每个接口单独做错误处理。分页返回结构我单独定义了一个 PageResult 类包含总记录数 total、当前页数据列表 records、当前页码 current、每页大小 size。这个设计和 MyBatis-Plus 的 IPage 对象是解耦的Controller 层拿到 IPage 之后转换成 PageResult 返回。为什么要多做一层转换因为 MyBatis-Plus 的 Page 对象里带了搜索条件和额外属性直接序列化给前端会暴露太多无意义字段而且返回结构不够稳定一旦 MP 版本升级字段变了前端可能就解析报错了。全局异常处理我使用了 RestControllerAdvice 注解。业务异常通过自定义的 BizException 抛出比如该房屋已被业主绑定工单状态不允许取消统一到这里捕获后转换成标准的 R 响应状态码可以根据异常类型动态映射。还有一类容易忽略的异常是参数校验异常我在实体 DTO 上用了 javax.validation 注解比如 NotBlank、Email、Pattern校验失败抛出的 MethodArgumentNotValidException 也要在全局异常里接住否则返回默认的 400 错误结构前端拿到的是无法直接提示的原始错误对象。2.3 JWT 登录与接口鉴权的实现要点社区管理系统的用户角色分三类系统管理员超管、物业人员包括管理员和维修师傅、业主。业主登录后只能看到自己的房屋、缴费和报修物业人员可以看到自己负责范围内的业务数据超管则拥有一切权限。这里我用 JWT 方案实现无状态登录登录成功时签发一个 TokenToken 里在 payload 部分封装 userId、username、role 三个字段。出于安全考虑我在 JWT 配置里设置了两个关键参数过期时间 7200 秒两小时签名密钥足够复杂至少 32 位随机字符串防止被暴力破解。后端拦截器我实现了一个 JwtInterceptor继承 HandlerInterceptor在 preHandle 里解析 Token。校验通过后把 userId 存入 request 的 Attribute 中业务层从 request 里取当前操作用户而不是把用户信息写在方法的参数列表里传来传去。这个做法的好处是后续在任意 Service 方法里都能获取到当前登录人比如记录操作日志时直接调用一个静态方法就行。角色权限我用了一个简单的自定义注解 RequireRole标注在 Controller 方法上。拦截器解析完 JWT 之后检查当前用户角色是否满足注解中声明的角色集合。整套系统规模不大这种注解 方法级拦截方案比引入 Spring Security 全家桶要轻量得多学 Spring Security 的成本要比写这个拦截器高不少。等系统真的需要动态权限、细粒度数据权限的时候再迁移过去不迟。3. 数据库设计与 MyBatis-Plus 实战MySQL8.0 的正确打开方式3.1 核心表结构设计外键怎么取舍关于数据库表外键我的原则是业务系统里不使用物理外键全部通过逻辑关联维护。物理外键在数据插入时性能损耗明显而且社区管理系统后期如果有拆分数据库的需求物理外键会成为巨大阻碍。比如房屋表和业主表之间的关联我只在房屋表里保留 owner_id 字段作为逻辑外键通过定期校验和代码层面约束保证数据一致性效果完全够用。核心表的设计我列一张核心结构表来说明表名关键字段关联关系说明communityname, address, area, developer1对多building小区基础档案buildingcommunity_id, building_no, floor_count多对1community楼栋及层数信息roombuilding_id, unit_no, room_no, area, owner_id多对1building房屋核心档案ownerreal_name, mobile, id_card, status多对多roomroom_owner 表业主信息paymentroom_id, fee_type, amount, status, deadline多对1room物业缴费记录repairroom_id, order_no, description, status, assignee_id多对1room / user报修工单所有核心业务表都包含三个公共字段create_time、update_time、deleted。create_time 和 update_time 由 MyBatis-Plus 的自动填充功能在 insert 和 update 时自动写入deleted 字段配合逻辑删除功能实现数据安全删除——用户在前台删除一条缴费单时数据库实际上只执行了 UPDATE deleted1这样误删数据还能恢复系统审计时也能追溯。3.2 MyBatis-Plus 的自动填充、分页插件与条件构造器MyBatis-Plus 自动填充是在实体类的 createTime 字段上加 TableField(fill FieldFill.INSERT) 注解然后实现一个 MetaObjectHandler 处理器在 insertFill 方法里统一写入 LocalDateTime.now()。注意最好用 LocalDateTime 而不是 java.util.Date因为 MySQL8.0 驱动对 java.time 包的支持更好JSON 序列化时也能避免时区问题。分页插件配置我曾经漏掉过一次导致调用 selectPage 方法时返回的数据是全量而不是真正分页排查了很久。关键是要在 MybatisPlusConfig 里注入 MybatisPlusInterceptor并添加 PaginationInnerInterceptor指定数据库类型为 DbType.MYSQL。条件构造器 QueryWrapper 是 MyBatis-Plus 用得最多的 API。我不建议在 Service 层直接 new QueryWrapper 写代码因为条件完全散落在业务代码里后期 SQL 调优会非常难受。我通常在 Service 层调用一个私有方法构建查询条件返回 QueryWrapper 对象。比如查询缴费记录时动态拼接 roomId、feeType、status 和缴费日期区间核心写法如下private QueryWrapperPayment buildPaymentQuery(PaymentQueryDTO dto) { QueryWrapperPayment wrapper new QueryWrapper(); wrapper.eq(StringUtils.isNotBlank(dto.getRoomId()), room_id, dto.getRoomId()); wrapper.eq(dto.getFeeType() ! null, fee_type, dto.getFeeType()); wrapper.eq(StringUtils.isNotBlank(dto.getStatus()), status, dto.getStatus()); if (dto.getStartDate() ! null dto.getEndDate() ! null) { wrapper.between(deadline, dto.getStartDate(), dto.getEndDate()); } wrapper.orderByDesc(create_time); return wrapper; }注意 eq 方法的第一个条件参数必须是 boolean前端传来的查询参数为空时就不拼接这个条件这样才能实现真正的动态查询。还有就是每张表的逻辑删除字段名为 deleted 时MP 的查询会自动追加 deleted0 条件但如果你在 XML 里手写 SQL 或者用了自定义 SQL 片段这个自动过滤是失效的必须手动加上条件这是一个非常容易踩的坑。批量插入也值得提一下。如果缴费系统月结时需要给上千户业主批量生成账单逐条 insert 性能太差MP 提供了 saveBatch 方法。但实测时我发现默认的批量插入语句还是拆成了多条 insert性能和一条 insert 带多组 values 比差距明显。我的做法是在 XML 里手写 foreach 批量 insert 语句几千条数据的插入时间能从几十秒降到一两秒以内。有些版本 MP 的 saveBatch 也做了优化但自己验证一把才是最靠谱的。3.3 升级 MySQL8.0 之后的三个兼容性问题这套系统最初开发时我在本机用的是 MySQL5.7一切正常。切到 MySQL8.0 之后接连遇到三个问题这里单独列出来。第一个是认证插件问题。MySQL8.0 默认的认证插件是 caching_sha2_password而 MySQL5.7 时代常用的客户端连接工具和旧版本驱动只认 mysql_native_password。如果 SpringBoot 项目的驱动版本太老启动时就会报 Unable to load authentication plugin 错误。解决办法有两个一是把 mysql-connector-java 升级到 8.0.x 版本这是治根的方式二是临时把用户的认证插件改回 mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;。部署到 Linux 服务器时建议直接用新驱动不做兼容降级。第二个是JDBC URL 必须加时区参数。MySQL8.0 对时间类型的处理更严格连接字符串里如果不加 serverTimezoneAsia/Shanghai 和 useUnicodetruecharacterEncodingutf8项目启动时就会一直报数据库连接超时或者时间解析错误。经验值是把完整的参数串放在配置文件里jdbc:mysql://localhost:3306/community?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue。第三个是utf8mb4 排序规则的变化。MySQL8.0 的默认排序规则是 utf8mb4_0900_ai_ci这个排序规则在 LIKE 查询和 UNIQUE 索引上的一些行为与老版本的 utf8mb4_general_ci 有细微差异。如果你是从 5.7 导出的数据库导入 8.0 之后部分表的索引可能变成无效索引。建议建库时直接指定 utf8mb4 的通用排序规则建库语句我用的是CREATE DATABASE community CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci。4. Vue3 前端工程从登录页到业务页面的完整链路4.1 Vite 工程初始化与项目结构前端部分我用 Vite 而不是 Vue CLI 来搭建理由很直接Vite 的开发服务器启动速度在项目变大之后优势非常明显而且 Vite 5 对 Vue3 的支持是官方一等公民配置要比 Vue CLI 的 webpack 配置简洁太多。项目初始化命令是 npm create vitelatest community-web -- --template vue然后手动安装核心依赖vue-router、pinia、element-plus、axios、sass。Element Plus 我采用全量引入而不是按需自动导入原因是在后台管理系统这种内部项目里全量引入的打包体积虽然大了几百 KB但省去了插件配置的麻烦开发体验更顺畅。如果以后要优化首屏加载再改成按需自动导入也不迟。目录结构我按照前端工程化的标准组织src/api 按业务模块放接口请求文件src/views 放页面级组件src/components 放公共组件src/router 放路由配置src/store 放 Pinia 状态管理。还有一个容易忽略的是 src/utils 里放公共工具方法比如日期格式化、金额保留两位小数、字典映射函数。社区管理系统的很多状态字段是数字字典比如工单状态 0 是待派单 1 是已派单我写了一个 getDictLabel 方法统一处理避免在页面上到处写 if-else。4.2 登录态管理路由守卫、Pinia 与 Token前端登录流程是整个系统的门口这块设计不好会出现很恶心的体验问题比如刷新后白屏、直接通过网址访问未授权页面。我的做法是登录成功后后端返回 Token 和用户基本信息前端用 Pinia 定义一个 user storestate 里放 token、userInfo、role。Pinia 的持久化我直接写死在 store 的初始化逻辑里从 localStorage 读取 Token 和用户信息有就直接放入 state没有就为空。这里不建议把全部业务缓存都交给 Pinia 的持久化插件因为用户信息在权限变动时容易留下脏数据只要持久化 token 和 username 就够了其余的每次刷新后重新拉取。路由守卫我同时用了全局前置守卫和动态 meta 字段。router.beforeEach 里做三件事判断是否存在 Token不存在则重定向到登录页存在但用户信息为空时调用接口拉取当前用户信息最后判断当前路由的 meta.roles 数组是否包含用户角色不包含就跳转到 403 页面。这里要特别提示的是路由守卫的跳转逻辑一定要避免死循环比如重定向到 /login 时如果 /login 页面自身也在守卫里判断 token就会陷入无限跳转。我的处理是守卫的最开始先判断 to.path 是否为 /login如果是直接放行。4.3 业务页面里的三种高频模式社区管理系统的后台页面看起来多但拆开来看基本就是三种模式列表 分页 搜索、弹窗 表单、状态流转操作。把这三个模式写好其他页面都是套模板。列表页的核心是这个套路页面挂载时调用查询接口关键词变化时重置页码为 1 再重新查询分页组件的 current-change 事件触发翻页。搜索区我统一用 el-form 的内联模式查询按钮和重置按钮并排重置方法里把搜索表单所有字段清空然后同样重置页码再查一次。弹窗表单我写了一个通用的 useFormDialog 组合式函数里面封装了打开弹窗、回显数据、提交前校验、调用新增或更新接口这几个动作。新增和编辑共用一个弹窗组件区别只在回显时调一次详情接口并给表单赋值。这一步有个细节编辑回显时别直接拿列表行数据赋值因为列表返回的字段往往和表单字段不是一一对应的比如时间字段在列表里是字符串在表单里需要的是 Date 对象直接赋值会出现校验失灵。状态流转操作比如派单、完成工单、退单我设计成在表格操作列里放下拉按钮组件。根据当前行状态动态显示可用操作禁用不可用的动作。点击操作后先弹出确认框再调接口。这里积累了血泪教训每个操作按钮必须绑定 loading 状态防止用户手快重复提交我封装了一个 useActionLoading 方法按 actionKey 来标记哪个操作正在进行。4.4 Axios 请求封装与接口联调细节Axios 封装的核心是拦截器我设置了三层逻辑。请求拦截器里从 Pinia 中获取 token 并注入 Authorization 头格式是 Bearer 。前端如果检测到路由正处在登录页就不注入。响应拦截器里统一判断后端返回的 code200 直接 resolve 返回 data 部分401 时清除本地 token 并跳转登录页其他错误码用 Element Plus 的 ElMessage 展示后端返回的 message 字段。接口文件组织是我比较看重的点。每个业务模块一个 api 文件例如 src/api/payment.js 里只放缴费相关的请求函数统一导出。函数命名遵循方法verb 资源名称的规则比如 getPaymentList、createPayment、updatePayment、deletePayment这样维护的时候搜索非常方便。和前端联调初期最容易出现的问题是后端返回的字段命名风格不统一有的字段是 createTime有的用的下划线 create_time。在这套项目里我们统一强制后端 DTO 使用驼峰命名返回JSON 里就是驼峰前端直接消费不用做任何转换。接口联调阶段我还发现一个问题SpringBoot 默认返回的时间格式是 UTC 格式的长字符串前端展示时非常难看。我在后端 yml 里配置了全局的 Jackson 时间序列化格式 spring.jackson.date-formatyyyy-MM-dd HH:mm:ss同时前端在 axios 请求时也设置了 paramsSerializer确保时间类型参数能正确传递到后端。如果前后端对时间格式没有统一约定排查起来会非常头疼。5. 部署与复盘让系统真正跑起来的全过程5.1 环境准备Linux 安装 MySQL8.0 的实操记录这套系统最终是部署在一台 2 核 4G 内存的 Linux 服务器上的用的 CentOS 8 系统。数据库我直接选择了 MySQL8.0安装时不推荐用官方 MySQL Yum Repository 的方式网络波动会导致安装中断。稳妥做法是直接用腾讯云环境或本地 rpm 包安装实际操作步骤是先检查系统是否装了旧版本rpm -qa | grep mysql。然后下载 MySQL8.0 的 RPM 包安装顺序必须先安装 common、libs、client最后装 server顺序反了会提示依赖错误。安装完成后执行 systemctl start mysqld 启动服务用 grep temporary password /var/log/mysqld.log 找到初始临时密码登录之后必须先执行 ALTER USER 修改密码因为 MySQL8.0 强制要求登录后修改临时密码才能执行任何操作。修改完密码后我给社区系统创建了独立数据库账号没有直接用 rootCREATE USER community% IDENTIFIED BY 这里写强密码;。然后授权 GRANT ALL PRIVILEGES ON community.* TO community%;。使用独立账号的好处是后续上线后会部署多个系统每个系统账号只拥有自己数据库的权限安全级别高很多。5.2 前后端部署流程后端部署非常简单Maven 打包命令我用的是 mvn clean package -Dmaven.test.skiptrue因为测试类里依赖了数据库连接在构建机上执行测试会浪费时间甚至报错。打出来的 jar 包用 nohup java -jar community-server.jar --spring.profiles.activeprod 启动注意这里必须要让日志输出重定向到文件nohup 命令的日志重定向到 nohup.out 不够规范我写成 java -jar xx.jar /usr/local/community/logs/app.log 21 方便之后用 tail 查看实时日志。前端部署的核心是 Nginx 静态资源服务。Vite 打包后生成 dist 目录我把 dist 目录放到 /usr/local/nginx/html/community 下。Nginx 配置里最关键的是 location /api/ 的代理转发把所有 /api 开头的请求代理到后端服务的地址同时做了 WebSocket 支持。location /api/ { proxy_pass http://127.0.0.1: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_pass http://127.0.0.1:8080/ 末尾的斜杠非常关键如果有斜杠代理时会把 /api 前缀去掉比如 /api/payment/list 会转成 /payment/list 发给后端如果没有斜杠原路径会整体传给后端此时后端的 Controller 里就必须用 /api 作为前缀。两种写法必须和前后端约定保持一致否则接口一定 404。5.3 上线前需要检查的清单与常见坑上线前我养成了一个固定的检查清单特意分享出来因为踩坑踩多了自然就总结出了规律第一检查 SpringBoot 配置文件里的 MySQL 地址是否改成了服务器 IP数据库账号密码是否和服务器上创建的一致。我遇到过朋友把 dev 环境配置直接打成 prod 包上线后数据库连到本地导致启动失败。第二检查防火墙和服务器安全组是否放行了 8080 和 3306 端口。很多情况下后端 jar 包明明启动了接口却一直超时最后查到是安全组没开端口这个坑看起来低级但排查起来相当隐蔽。第三检查 JWT 密钥是否修改。源码里自带了一套默认密钥上线前不改就等于门锁形同虚设。我习惯让运维在环境变量里注入 JWT_SECRETSpringBoot 配置里通过 ${JWT_SECRET} 读取既保证不泄露到代码仓库又方便不同环境使用不同密钥。第四检查定时任务是否启动。缴费系统里逾期账单的状态变更依赖定时任务上线后要确认日志里定时任务有正常执行记录我曾经遇到过一台服务器时区没设对定时任务在凌晨 4 点才跑导致白天展示的账单状态一直是昨天的。第五检查前端页面是否启用了生产模式。Vite 打包时如果用 npm run dev 启动而不是 build网站访问性能会差很多而且浏览器控制台里全是开发模式的警告信息。第六检查数据库的初始数据是否正确导入。系统的初始小区、初始楼栋、初始管理员账号都是通过 SQL 脚本导入的上线时脚本执行顺序错了会导致关联数据缺失比如房屋表已经有了数据但楼栋表还没有数据完整性就挂了。部署完成之后一定要做的自检动作是先通过 curl 测试后端健康检查接口确认返回 200再验证前端登录页是否能正常拉取验证码和提交登录请求最后模拟一遍核心业务路径——新建小区、添加楼栋、创建房屋、绑定业主、生成缴费单、提交报修单、完成工单。这条主链路走通系统上线基本就成了。写到这里我把这套智慧社区管理系统从业务设计、技术选型、核心模块、数据库设计一直到前端实现、后端实现和部署上线的完整链路都过了一遍。如果你正在学习 SpringBoot 和 Vue3最大的建议还是别只盯着教程看真正用这套系统把代码通读、跑通然后自己动手改两个模块比如给缴费模块加一个导出 Excel 功能、给报修模块加一个通知推送这两个实操做下来你对这套技术栈的熟悉程度会发生质的飞跃。这套系统的源码和详细文档我都已经整理好放在仓库里了有需要学习交流的可以直接对照本文里的实现思路去读代码。
返回列表