ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue隔离管理系统实战:从表设计到部署

SpringBoot+Vue隔离管理系统实战:从表设计到部署 1. 这个系统要解决的真实问题隔离管理为什么需要一套专门系统先说结论隔离管理这件事流程本身不难难的是信息不落地。我在做这类管理系统之前也想过不就是几个表单嘛Excel都能搞定。但真去梳理一遍隔离业务流程就会发现散落在微信、电话、纸质登记表里的信息根本没法追溯今天上报的体温记录在哪里某栋楼的隔离人员还差几次核酸检测哪个隔离点已经满员了权限怎么控制这些问题一旦叠加起来Excel和口头沟通就会全面崩溃。疫情隔离管理系统本质上是把隔离人员信息登记、健康监测记录、隔离任务分配、状态变更审批、数据统计汇总这几件事从线下搬到线上让管理员、医护人员、被隔离人员三个角色都能在一个系统里完成各自的操作。技术选型上SpringBoot提供后端接口能力Vue负责前端交互MyBatis承担数据库操作MySQL做数据存储——这套组合在中小型管理系统中非常成熟社区资料多、上手快、排错容易。如果你正准备做一个类似的业务管理系统或者正在学习SpringBoot和Vue的整合开发这篇文章会从需求分析、表结构设计、接口实现、前端页面到部署打包完整走一遍这个系统的实现路径。文章里所有的模块拆分思路和数据表设计逻辑换成别的业务场景比如访客登记系统、宿舍管理系统、物资领用系统同样可以复用。2. 后端核心模块拆解健康上报、隔离任务分配、权限控制怎么落地一个隔离管理系统的后端绕不开三个核心模块健康上报、隔离任务分配、用户权限控制。这三个模块覆盖了系统的主线业务也决定了系统的复杂度和可用性。2.1 健康上报模块防重复、防篡改、可追溯健康上报是使用频率最高的模块。隔离人员每天需要上报体温、是否有咳嗽、乏力等症状必要时还要上传核酸检测结果。这个模块看起来就是一个简单的insert操作但实际落地时有两个细节必须处理。第一个是重复上报问题。用户一天可能误操作提交两次或者故意重复提交如果不做校验数据库里就会出现同一天、同一个人的多条上报记录后续统计今日上报人数时就会出错。我的做法是在Service层做前置校验查询当天是否已存在该用户的上报记录存在则直接返回提示不执行insert。有并发场景的话可以在数据库层加唯一索引字段组合是user_id和report_date双保险。第二个是修改权限问题。健康上报数据属于敏感数据一旦提交就不应该允许用户随意修改。这里我用状态字段来区分提交后状态为已提交管理员审核后变为已审核审核过的记录在前端直接置灰不接受编辑请求。后端接口在update操作前校验状态防止绕过前端直接调接口篡改数据。核心上报接口大致是这样PostMapping(/report/submit) PreAuthorize(hasRole(USER)) public ResultString submitReport(RequestBody Valid HealthReportDTO dto) { // 1. 判断今天是否已上报 int count healthReportMapper.countByUserIdAndDate( SecurityUtils.getUserId(), LocalDate.now()); if (count 0) { return Result.error(今日已上报无需重复提交); } // 2. 组装实体补充审计字段 HealthReport report new HealthReport(); BeanUtils.copyProperties(dto, report); report.setUserId(SecurityUtils.getUserId()); report.setReportDate(LocalDate.now()); report.setStatus(PENDING); report.setCreateTime(LocalDateTime.now()); // 3. 写入数据库 healthReportMapper.insert(report); return Result.success(上报成功); }这里用PreAuthorize做接口级别的权限控制避免未登录用户直接调用。审计字段create_time、create_by属于标配任何管理系统都必须带上不然出了问题连是谁在哪天提交的都不知道。2.2 隔离任务分配与状态流转用状态机思维设计业务流程隔离任务指的是隔离人员从登记入驻到解除隔离的完整周期包括分配房间、安排核酸检测、每日健康监测、到期解除等步骤。这个模块最核心的设计是状态流转。一开始偷懒的人会直接在实体类里放一个status字段0表示隔离中1表示已解除。这样做小程序没问题但业务稍微一复杂就会失控。比如隔离中途需要转院怎么办隔离期满但核酸结果没出怎么办这些情况根本不是两个状态能表达的。我用的是状态机思路定义一组清晰的状态和允许的流转路径状态编码状态名称允许流转到PENDING待入住ASSIGNED, CANCELLEDASSIGNED已分配房间IN_PROGRESS, CANCELLEDIN_PROGRESS隔离中PENDING_RELEASE, EXTENDEDEXTENDED已延期PENDING_RELEASE, RELEASEDPENDING_RELEASE待解除审核RELEASED, EXTENDEDRELEASED已解除无状态流转的代码我建议单独抽一个IsolationStatusHandler类里面放一个Mapkey是当前状态value是允许流转到的目标状态集合。每次执行状态变更时先查Map校验不合法直接抛业务异常。private static final MapString, SetString TRANSITIONS new HashMap(); static { TRANSITIONS.put(PENDING, new HashSet(Arrays.asList(ASSIGNED, CANCELLED))); TRANSITIONS.put(ASSIGNED, new HashSet(Arrays.asList(IN_PROGRESS, CANCELLED))); TRANSITIONS.put(IN_PROGRESS, new HashSet(Arrays.asList(PENDING_RELEASE, EXTENDED))); TRANSITIONS.put(EXTENDED, new HashSet(Arrays.asList(PENDING_RELEASE, RELEASED))); TRANSITIONS.put(PENDING_RELEASE, new HashSet(Arrays.asList(RELEASED, EXTENDED))); } public boolean canTransit(String current, String target) { SetString allowed TRANSITIONS.get(current); return allowed ! null allowed.contains(target); }状态机的好处在于一是业务规则集中在一个地方不会散落在各个Service里二是非法操作在入口就被拦截不会污染数据三是后续接审批流或者操作日志时可以很方便地在状态变更前后做钩子。2.3 基于RBAC的权限控制三种角色各管各的隔离管理系统至少要支持三种角色系统管理员、医护人员、被隔离人员。权限设计直接用Spring Security加JWT的方案配合PreAuthorize注解做方法级别的控制。角色权限划分大概是这样的管理员用户管理、隔离点管理、房间分配、数据导出、系统配置医护人员查看隔离人员列表、登记健康记录、审核上报数据、处理解除申请被隔离人员每日健康上报、查看自己的隔离信息、提交解除申请实现上我用了一张sys_role表、一张sys_user_role关联表再加一张sys_permission表。用户登录时根据JWT中的角色标识去加载对应的权限集合Vue前端拿到权限列表后再决定渲染哪些菜单和按钮。后端接口层面用PreAuthorize拦截确保即使有人绕过前端直接请求接口也拿不到越权数据。有一个实际开发中容易被忽略的点通用查询接口的分页参数也要做数据隔离。比如医护人员查看隔离人员列表只能看到自己负责的隔离点不能全表查询。MyBatis的Mapper里加一个Param(deptId)参数SQL里强制拼接WHERE dept_id #{deptId}这一条要写死在Mapper XML里不能依赖业务代码自觉。3. 数据库模型设计几张核心表的关系和字段细节这个系统的数据表不算多核心大概六到八张。我最想展开说的是其中三张隔离人员主表、健康上报表、隔离任务流转表。这三张表设计好了后面写代码能省一半力气。3.1 隔离人员主表冗余设计要克制状态字段要留够CREATE TABLE isolation_person ( id bigint(20) NOT NULL AUTO_INCREMENT, name varchar(32) NOT NULL COMMENT 姓名, id_card varchar(18) NOT NULL COMMENT 身份证号, phone varchar(20) DEFAULT NULL COMMENT 联系电话, address varchar(128) DEFAULT NULL COMMENT 居住地址, isolation_point_id bigint(20) DEFAULT NULL COMMENT 隔离点ID, room_no varchar(16) DEFAULT NULL COMMENT 房间号, start_date date DEFAULT NULL COMMENT 隔离开始日期, expected_end_date date DEFAULT NULL COMMENT 预计解除日期, actual_end_date date DEFAULT NULL COMMENT 实际解除日期, status varchar(20) NOT NULL DEFAULT PENDING COMMENT 状态, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, create_by bigint(20) DEFAULT NULL, update_by bigint(20) DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_id_card (id_card), KEY idx_status (status), KEY idx_point_id (isolation_point_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT隔离人员信息表;这个表设计有几个点可以说道说道。id_card设唯一索引防止同一个人重复登记。status字段用varchar而不是int可读性好一些排查问题时一眼能看懂状态含义代价是多占几个字节但管理系统的数据量根本不在乎这点空间。start_date、expected_end_date、actual_end_date三个日期都单独存避免算隔离天数时还要从状态日志表里倒推时间节点。房间号字段我选择了直接冗余到人员表而不是单独建一张房间分配表。原因很简单隔离管理场景下一个房间在同一时间只会分配给一个人不存在复杂的多人共用或跨时段预约逻辑直接挂在人员表上最简单查询列表时少一次join。3.2 健康上报表唯一索引防重复症状字段用JSON还是用多列健康上报表的设计重点是字段的灵活性。体温是必填项这是硬性指标。但是否有咳嗽是否有乏力是否接触过疑似病例这类问题不同的隔离点可能问法不一样有的还要传核酸结果图片。我的设计是必填的数值指标用独立字段可选的信息用JSON字符串存到extra字段里。CREATE TABLE health_report ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL COMMENT 上报人ID, report_date date NOT NULL COMMENT 上报日期, temperature decimal(4,2) NOT NULL COMMENT 体温, symptom_type varchar(255) DEFAULT NULL COMMENT 症状类型多个逗号分隔, nucleic_acid_result varchar(10) DEFAULT NULL COMMENT 核酸结果NEGATIVE/POSITIVE/PENDING, extra_json text COMMENT 扩展信息, status varchar(20) DEFAULT PENDING COMMENT PENDING/APPROVED/REJECTED, audit_user_id bigint(20) DEFAULT NULL COMMENT 审核人ID, audit_time datetime DEFAULT NULL COMMENT 审核时间, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_user_date (user_id, report_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT每日健康上报记录;symptom_type用逗号分隔的字符串而不是单独建关联表是权衡之后的选择。症状种类有限十几个枚举值封顶逗号分隔完全够用还能避免频繁join。后面如果想统计有多少人报告了咳嗽一个FIND_IN_SET(COUGH, symptom_type)就能查出来。extra_json是给未来扩展用的比如隔离点临时要求上报是否出现腹泻不用改表结构直接往JSON里塞字段就行。3.3 审计字段与逻辑删除管理系统不能马虎的底线管理系统的数据一旦写错影响的是真实的人所以审计字段必须齐全。我在所有业务表上都加了create_time、update_time、create_by、update_by四个字段命名统一后续写通用查询和代码生成器的时候非常省事。逻辑删除这件事我的经验是管理系统的核心业务表比如人员表、上报表坚决做逻辑删除日志型数据表比如状态变更记录表直接物理删除也不心疼。人员表如果物理删了历史上报记录就会变成孤儿数据统计报表时对不上号到时候找人哭都来不及。MyBatis层面的逻辑删除不需要每个Mapper手写update语句用MyBatis-Plus的TableLogic注解就能全局处理普通delete接口调用时自动变成update查询时自动拼接deleted0条件。这个能力是MyBatis-Plus白送的但很多人不知道还在手写逻辑删除SQL浪费功夫。4. 前端Vue层的实现重点动态路由、状态可视化、表单交互前端这部分Vue 3加Element Plus是当前比较顺手的组合。我挑三个自己认为最有信息量的模块来讲动态路由控制、隔离状态的时间轴展示、每日上报的表单交互。4.1 动态菜单和路由守卫不同角色登录后看到的不是同一个系统隔离管理系统的用户角色差异非常大医护人员进入系统要立刻看到任务列表被隔离人员只想看到自己的上报入口和状态进度。如果所有人登录后看到的是同一个菜单系统就会显得很笨。实现思路是用户登录成功后后端返回该用户的角色编码和权限标识列表前端把这个列表存到Pinia/Vuex中然后根据权限标识动态生成路由表。// 路由守卫中的动态路由注册逻辑 router.beforeEach((to, from, next) { const store useUserStore(); if (!store.token) { if (to.path /login) { next(); } else { next(/login); } return; } // 已登录但未注册动态路由时先根据权限生成路由 if (!store.routesLoaded) { const menus store.permissionList; // 后端返回的权限标识 const dynamicRoutes generateRoutes(menus); dynamicRoutes.forEach(route router.addRoute(route)); store.routesLoaded true; next({ ...to, replace: true }); // 重新进入目标路由确保路由已注册 } else { next(); } });generateRoutes函数里面做的事情很简单维护一份前端所有的页面路由表每一项标记需要的权限标识遍历权限列表筛选出当前用户能访问的路由返回给addRoute注册。菜单的渲染同样基于这份列表这样就保证了后端接口权限和前端页面权限的一致性。4.2 隔离状态的时间轴展示让隔离人员一眼看明白我在哪个阶段隔离人员最关心的三个问题我现在是什么状态还有几天解除下一步该做什么这些信息如果只用一行状态文字表达用户很难形成直观印象。前端我用了时间轴组件来展示整个隔离流程。时间轴上的节点包括登记入驻、分配房间、每日健康上报、核酸检测、解除审核、完成隔离。每个节点根据后端返回的状态码显示为已完成、进行中、待开始三种样式。后端接口返回的数据结构大概是这样{ currentStatus: IN_PROGRESS, nodes: [ { name: 登记入驻, status: DONE, time: 2025-03-01 08:30 }, { name: 分配房间, status: DONE, time: 2025-03-01 09:00 }, { name: 健康上报, status: DOING, time: null }, { name: 核酸检测, status: TODO, time: null }, { name: 解除隔离, status: TODO, time: null } ] }前端拿到之后直接映射节点颜色和文案逻辑清晰后端也不需要在接口里拼接太多展示逻辑。这种模式在隔离管理场景之外比如快递物流跟踪、工单流程跟踪都能直接复用。4.3 每日上报表单校验规则和防重复提交的体验细节健康上报表单在功能上就是个普通表单但使用频率高、场景单一所以体验细节很关键。第一个细节是默认值的处理体温字段默认显示36.5℃用户只需要在异常时修改减少操作步骤。第二个细节是症状多选用Element Plus的checkbox组选中项直接拼成逗号分隔的字符串提交。第三个细节是防重复提交提交按钮点击后立刻置灰同时后端再兜底校验一次做到双重保险。el-form refreportFormRef :modelreportForm :rulesrules label-width90px el-form-item label今日体温 proptemperature el-input-number v-modelreportForm.temperature :precision2 :min35 :max42 / /el-form-item el-form-item label症状情况 el-checkbox-group v-modelreportForm.symptomList el-checkbox label咳嗽 / el-checkbox label乏力 / el-checkbox label咽痛 / el-checkbox label无异常 / /el-checkbox-group /el-form-item el-form-item el-button typeprimary :loadingsubmitting clickhandleSubmit {{ todayReported ? 今日已上报 : 提交上报 }} /el-button /el-form-item /el-form还有一个容易被忽略的体验点用户第一次上报成功后再次进入页面时应该看到的是今日已上报的状态而不是再次弹出表单。这个我用一个todayReported布尔值控制进入页面时先调接口查询当天上报记录存在就直接渲染一个结果卡片替换表单区域操作路径非常短。表单提交成功后不要简单弹个提交成功就完事直接跳到健康记录列表页或者展示一个详情页用户能直观看到自己刚才提交的数据信任感会好很多。5. 前后端联调、打包部署的实操记录前后端分离项目的联调和部署踩坑是必然的。我把最容易出问题的几个环节单独拉出来每个都是实际遇到并且解决过的。5.1 跨域问题开发环境下的代理配置和生产环境的Nginx转发开发环境下前端跑在8080端口后端跑在8081端口直接请求一定会遇到跨域。我选的方式是配置Vue脚手架自带的代理而不是在后端写CrossOrigin。原因很简单生产环境的请求路径和后端是同一个域名根本不存在跨域开发环境用代理模拟同源和后端真实部署环境一致避免到了生产才发现问题。// vite.config.js export default defineConfig({ server: { port: 8080, proxy: { /api: { target: http://localhost:8081, changeOrigin: true, // 后端接口没有/api前缀这里做一下重写 rewrite: (path) path.replace(/^\/api/, ) } } } });后端接口统一以/api开头方便前端代理规则统一匹配。生产环境上Nginx配置一个location /api的转发块指向后端服务就行整个链路的请求路径非常一致排查问题时很省力。5.2 Vue打包放进SpringBoot的静态资源处理这个系统的部署方式我选择了直接把前端打包产物放到SpringBoot的static目录下一个jar包解决所有问题。好处是部署简单不用单独维护前端服务坏处是第一次配置容易踩坑。Vue默认的打包路径是/放到SpringBoot后需要通过http://ip:8081/index.html访问路由跳转的是/login刷新页面时SpringBoot会把/login当成后端路径去匹配得到404。解决办法是在后端加一个转发配置非/api开头的请求都转发到index.htmlConfiguration public class WebConfig implements WebMvcConfigurer { Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController(/{path:[^\\.]*}).setViewName(forward:/index.html); } }这个配置有个副作用前端引用的静态资源如果是/assets/js/xxx.js这种路径也会被这个规则拦走。所以构建前端时要把base路径改成相对路径或者./这样资源加载变成./assets/js/xxx.js就不会命中断言转发规则了。构建命令我通常是这样配的npm run build:prod # 产物输出到 dist 目录 # 把 dist 目录下的文件全部拷贝到 SpringBoot 的 src/main/resources/static 下拷贝操作我用的是Maven的maven-resources-plugin插件来做这样打包时前端产物会被自动复制到target/classes/static下面不需要手动拷贝每次部署执行一条mvn clean package就够了。5.3 环境配置细节MySQL时区、JVM参数、端口规划部署时这几个配置细节不处理白天还好晚上一到整点查询就出错。MySQL的时区问题是最经典的。连接串里必须显式指定serverTimezone否则会报The server time zone value Öйú±ê׼ʱ¼ä的乱码错误。用Asia/Shanghai而不是UTC避免日期字段差8小时的诡异问题。spring.datasource.urljdbc:mysql://127.0.0.1:3306/isolation_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueJVM参数也要留足内存。SpringBoot默认启动参数比较保守管理系统虽然数据量不算大但加上前端静态资源转发堆内存给个512M起步比较稳妥java -Xms512m -Xmx1024m -jar isolation-system.jar --server.port8081端口规划这块我习惯是8081跑后端服务8080留给前端开发服务器3306是MySQL。Nginx监听80统一入口根据路径分发/api走后端其余走前端静态文件。这样整个环境的访问路径足够清晰不管谁接手都能快速上手排查。6. 数据库连接池、事务边界和MyBatis映射里容易被忽略的坑最后一个部分我想分享几个在实现过程中反复踩过、最后总结出经验的高频问题。这几个问题单独看都不大但组合在一起会严重影响系统的稳定性和开发效率。6.1 事务边界健康上报和状态变更必须放在同一个事务里健康上报这个操作涉及的动作不只是insert一条上报记录还包括更新隔离人员表的last_report_date字段。如果这两个操作不在同一个事务里insert成功了但更新失败就会出现上报记录存在但用户下次再来上报时查不到的诡异问题。我用Transactional注解把整个Service方法包起来同时注意事务粒度。管理系统的业务方法一般来说直接加在Service方法上就好不需要细到把事务拆到多个方法里。但要注意Transactional默认只在抛出RuntimeException时才回滚如果手写了try-catch吞掉异常事务就不会回滚。所以Service内部不要捕异常让事务管理器统一处理。6.2 MyBatis的resultMap和驼峰映射问题MyBatis映射的坑非常隐蔽。数据库字段是下划线命名create_timeJava实体是驼峰命名createTime老手都知道要开启驼峰映射mybatis.configuration.map-underscore-to-camel-casetrue但有一个场景是设置了这个也救不了的多表联查返回DTO时如果两个表都有create_time字段resultMap里的映射会冲突。比如隔离人员表和房间表关联查询列名都是create_timeMyBatis映射后得到的值可能来自后者或者干脆为null。我在这个项目里的处理方案是SQL里显式给字段起别名保证返回的列名唯一SELECT p.id AS person_id, p.name AS person_name, p.status AS person_status, r.room_no AS room_no, r.create_time AS room_create_time FROM isolation_person p LEFT JOIN isolation_room r ON p.room_id r.id然后resultMap里写清楚每个字段对应的列名不依赖自动映射。这个习惯养成之后再复杂的联查也不会出现字段值错乱而且SQL一眼就能看出哪些列来自哪张表。6.3 分页查询的总数统计count查询不能带上排序和联查的大字段列表分页在管理系统里是标配。很多人在写Mapper时分页插件自动生成的count语句会带上原SQL中的LEFT JOIN但有些join其实只是为了查一个展示字段比如人员列表联查隔离点名称。这样count效率极差。我的做法是把List查询和count查询拆成两个SQL。List查询保留left join拿展示字段count查询去掉join只查主表select idpagePersonList resultTypePersonVO SELECT p.id, p.name, p.status, po.point_name FROM isolation_person p LEFT JOIN isolation_point po ON p.isolation_point_id po.id WHERE p.deleted 0 if testkeyword ! null and keyword ! AND (p.name LIKE CONCAT(%, #{keyword}, %) OR p.id_card LIKE CONCAT(%, #{keyword}, %)) /if ORDER BY p.create_time DESC LIMIT #{offset}, #{pageSize} /select select idcountPersonList resultTypelong SELECT COUNT(*) FROM isolation_person p WHERE p.deleted 0 if testkeyword ! null and keyword ! AND (p.name LIKE CONCAT(%, #{keyword}, %) OR p.id_card LIKE CONCAT(%, #{keyword}, %)) /if /select这样做的收益在大数据量场景下非常明显。管理系统的数据量发展到几万条时count查询少了join快的不止一点。就算在分页插件里配置了optimize-count也不如直接从源头分离来得干净。6.4 时间字段的时区与日期计算处理隔离管理的核心业务之一就是日期计算判断隔离天数、判断是否到期。系统里所有日期时间字段统一使用LocalDateTime前端传递使用yyyy-MM-dd HH:mm:ss格式字符串后端用JsonFormat注解统一转换JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private LocalDateTime createTime;涉及今天是否已上报这类判断时不要在前端用JS算前端时钟可能不准用户也可能改系统时间。必须走后端接口以服务器时间为准LocalDate today LocalDate.now();隔离到期判断的逻辑是// 隔离开始日期 隔离天数 今天说明隔离期已满 boolean expired startDate.plusDays(isolateDays).isBefore(LocalDate.now());LocalDate自带的plusDays方法天然处理了跨月、跨年、闰年的情况不需要自己写日期加减的算法这部分用JDK时间API比用第三方工具类更可靠、语义更清晰。我在实际开发中还遇到过一次坑就是服务器时间不是东八区导致每天0点跑定时任务把今日待上报人员统计到了前一天。排查了一下午最后发现是服务器的/etc/localtime没配好date命令显示的UTC时间。Linux服务器上务必把时区调对这个属于环境问题不是代码问题但排查思路值得留意。7. 这个小系统做完之后的几点体会疫情期间我身边有亲戚朋友真的经历过集中隔离也体验过一些粗糙的信息登记方式——每天在微信群里接龙报体温管理员一张张截图保存14天下来信息乱成一锅粥。所以我做这个项目的时候对信息真正落地这件事感受特别深。一套合格的隔离管理系统代码只是载体核心价值在于把规则变成系统强制逻辑该上报的必须报该审核的必须审该解除的自动提醒数据全程留痕。所有设计从状态机到权限控制到审计字段都在围绕减少出错、保证追溯这八个字。如果你正在照着类似的业务逻辑做自己的管理系统我的建议是先把状态流转图画透把表结构设计想清楚再动手写代码。表结构稳了后面至少少改八成需求。千万别一上来就先写接口需求还没理清就码代码后面返工的成本够你喝一壶的。最后再多说一句部署相关的事这套系统一顿操作下来我强烈建议把前端做成静态资源扔进SpringBoot里一个jar包一把梭。别看网上都在说前后端分离部署更规范对于隔离管理系统这种业务体量单体部署省下的运维成本远高于那点理论上的架构优势。遇到排查问题的时候你只需要看一个进程的日志心不累。
返回列表