1. 开工前先搞清楚:这套EHS系统到底解决什么问题
做毕业设计时,最忌讳一上来就写代码。我见过太多同学拿到"安全环保管理系统"这类题目,直接建个表就开始堆CRUD,最后做出来的东西自己都讲不清楚业务逻辑,答辩时被老师一问就卡壳。
先说结论:EHS是Environment(环境)、Health(健康)、Safety(安全)三个单词的缩写,在制造型企业里,这三件事往往由一个部门统管。EHS管理系统要解决的,是企业安全管理中"台账混乱、整改滞后、数据孤岛"这三大顽疾。
打个比方你就明白了。传统的安全巡检靠纸质检查表,车间发现一处隐患,填表、上报、等领导签字、再安排人去整改,这个流程走下来少说三五天,中间还容易丢单。环境部门要统计废弃物处置记录,得翻几个月前的Excel。职业健康那边,员工体检报告、劳保用品领用记录都散在各处,想查某个班组近三年的体检异常情况,几乎是不可能完成的任务。
这套系统就是把安全、环境、健康三块数据统一收口到一个平台里。隐患可以从发现、上报、整改到复查全程线上流转;环保数据可以形成可视化报表;员工健康档案和劳保用品可以按人归档、到期提醒。对于毕业设计来说,这题目的好处是领域特征强、功能边界清晰、业务逻辑足够复杂又不至于失控——既有常规的增删改查,又有状态流转、审批、提醒这些有技术含量的设计点,非常适合用来展示SpringBoot的核心能力。
我带的几个学生做完这套系统后反馈很一致:写业务代码本身难度不大,真正花时间的反而是把EHS的业务规则理清楚,以及把SpringBoot的周边生态(权限、定时任务、文件存储、报表导出)整合好。这篇就把整个思路铺开讲一遍,重点会说我的设计取舍和踩坑过程,可以直接拿来当开题和开发的参考。
2. SpringBoot技术栈选型:为什么是这个组合,以及版本怎么定
技术选型这块,直接看我在实践中的取舍和理由。
2.1 框架版本:选2.7而不是3.x
很多同学习惯把Spring Boot版本拉最新,但做毕设,我强烈建议用Spring Boot 2.7.x。原因很实际:
- 3.x基于Jakarta EE,很多老教程里的javax包路径写法会报错,排查起来费时间
- 2.7是2.x系列最后一个免费维护版本,资料最全,遇到报错一搜就有答案
- 大部分毕业设计的依赖(比如MyBatis Plus、Shiro、JWT工具包)在2.7下都有成熟兼容版本
我用的是Spring Boot 2.7.8,配合JDK 1.8。别小看JDK版本,JDK 17配合2.7.x虽然也能跑,但某些依赖会出现编译问题,为了省事,JDK 8是最稳妥的选择。
2.2 核心依赖清单
这套系统的依赖选型如下:
| 组件 | 选型 | 说明 |
|---|---|---|
| 持久层 | MyBatis Plus 3.5.x | 内置分页插件和代码生成器,省掉大量Mapper XML |
| 数据库 | MySQL 8.0 | 开源、免费、毕设友好 |
| 权限认证 | JWT + Spring Security | 前后端分离项目的标准方案 |
| 缓存 | Redis | 存登录态、验证码、高频读取的配置项 |
| 文件存储 | MinIO | 统一种安全隐患图片、报告附件的上传管理 |
| 定时任务 | Spring Quartz | 处理隐患超期提醒、劳保用品到期提醒 |
| 报表导出 | Apache POI / EasyExcel | 生成Excel格式的统计报表 |
这套组合的合理性在于:每个组件都有明确的落地场景,不会让人觉得"为了用而用"。比如Redis不只用来存登录状态,还可以缓存隐患类型字典表,这个设计在答辩时能体现你对性能的思考。
2.3 Maven项目结构
项目用Maven构建,标准的父子模块结构:
ehs-system ├── ehs-common # 通用工具类、返回结果封装、异常处理 ├── ehs-framework # Spring Security、JWT过滤器、配置类 ├── ehs-system # 业务模块:用户、角色、菜单 ├── ehs-domain # EHS业务实体和Mapper └── ehs-web # Controller层、启动类、配置文件如果是单体毕设,用单模块其实也行,但多模块有一个好处:后端的代码量看起来更规范,论文里画项目结构图也更有说服力。我实际开发中遇到过一个问题——Spring Boot Test扫描模块时Bean找不到,后来发现是@SpringBootApplication放在ehs-web模块,而MyBatis的Mapper接口在ehs-domain模块,需要指定@ComponentScan和@MapperScan的扫描路径,这个细节很多人会踩。
3. EHS核心数据模型:安全、环境、健康三块业务怎么建表
EHS系统的数据建模和普通业务系统不太一样,它不是简单的"用户-角色-菜单"加几张业务表就完事。安全、环境、健康三块业务的数据关系既有独立维度又有交叉关联,设计不好后面写SQL会非常痛苦。
3.1 安全模块的核心表设计
安全模块是整个EHS系统的重头戏,最常见也最重要的两张表是隐患登记表和巡检任务表。
隐患登记表的核心字段,除了基础的主键、隐患描述、隐患位置、发现人、发现时间、风险等级,还有一个关键字段叫隐患状态。我把它设计成状态机流转:
待整改 -> 整改中 -> 待复查 -> 已闭环 ↑ ↓ 发现隐患 -> 指派整改人 -> 复查通过这个状态机是整个系统的核心逻辑之一。为什么我强调用状态机而不是单个状态字段?因为隐患整改遵循的是**"五定原则"——定人员、定时间、定措施、定责任、定预案**。一张表只记录当前状态,你就没法追溯"这个隐患是谁指派的、整改期限是哪天、超期了系统要提醒谁"。所以我在隐患表之外,又加了一张整改进度日志表,每条状态变更都落一条日志,这样既能追责,后续做报表也有原始数据。
巡检任务表则是隐患的上游入口。我会预置一批巡检点(比如"一车间配电室""仓库消火栓"),每个巡检点设置巡检周期和责任人,定时任务到点自动生成巡检工单,巡检人填写结果时如果发现问题,一键转入隐患登记流程。这个联动设计是整个系统的演示亮点。
3.2 环境模块与健康模块的表结构
环境模块的表没有安全模块复杂,但有一个容易忽略的点:排放物的数据要按时间维度组织。我的设计中有一张废气排放记录表,按月记录废气检测数据,关联到对应的排放口和监测指标。展示时用折线图呈现趋势,这张表就是图表的数据源。
健康模块则是典型的"一主多从"结构。员工健康档案表做主表,子表包括体检记录、劳保用品领用记录、职业危害接触记录。用员工ID关联,后续可以一个员工页面把三年内的体检趋势、劳保领用明细都拉出来。
EHS数据模型设计上,最核心的一条经验是:干线穷举优先建,交叉统计靠中间表。比如查"某车间在3月份有多少条隐患未闭环",如果隐患表关联了车间ID,一条SQL就解决;如果当初没设计车间维度,后面查这类统计只能逐条过滤,性能堪忧。
4. 隐患排查闭环流程:状态机+定时任务+消息触达的落地细节
安全隐患整改模块是这套系统里技术含量最高、也是答辩时最能拿出来讲的部分。这里把完整的设计链路拆开说。
4.1 闭环流程的完整链路
我设计的隐患闭环路径是这样的:
- 发现登记:巡检人(或任意登录用户)填写隐患信息、上传现场照片、选择风险等级
- 系统自动指派:根据隐患所属区域,自动匹配该区域的安全责任人,生成整改任务
- 整改处理:责任人收到待办,填写整改措施和整改结果
- 复查验收:安全主管对整改结果进行复查,支持退回重改
- 归档闭环:复查通过后,隐患单自动归档,纳入历史台账
在这个流程里,SpringBoot的关键技术应用点有三个:
第一,状态流转的后端实现。我写了一个整改状态处理器,用策略模式加状态枚举来管理流转:
public enum RectificationStatus { PENDING(0, "待整改"), PROCESSING(1, "整改中"), PENDING_REVIEW(2, "待复查"), CLOSED(3, "已闭环"); private Integer code; private String desc; }每个状态下只允许执行特定的操作。比如"已闭环"状态不允许再提交整改内容,Controller在入口做状态校验。这个设计比纯if-else判断要清晰得多,也更好扩展。
第二,超时提醒的定时任务调度。隐患整改设置了整改期限(一般高风险3天、中风险7天、低风险15天)。我用Spring Quartz实现了一个跑批任务,每天凌晨扫描隐患表,把超过整改期限未关闭的隐患找出来,向对应责任人推送待办通知。
第三,消息触达的渠道设计。系统内的待办信息通过站内信呈现——其实就是在数据库里加了一张通知表,存接收人ID、内容、是否已读。用户登录后在首页的待办中心看到红点提醒。如果后续想扩展,可以在这个基础上接邮件或短信,接口可以做成策略模式。
4.2 演示时的操作顺序怎么设计
这里说一个答辩演示的小技巧。很多同学演示隐患模块时,直接进列表页点"新增"填一条数据,老师看着没有任何代入感。
我的建议是先把一个预置的真实感场景放进去。比如提前录入一条带图片、有完整整改日志的隐患记录,演示时从待办中心进入,点开这条记录,带着老师一步步看状态流转的历史轨迹。这样老师能直观感受到这个系统不是空壳,是有真实业务承载的。
我实测下来,这条演示路线比生硬地演示增删改查效果好得多,也更容易让老师理解系统的业务价值。
5. 权限、缓存、文件上传、图表与报表:通用能力怎么贴合EHS场景
EHS系统的通用能力模块,如果只是简单做登录注册和CRUD,深度明显不够。这里讲几个我做了重点设计的地方。
5.1 基于RBAC的多角色权限控制
EHS平台的用户角色天然是多样化的:系统管理员、安全主管、车间安全员、环境专员、职业健康专员、普通员工。不同角色看到的菜单和能操作的功能完全不一样。
我用的方案是Spring Security + JWT + RBAC三张表(用户、角色、菜单)。登录成功后后端生成JWT令牌,前端把令牌存到localStorage里,每次请求在Header里带上。后端通过拦截器解析令牌,把用户信息放进SecurityContext。
权限控制的细化粒度我建议做到按钮级别。比如"隐患登记"按钮,普通员工能看到,但"隐患指派"按钮只有安全主管能操作。前端通过后端返回的按钮权限标识做v-if渲染,后端在Controller增加@PreAuthorize注解做二次校验。这个"前端控制显示+后端控制权限"的双重校验,是答辩时的一个加分项。
5.2 Redis缓存的高频使用场景
Redis在EHS系统里我主要用在了三个地方:
- 登录验证码:生成后存Redis,设置5分钟过期
- 隐患类型字典:启动时加载到Redis,查询时优先走缓存
- 用户待办数量:登录后显示待办红点数字,从Redis读取,有变更时清除重建
这里有一个缓存穿透的实际案例。隐患类型字典表总量不超过50条,属于典型的"读多写少"数据。如果每次前端需要下拉框选项时都查数据库,虽然压力不大,但高频页面上接口响应会有明显延迟。我做了个简单处理:接口先查Redis,没有再从数据库加载并回写缓存。
5.3 文件上传与MinIO整合
隐患登记时要上传现场照片,整改完成要传整改后照片,安全隐患台账要挂附件——文件存储是EHS系统跑不掉的刚需。
我一开始用本地磁盘存储,文件存在项目根目录的upload文件夹下,后来发现两个问题:一是项目重新打包会覆盖文件,二是论文里写"文件存储在应用服务器本地磁盘"显得不够现代化。于是换了MinIO,一个开源的对象存储服务。
SpringBoot整合MinIO的关键代码很简单:
@Configuration public class MinioConfig { @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint("http://localhost:9000") .credentials("minioadmin", "minioadmin") .build(); } }上传文件时调readyBucket判断桶是否存在,不存在则创建,然后putObject上传,返回文件访问路径。前端用<el-image>直接展示上传后的图片,非常顺畅。MinIO有Web控制台,演示之前先在浏览器里打开管理界面,老师可以看到上传的隐患照片都在里面躺着,很直观。
5.4 图表和报表:从数据到决策
EHS系统没有报表和图表会显得很单薄。我做了三个维度的可视化:
- 安全驾驶舱:首页展示未闭环隐患数、本月巡检完成率、隐患环比趋势折线图
- 环境监测页:近12个月废气排放趋势图,柱状图加折线图组合
- 健康管理页:员工体检异常率统计、劳保用品到期数量提醒
后端图表接口统一使用聚合查询:
public List<Map<String, Object>> getTrendData(Integer months) { // 按月份分组统计隐患数量 return jdbcTemplate.queryForList( "SELECT DATE_FORMAT(create_time, '%Y-%m') as month, " + "COUNT(*) as cnt FROM hazard WHERE create_time >= ? GROUP BY month", startTime); }前端用的是轻量级图表库,考虑到毕设项目的定位,不需要引入太重型的可视化组件,能画折线图、柱状图、饼图就够了。
报表导出用EasyExcel,写一个监听器,查询隐患台账列表,调用ExcelWriter写入流,前端一个按钮点击就下载。答辩前可以预生成一份真实感的月度隐患分析报告,用导出的Excel跟在座老师展示,比单纯看页面更能加分。
6. 项目部署、演示数据和答辩准备的实战经验
最后这部分,说说这套系统的部署和答辩环节最容易忽略的事情。
6.1 本地环境搭建和演示环境准备
如果你的开发环境是Windows,数据库和Redis服务装好之后,重点检查几个配置文件:
- application.yml:MySQL连接串的时区参数serverTimezone设为Asia/Shanghai,否则日期字段会有8小时偏差
- Redis密码:如果本地Redis没设密码,配置里就留空,但有密码时启动时会报认证失败
- MinIO端口:默认9000,注意防火墙放行
启动顺序也很重要:先启动MySQL和Redis,再启动MinIO,最后启动Spring Boot应用。我遇到过启动顺序写错导致应用连不上Redis的尴尬,查了半天才发现是忘了启动服务。
6.2 演示数据怎么造才真实
毕设答辩最怕的场面是:系统里空空荡荡,老师一页页翻什么都没有。所以演示数据必须提前认真准备。
我造数据的方式是写一个DataInitializer类,项目启动时自动初始化:
- 创建5个用户(管理员、安全主管、车间安全员、环境专员、普通员工),密码统一123456
- 录入20条隐患数据,分布在不同月份,状态覆盖各个阶段
- 录入10个巡检点、30份巡检记录
- 录入15名员工健康档案、若干条体检记录
- 环境模块录入12个月的废气排放模拟数据
- 日常待办、通知公告、操作日志也铺满
这样打开系统后,首页驾驶舱的数据图表不会是全空的,各个模块点进去都有内容可看。这个环节很耗费耐心,但直接决定答辩时的观感。
6.3 答辩时容易被追问的三类技术问题
结合我带毕设的经验,EHS系统答辩时老师最容易追问这几个技术点:
- "安全隐患状态流转你是怎么保证数据一致性的?"回答思路:状态变更限定在特定操作内,每次流转增加状态校验,同时通过日志表记录全部历史状态,保证可回溯。
- "JWT过期了用户怎么办?"回答思路:JWT是无状态的,过期后前端收到401状态码,引导用户重新登录。业务上用了双token机制(访问token短时效、刷新token长时效),刷新token过期才强制重新登录。
- "如果隐患数据量达到百万级别,你的查询会慢吗?"回答思路:隐患表在create_time和status上建了联合索引,列表查询默认按创建时间倒序分页,同时支持状态过滤。数据量大时可以引入读写分离或分表,但这属于扩展方案。
这三个问题的回答思路,在开发时就要想清楚,因为它们的答案其实都已经体现在你的代码设计里了。
6.4 代码和论文对应表:避免"系统做完论文没得写"
最后给你一个非常实用的清单。很多同学系统做完了,写论文时不知道哪些内容算工作量。建议你在开发时顺手做一张"功能点-技术点-论文章节"的对应记录:
- 页面仪表盘 -> 聚合查询、定时任务 -> 数据可视化章节
- 隐患闭环 -> 状态机设计、Quartz调度 -> 系统详细设计章节
- 角色权限 -> Spring Security+JWT -> 系统安全设计章节
- MinIO文件上传 -> 对象存储集成 -> 系统集成章节
- Excel导出 -> EasyExcel -> 报表模块章节
开发过程里随手记录,写论文时会轻松一大截。
7. 我做完这套系统后的几点心得
EHS系统做完,我自己最大的体会是:这个题目选出来的效果上限,取决于你对业务闭环的理解深度,而不是技术栈的新旧。SpringBoot本身是个"熟练工"框架,真正让系统亮眼的,是隐患排查闭环设计、角色分权、状态机、定时任务整合这些能讲出逻辑的设计点。
一个比较意外的收获是,我在做定时任务超期提醒时,为了验证逻辑反复调时间参数,后来干脆把整改期限设计成了可配置项——管理员在系统设置里就能修改不同风险等级的整改时限。这个细节虽然不起眼,但它在答辩时体现出了你对业务弹性的考虑,比写一堆花哨代码有用得多。
最后提醒一件事。如果你是纯新手,开发顺序建议先做权限模块再做业务模块。因为所有页面都依赖登录用户信息,地基不打牢,后面每写一个模块都要翻回去修权限,非常痛苦。我先做通了用户-角色-菜单这条链路,后续隐患、巡检、健康档案都是在这个地基上快速垒起来的。
这套系统如果你从零开始写,预留三到四周比较稳妥:第一周围绕环境搭建和数据建模,第二周做权限和用户模块,第三周做EHS三大业务闭环,最后一周留给图表报表和演示数据准备。节奏稳住,过程记录好,不管是系统展示还是论文写作,都会很从容。