ARTICLE DETAIL

资讯详情

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

SSM+Flask高校疫情防控系统:架构设计、功能实现与部署实战

SSM+Flask高校疫情防控系统:架构设计、功能实现与部署实战 这两年高校信息化和毕业设计里有一类需求几乎成了“标配”——疫情期间高校防控系统。只要你有同学在高校信息中心、后勤或学工口工作大概率听他们吐槽过每日健康上报靠微信接龙出入校审批靠纸质单隔离信息靠Excel表辅导员天天晚上催学生打卡。所以这类“基于JavaSSMFlask的疫情期间高校防控系统”一出来很多人第一反应是“又是个毕设项目”但仔细拆完会发现它其实是把校园安全、健康监测、远程教学入口、高校管理这些真实业务全部揉进了一套系统里。我前后带过几个团队做过同类项目也帮不少同学调试过这种经典 JavaPython 混搭的项目包。今天这篇就把这个课题从需求、表设计、接口实现到本地跑通、服务器部署再到防坑指南完整梳理一遍。如果你想学一套SSM开发经验或者正在为选型纠结这篇文章都能给到一些纯实操层面的参考。1. 项目拆解先搞清楚这套系统到底要解决什么问题1.1 高校防疫场景的真实痛点很多同学拿到题目就急着建表写接口这是大忌。高校防控系统跟普通后台管理系统差别很大核心不是“能增删改查”而是要在特定业务约束下扛住全校上万人的同时操作。最典型的问题有这么几个数据源头太散。学生分布在不同学院、年级、宿舍楼辅导员没法快速看到“谁没上报”校医院想统计异常体温得从若干Excel和微信接龙记录里人工汇总。权限层级复杂。一个学生干部能看本班数据辅导员能看本系学院管理员能看本学院防控办要全校汇总校领导可能要看“今日上报率”这种宏观指标。这五层权限在代码里处理得不干净后面上线就是灾难。上报场景集中爆发。每天早上8点到10点是打卡高峰上万人在几分钟内同时提交数据库和接口设计的抗压能力很重要。流程审批链路长。学生出校要申请辅导员审核学院备案门卫还要核对名单每一步断在任何一个环节线下沟通成本就翻倍。统计报表要求多。今日上报率、异常体温人数、隔离人数、出校人次、各学院完成排名……这些报表在纯Java里写起来很啰嗦Python那边一行pandas就出来了。所以这个系统真正要解决的不是“做个网站”而是把上报、审批、监测、统计、通知五件事串成一条流水线。业务上它服务于四类人学生打卡上报、出入申请、辅导员催报、审核、学院管理员汇总、导出、防控办全局决策。1.2 选型逻辑为什么是 JavaSSM 还要再揉一个 Flask先说为什么用SSM。Spring、SpringMVC、MyBatis这一套组合在国内高校和企业里沉淀太多年了资料多、面试考、课程教对毕设和中小型管理系统来说完全是够用的组合。它不像Spring Boot那样把配置大批量自动化反而更适合展示你对事务、拦截器、SQL映射这些底层机制的理解。再说为什么很多项目还要加一个Flask。我在实际开发里总结过这类防控系统有三件事用Python做效率高得多数据处理与统计。Pandas处理几万条健康上报记录生成透视表和图表数据代码量比Java的Stream加工具类少一半以上。定时任务。比如每天早上9点自动统计“昨日未上报名单”通过钉钉/企业微信/邮件接口推送给辅导员。Python写APScheduler加requests十分钟搞定。Excel报表导出。OpenPyXL或Pandas直接生成复杂格式的报表比Java的POI那套API舒服太多。双服务架构在本地调试时就是两个端口各跑各的。Java服务起在8080Flask起在5000Java通过REST接口去调Flask的统计能力Flask通过数据库直连读数据互不干扰。提示如果只是为了展示“技术栈丰富”硬把Flask塞进来反而会让评审老师追问“为什么不用纯SSM”。我建议在文档和答辩里把分工讲清楚Java管事务性核心业务Python管数据分析与自动化任务这个理由很充分。1.3 架构拆分两个服务各自管什么用一个图来理解整个系统边界浏览器/Ajax请求 │ ▼ ┌─────────────────────┐ │ SSM 核心平台 │ Tomcat :8080 │ 登录鉴权/健康上报 │ │ 出入审批/隔离管理 │ Spring SpringMVC MyBatis │ 公告与角色权限 │ └─────────┬───────────┘ │ HTTP调用统计、导出接口 ▼ ┌─────────────────────┐ │ Flask 数据服务 │ Gunicorn/python app.py :5000 │ 统计报表/Excel导出 │ │ 定时催报/异常告警 │ Flask APScheduler Pandas └─────────────────────┘SSM端负责“谁在什么时候做了什么”——比如学生提交体温、辅导员审批出校Flask端负责“整体情况怎么样”——比如今日上报率曲线、异常体温分布、导出全校报表。两个服务共用同一个MySQL库但分工清晰代码边界不互相污染。这个架构也方便以后扩展比如你后面想单独做一个微服务的健康监测模块直接复用Flask这套接口就行。2. 核心功能模块与数据库设计2.1 六大功能模块怎么划分以我做的版本为例功能模块按用户角色和业务域拆成了六块模块核心功能点主要技术落点用户与权限管理登录、角色路由、密码重置、账号管理SSM拦截器自定义注解每日健康上报体温、症状、健康状态、地址定位、行程码状态SSM接口数据库唯一索引出入校审批申请提交、辅导员审核、学院备案、门卫查看SSM事务动态SQL隔离健康监测隔离名单管理、每日体温记录、解除隔离提醒SSMFlask定时任务数据统计与报表上报率、异常统计、部门排名、Excel导出FlaskPandasOpenPyXL通知公告与教学入口公告发布、远程教学链接汇总、课程通知SSM前端标签页在线教育、远程教学这两个词在标题里也有体现。实际业务中防控系统不需要去做完整授课功能但要把“课程空间入口”集成进来比如学工通知里挂上在线教学平台的链接按学院筛选通知给对应人群起到信息汇聚的作用。这个模块别做重做重了和教务系统就边界重叠了。2.2 数据库表设计与关键字段防控系统的核心表我建议至少六张。这里把最重要的三张表结构列出来t_user 用户表字段名类型说明idbigint主键usernamevarchar(32)登录账号学号/工号passwordvarchar(128)BCrypt加密存储real_namevarchar(32)真实姓名roletinyint1学生 2辅导员 3学院管理员 4防控办collegevarchar(64)学院class_namevarchar(64)班级phonevarchar(20)手机号statustinyint1正常 0禁用t_health_report 健康上报表字段名类型说明idbigint主键user_idbigint关联用户report_datedate上报日期temperaturedecimal(4,1)体温is_symptomtinyint是否有咳嗽/乏力等症状is_contacttinyint是否接触过异常人员health_codetinyint健康码状态1绿2黄3红locationvarchar(255)当前位置省市区remarkvarchar(255)备注report_timedatetime上报时间关键语句CREATE TABLE t_health_report ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, report_date DATE NOT NULL, temperature DECIMAL(4,1), is_symptom TINYINT DEFAULT 0, is_contact TINYINT DEFAULT 0, health_code TINYINT DEFAULT 1, location VARCHAR(255), remark VARCHAR(255), report_time DATETIME, UNIQUE KEY uk_user_date (user_id, report_date) );这条UNIQUE KEY uk_user_date (user_id, report_date)是整个上报防重的第一道屏障。即使程序逻辑出现并发竞争数据库层面也能把同一个人同一天的重复上报挡掉。t_leave_apply 出入校申请表字段名类型说明idbigint主键user_idbigint学生reasonvarchar(255)出校原因就医、办事、其他destinationvarchar(255)目的地start_timedatetime计划出校时间end_timedatetime计划返校时间statustinyint0待审核 1通过 2驳回approver_idbigint审核人approve_remarkvarchar(255)审核意见create_timedatetime申请时间这里状态字段要用tinyint整数不要用varchar存“待审核”“已通过”排查问题时整数状态配合含义注释比中文枚举值高效得多。2.3 表设计里的三个实用心得第一上报表要同时保留report_date和report_time。report_date是业务日期report_time是实际提交时间。业务上允许补报昨天的卡所以这两个字段必须分开不能偷懒只存一个datetime。第二审批记录要留approve_remark。真实运营中驳回理由极其重要学生被驳回后不知道原因立马电话轰炸辅导员有一个备注字段能避免大量沟通成本。第三所有涉及隐私的字段如体温记录中的详细地理位置在页面展示时要做脱敏或按角色限制普通学生登录后不应该看到全校任何其他人的具体位置信息这个在权限设计上就要卡死。3. 关键功能实现细节SSM 和 Flask 怎样分工协作3.1 SSM端核心接口设计与实现SSM端最常见的“骨架”是Controller接收前端请求并校验基础参数Service负责事务和业务规则Mapper负责SQL。按这个思路健康上报模块的核心接口可以设计成下面这种风格。先写一个通用返回类public class Result { private Integer code; // 200成功 500失败 401未登录 private String msg; private Object data; // 省略getter/setter }然后是健康上报接口Controller RequestMapping(/api/report) public class HealthReportController { Autowired private HealthReportService reportService; // 提交健康上报 PostMapping(/submit) ResponseBody public Result submit(RequestBody HealthReportReportDTO dto, HttpSession session) { // 从session取当前登录用户避免前端传userId导致越权 User user (User) session.getAttribute(login_user); if (user null) { return Result.error(401, 请先登录); } // 基础参数校验 if (dto.getTemperature() null || dto.getTemperature() 0) { return Result.error(500, 体温参数有误); } // 交Service处理包含“该用户当天是否已上报”的判断 return reportService.submit(user.getId(), dto); } // 查询某用户一段时间的上报记录 GetMapping(/list) ResponseBody public Result list(Long userId, String beginDate, String endDate) { return reportService.listByUser(userId, beginDate, endDate); } }这里有一个很容易忽略的点登录用户从Session取而不是前端传。很多新手会把userId放在请求参数里结果任何人都能改参数替别人打卡这在防疫数据上是大忌。Service层的核心逻辑是“先查再插”但单纯先查再插在高并发下有重复风险所以我一般让Service做两层防护Service public class HealthReportServiceImpl implements HealthReportService { Autowired private HealthReportMapper reportMapper; Override Transactional(rollbackFor Exception.class) public Result submit(Long userId, HealthReportReportDTO dto) { Date today DateUtils.parseDate(DateUtils.getDate()); // 第一层查询今天是否已上报 int count reportMapper.countByUserAndDate(userId, today); if (count 0) { return Result.error(500, 您今天已经上报过请勿重复提交); } HealthReport record new HealthReport(); record.setUserId(userId); record.setReportDate(today); record.setTemperature(dto.getTemperature()); // ... 其他字段setter reportMapper.insert(record); return Result.success(); } }第一层业务拦截负责给出友好提示第二层数据库唯一索引负责极端并发兜底。两层加在一起重复打卡这个高频投诉点基本就堵死了。出入校审批接口则需要事务处理。学生先插入一条申请记录状态为0待审核辅导员审核通过后状态改为1同时往“当日允许出校名单”表里插一条门卫登录后看到的就是这个名单。如果不开事务会出现“状态改了但名单没生成”的中间状态。Override Transactional(rollbackFor Exception.class) public Result approve(Long approveId, Long applyId, Integer status, String remark) { LeaveApply apply leaveMapper.selectById(applyId); if (apply null) { return Result.error(500, 申请记录不存在); } // 只有当前登录用户是申请人的辅导院/学院管理员才有权限 // 这个权限校验在Controller拦截器层面做Service再做一次防御 leaveMapper.updateStatus(applyId, status, approveId, remark); if (status 1) { // 生成门卫通行记录 gateMapper.insert(new GateRecord(apply.getUserId(), apply.getStartTime())); } return Result.success(); }注意Transactional(rollbackFor Exception.class)。默认情况下Spring只对RuntimeException回滚如果审核中抛的是IOException这类受检异常事务不会回滚就会留下脏数据。写事务注解时最好显式指定rollbackFor。3.2 Flask端统计报表和定时任务的常规玩法Flask在这个项目里不是主平台但它的地位同样重要。我的习惯是Flask服务独立成一个子目录维护一张requirements.txtflask2.2.5 flask-cors4.0.0 pandas2.0.3 openpyxl3.1.2 apscheduler3.10.4 pymysql1.1.0 requests2.31.0Flask端做三件事第一件事统计接口。比如每天全校上报情况汇总app.route(/api/statistics/daily, methods[GET]) def daily_statistics(): date request.args.get(date) if not date: date datetime.now().strftime(%Y-%m-%d) conn get_db_conn() sql SELECT IFNULL(COUNT(*), 0) AS total, SUM(CASE WHEN temperature 37.3 THEN 1 ELSE 0 END) AS fever_count FROM t_health_report WHERE report_date %s df pd.read_sql(sql, conn, params[date]) # 再查用户总数计算上报率 ... conn.close() return jsonify({code: 200, data: {...}})代码里的37.3是体温阈值这个值在真实业务里建议放到配置项因为不同时期标准会调整写死在代码里后期改起来要重新发版。第二件事Excel导出。辅导员最爱的“一键导出一周未上报名单”用pandas做数据透视后再用openpyxl生成带格式表格。因为Excel文件生成是IO密集任务接口内部用线程池处理避免大范围导出时阻塞Flask主线程。第三件事定时催报。用APScheduler每天早上9点半统计前一天未上报的学生名单按学院分组后调用Java服务的一个通知接口把数据推给辅导员。from apscheduler.schedulers.blocking import BlockingScheduler def job_miss_report(): # 查询昨天未上报学生名单 # 调用 SSM 的 /api/notice/send 或者企业微信/钉钉机器人接口 ... scheduler BlockingScheduler() scheduler.add_job(job_miss_report, cron, hour9, minute30) scheduler.start()这里有个经验定时任务要注意“补报窗口”。某学生昨天漏报今天补报了统计“昨日未上报名单”时要把今天的补报数据合并进去否则一早就群发催报信息结果学生已经补了就容易造成负面体验。Flask端启动很简单cd flask_service python -m venv venv source venv/bin/activate # Windows下用 venv\Scripts\activate pip install -r requirements.txt python app.py建议开启debugFalse。Flask的调试模式在接入第三方服务联调时会输出大量敏感请求信息而且会导致worker重启正式环境务必关掉。3.3 前端交互与权限控制前端部分这个课题最常见的组合是SSM Layui或者SSM Bootstrap Vue2。核心页面包括登录页、学生看板今日打卡出入申请、辅导员工作台审批查看班级上报情况、学院管理页、系统管理页、数据大屏。前端调用Java接口时用jQuery的$.ajax比较常见。提交健康打卡的示例$.ajax({ url: /api/report/submit, type: POST, contentType: application/json, data: JSON.stringify({ temperature: 36.5, isSymptom: 0, isContact: 0, healthCode: 1, location: XX省XX市, remark: }), success: function(res) { if (res.code 200) { layer.msg(上报成功); } else { layer.msg(res.msg); } }, error: function() { layer.msg(网络异常,请稍后重试); } });权限控制放在两个层面。前端根据登录返回的role字段决定渲染哪个菜单后端每个接口的Controller调用拦截器校验角色。以SSM传统的HandlerInterceptor为例public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); User user (User) session.getAttribute(login_user); if (user null) { // 返回401前端跳转登录页 response.setStatus(401); return false; } // 检查请求路径和角色是否匹配 if (!PermissionChecker.check(user.getRole(), request.getRequestURI())) { response.setStatus(403); return false; } return true; } }不要只在前端隐藏按钮就以为安全了攻击者完全可以绕过前端直接调后端接口。务必每个后台接口都过权限拦截。数据大屏部分用ECharts实现。Flask提供整理好的JSON数据前端通过Ajax拉取后填充折线图每日上报率趋势、饼图各学院上报完成情况、柱状图异常体温统计。这里不用WebSocket做实时推送因为疫情数据本身是日报频率轮询加缓存足够。4. 从零跑通这套系统环境搭建与部署全流程4.1 项目资料包结构先看明白这类项目打包交付的时候一般会包含几样东西源码、LW论文文档、调试文档、讲解视频。拿到压缩包之后第一件事不是双击IDEA导入而是先看目录结构。一个合格的资料包通常长这样project/ ├── sql/ # 数据库初始化脚本 │ └── campus_epidemic.sql ├── ssm_admin/ # Java主服务 │ ├── src/main/java │ ├── src/main/resources │ ├── pom.xml │ └── ... ├── flask_service/ # Python数据服务 │ ├── app.py │ ├── requirements.txt │ └── ... ├── 论文文档/ # LW 重点看系统设计章节 ├── 调试文档/ # 记录常见报错和解决方案 └── README.md # 环境要求与启动步骤如果资料包里没有sql目录先别急着写代码直接找作者要初始化脚本否则项目大概率跑不起来。4.2 本地运行分四步走第一步准备环境。推荐这套组合组件版本建议说明JDK1.8SSM项目最稳的版本不要上来用JDK17Maven3.6.3配置阿里云镜像加速依赖下载MySQL5.7 / 8.08.0注意驱动和时区参数Tomcat8.5war包部署IDEA2019社区版够用Python3.8Flask服务使用Navicat任意可视化操作数据库第二步初始化数据库。用Navicat新建数据库字符集选utf8mb4排序规则utf8mb4_general_ci然后执行campus_epidemic.sql。执行完看下表数量和数据是否正常至少该有管理员测试账号。常见的admin账号就是admin/admin123学生账号一般是stu001/123456。第三步启动SSM服务。用IDEA打开ssm_admin目录等待Maven导入依赖。修改数据库配置jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/campus_epidemic?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的数据库密码注意如果是MySQL 5.7驱动可以用com.mysql.jdbc.DriverMySQL 8.0要用com.mysql.cj.jdbc.Driver而且必须带serverTimezoneAsia/Shanghai否则日期字段在Java和数据库之间转换时很容易差8小时或者直接报错。然后在IDEA里配置TomcatDeployment选war explodedApplication context填/直接运行。看到“Tomcat started”后访问http://localhost:8080/login.html。第四步启动Flask服务。打开自己的项目文件夹cd flask_service python -m venv venv venv\Scripts\activate # Windows pip install -r requirements.txt python app.py看到Running on http://127.0.0.1:5000就成功了。再用浏览器访问http://localhost:5000/api/statistics/daily?date2024-05-20测试接口通不通。如果跨域报错确认Flask里已经注册了CORS。两个服务都起来之后用管理员账号登录打开数据看板页面如果能看到各学院上报率数字说明Flask和SSM的联调已经打通。4.3 部署到服务器时的三个关键配置本地跑通只是第一步真正上线部署还会遇到几个问题。Tomcat的war包部署。在pom.xml里配置packaging为warIDEA里双击package生成war包扔进Tomcat的webapps目录启动后访问http://服务器IP:8080/项目名。如果部署后找不到404八成是项目名和访问路径不匹配把war包名改成ROOT.war就直接用根路径访问了。Nginx反向代理Flask。生产环境不建议直接让Flask裸奔在5000端口一般用Nginx把请求转发过去server { listen 80; server_name your.domain.com; location /api/flask/ { proxy_pass http://127.0.0.1:5000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }Java服务里配置Flask地址时也要从http://localhost:5000改成http://127.0.0.1:5000或者通过Nginx转发的内网地址不要用localhost避免线上环境解析混乱。数据库备份。健康数据极其重要我一般写一个cron脚本每天凌晨备份数据库mysqldump -uroot -p密码 campus_epidemic /backup/epidemic_$(date %Y%m%d).sql保留最近30天备份这是底线。5. 常见问题排查与避坑实录5.1 SSM启动与数据库连接问题问题1启动Tomcat后报ClassNotFound或者NoClassDefFoundError。原因大多是Maven依赖没下载完整。先在IDEA里执行mvn clean再看右侧Maven面板里有没有红色波浪线。如果网络不好在settings.xml里配置阿里云镜像mirror idaliyunmaven/id mirrorOf*/mirrorOf urlhttps://maven.aliyun.com/repository/public/url /mirror问题2数据库连接超时或Public Key Retrieval is not allowed。MySQL 8.0下需要把连接URL加上allowPublicKeyRetrievaltrue。同时在MySQL执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 密码驱动和数据库的认证插件版本不匹配时会出现这个报错。5.2 健康打卡日期边界与国际化时区问题这是这个项目里踩坑率最高的一处。Java端判断“今天是否已上报”时如果直接用new Date()得到的是当前系统时区的时间。如果你用IDEA默认时区而MySQL数据库时区是UTCWHERE report_date CURDATE()可能查不到当天数据。统一的做法是public static Date getCurrentDate() { SimpleDateFormat fmt new SimpleDateFormat(yyyy-MM-dd); String dateStr fmt.format(new Date()); try { return fmt.parse(dateStr); // 得到当天00:00:00 } catch (ParseException e) { throw new RuntimeException(e); } }同时确保MyBatis映射日期类型时jdbcTypeDATE并且数据库连接URL带serverTimezoneAsia/Shanghai。5.3 Flask跨域与定时任务常见坑联调时前端在8080端口Flask在5000端口两者不同源浏览器会拦截请求。解决方式是Flask挂上CORSfrom flask_cors import CORS CORS(app, supports_credentialsTrue)定时任务在Windows上启动后窗口不能关否则进程结束。生产环境用nohup python app.py 或者配置systemd服务来托管保证重启后自动拉起。还有一个容易被忽视的坑Flask里不要用线程池修改变量后直接返回给多线程请求。Pandas处理DataFrame本身不是线程安全的我在写统计接口时都是函数内定义新变量不做全局缓存想要提升性能加上Redis做结果缓存而不是开线程去共享内存数据。5.4 资料包中的LW、调试文档怎么用LW论文文档不是让你从第一页读到最后一页当小说看重点看两块系统设计章节里面写了用例图、E-R图、流程图这套东西直接决定了你代码里的表结构和流程跳转逻辑。代码先跑起来再用论文里的图反推代码会比一把梭通读快得多。测试章节论文里一般列了几十个测试用例这些用例就是现成的验收清单。逐条验证系统里有没有对应功能查到某个按钮点了没反应顺着接口往下排查。调试文档里记录的报错往往就是那些最容易卡的坑。我见过某份调试文档里明确写了“MySQL 8.0需要加时区参数”和“Flask端口占用用taskkill /PID xxx /F解决”照抄就能避坑。6. 实战复盘与扩展建议讲道理这套SSMFlask双栈系统在代码量上不算特别大但它把高校疫情防控里那些非常琐碎的业务真正串了起来学生端打卡、辅导员端审批、学院端汇总、防控办端决策四个角色各管一段串联得越顺系统就越“能用”。我在实际落地时还有几点体会。第一个体会是权限设计要“前置到需求阶段”。哪条数据谁可以看、哪条操作谁可以做这个问题如果拖到编码期再补十有八九要返工。我的做法是先画一张角色-权限矩阵表每个功能模块对应哪些角色权限粒度精确到按钮级别之后Controller里的拦截器配置全部照着这张表来写。防控系统的数据涉及健康隐私越权读取问题必须从设计上堵死不能指望事后补洞。第二个体会是“宁可多一个统计维度不要少一个导出功能”。辅导员对这个系统最常说的需求永远是“能不能导出”而且每次导出的格式要求都不一样。所以我把Flask的Excel导出模块做成了模板化配置字段顺序、分组方式、合并单元格都可以通过参数调整不需要每次改代码这个思路后来在别的报表类项目里也搬过去用了。第三个体会是远程教学入口不要做复杂。这套系统的核心仍然是防控业务在线教育相关内容做成公告和课程链接的聚合页就好。如果硬要把在线考试、作业提交都塞进来系统和教务系统功能重叠维护成本直接翻倍评审老师也会觉得设计离谱。至于未来扩展方向我认为有三个点值得做一是接入企业微信或钉钉的“健康打卡自动提醒”替代短信通知省成本又及时二是增加人脸识别或扫码核验门禁能力把审批表和门禁系统做深一点联动三是把上报数据做趋势分析用机器学习预测学院内发热风险这部分正好是FlaskPython最擅长的领域。技术上的路是越走越宽的系统本身只是第一步。最后分享一个我一直在用的小技巧这种双服务项目正式开发前先把两个服务的启动命令写成脚本比如start_all.bat一键拉起MySQL、Tomcat和Flask三个进程。团队协作时新人不再被“没启动服务”这种问题卡住运行环境中每次启动也少犯低级错误。
返回列表