ARTICLE DETAIL

资讯详情

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

Java OA办公审批系统源码实战:Spring Boot+MyBatis部署与二次开发指南

Java OA办公审批系统源码实战:Spring Boot+MyBatis部署与二次开发指南 简介这是一套基于Java技术栈开发的完整OA办公审批系统源码及配套文档面向计算机相关专业本科生、研究生、教师及初级开发人员适用于毕业设计、课程设计、企业内部系统参考或SpringBootVue全栈学习实践。资源包含108个文件涵盖91个Java业务与配置类如ProcessServiceImpl、SysRoleController、WebSecurityConfig等、12个MyBatisPlus映射XML、2个SpringBoot配置yml文件以及README说明和架构图PNG整体压缩包仅106KB轻量易部署。已有726人下载学习代码经实测可正常运行覆盖管理端权限/审批/菜单管理与员工端微信公众号授权登录、审批流程、消息推送双角色场景。项目采用SpringBootMyBatisPlusSpringSecurityRedisActiviti后端架构前端基于vue-admin-templateElementUI模块划分清晰oa-parent统管common、model、service-oa并提供完整RESTful接口清单含角色/用户/登录等30标准API便于二次开发与功能扩展。 这套基于Java开发的OA办公审批系统源码我拿到手之后从解压到跑通花了不到一个下午整个流程走下来还是很顺畅的。这类项目源码包在圈子里一直很受欢迎——Spring Boot MyBatis的基础架构加上部门管理、用户权限、审批流、消息提醒这类OA核心模块无论是拿来练手、做毕业设计、参考二次开发还是给公司内部快速搭一套轻量审批系统都挺合适。网上类似的源码资源不少但很多包里的“项目详细说明”要么没写透要么跟代码对不上。我这里就把这套源码从整体设计、目录结构、核心审批流程、环境配置到跑通部署、常见坑点完完整整拆开讲一遍手把手带着你把这套OA办公审批系统从压缩包变成能访问的网页应用。1. 项目整体设计与思路拆解1.1 典型OA审批系统的功能边界到底包含哪些先看这套系统解决的核心问题把公司里日常要走的纸质审批流程搬到线上。请假、报销、用章申请、合同审批、物资领用……这些场景本质上都是“业务单据 审批过程”的组合。所以整个系统在功能层面一定要守住两条线第一条是“单据数据线”员工发起一个申请填写表单数据请假天数、报销金额、事由等这些数据需要有地方存、有地方查、按人员过滤可见范围。第二条是“审批流程线”单据从发起人提交之后要经过一级主管、二级主管、甚至跨部门会签每一层看到的是同一张表单但要先做出“通过/驳回/转交”的操作流程走到哪个节点需要清晰可见。围绕这两条主线再往外扩就是支撑性模块用户与组织架构管理部门树、用户账号、角色权限、岗位信息。审批流里“谁能审、按什么层级审”依赖这一层的数据。菜单与权限控制不同角色的用户登录进去看到的菜单和操作按钮不同典型RBAC基于角色的访问控制模型。系统监控与日志登录日志、操作日志、在线用户管理。消息与待办审批单据流转时当前审批人要有待办提醒甚至短信/邮件/站内信通知。如果你把压缩包里的源码解压开看会发现这些功能在代码层面是分层完成的功能模块划分和这套逻辑是能对上号的。1.2 技术选型为什么是这套组合这套OA源码的技术栈是当前主流的Java企业级开发组合属于“大众情人”级别后端框架Spring Boot基于Spring生态但简化了大量XML配置内嵌Tomcat容器打一个jar包就能跑部署成本低。持久层框架MyBatis / MyBatis-PlusSQL控制力强动态SQL适合审批系统里各种条件查询的场景。数据库MySQL 5.7或8.0业务量不大的OA系统用MySQL完全够数据量上去之后可以做读写分离或者换PostgreSQL。前端Vue Element UI或者类似的管理后台模板前后端分离接口走JSON。权限框架Apache Shiro 或 Spring Security两者都有。Shiro上手轻Spring Security功能全看源码里具体集成哪一个。工作流部分源码包自研了简单审批流部分直接集成Activiti/Flowable区别在于改造成本不同后面细说。为什么选这套组合而不去上Spring Cloud微服务因为OA办公审批系统属于企业内部管理系统并发量通常不会爆炸式增长单体应用阶段完全撑得住。微服务带来的注册中心、配置中心、分布式事务成本对团队和维护者来说都是额外的负担。核心业务逻辑清晰、开发效率高、运维简单单体现在就是最优解。1.3 源码包大概率是基于什么脚手架二开的我在解压之后翻了下pom.xml和包名这大概率是基于RuoYi若依或者类似风格的脚手架二次开发的。判断依据有几个三层包结构com.xxx.framework、com.xxx.system、com.xxx.project这类划分就是若依的经典结构。通用工具类齐全包含Redis工具、Excel导入导出、代码生成器、日志注解Log。前端使用Vue Element代码里包含src/api目录接口统一管理。基于若依这类脚手架二开是江湖上最常见的做法。脚手架本身的用户管理、权限管理、代码生成器就是现成的开发者只需要在上面加业务模块比如请假、报销、审批节点表再改改菜单SQL一套OA就能快速落地。这个细节对你后续深入研究源码很重要如果你知道通用脚手架的分层逻辑那读源码时七八成的代码都能快速看懂另外若依生态的文档也比较齐全网上搜得到大量配置说明和常见问题解决方案二次改造时能少踩很多坑。2. 源码目录与核心配置深度解析2.1 从zip压缩包到解压后验证完整性先说个常见的痛点。很多时候从网上下载的zip包在解压时会报“file is not a zip file”或者“invalid zip archive: could not find eocd”这种问题十有八九是下载过程不完整或者文件损坏导致的。我在Linux环境下习惯用unzip -t来校验unzip -t 基于Java开发的OA办公审批系统源码项目详细说明.zip看到No errors detected in compressed data of this zip file才说明包是完整的。Windows环境下用WinRAR打开时如果直接报错也是同样的原因重新下载一遍基本能解决。解压命令unzip 基于Java开发的OA办公审批系统源码项目详细说明.zip -d oa-project解压之后你会看到两大块内容一块是源码工程目录一块是项目说明文档。文档通常包含环境要求、部署步骤、账号密码、功能清单和数据库设计说明是整套系统的“说明书”别跳着看后面部署时很多关键信息都在这份文档里。2.2 后端标准工程结构怎么读进到源码目录后先看工程根目录下的pom.xml。这里第一件事就是确认JDK版本和Spring Boot版本这是之后配置本地环境的关键。典型配置是java.version1.8、spring-boot-starter-parent2.5.x或2.7.x。然后看工程分几个模块常见的是├── pom.xml # 父pom统一管理依赖和版本 ├── oa-admin/ # 启动模块包含启动类和admin接口 │ ├── src/main/java/com/xxx/OaApplication.java │ └── src/main/resources/ # 配置文件、静态资源 ├── oa-framework/ # 框架配置安全、Redis、拦截器、AOP ├── oa-system/ # 系统管理模块用户、角色、部门、菜单 └── oa-project/ # 业务模块审批流、公告、申请单等如果源码里只有一个单模块工程没有子模块那包结构依然是可以按功能分目录的controller、service、mapper、domain、common。单模块的改造空间相对小一些但阅读起来更直观。业务模块的controller层典型的接口风格长这样RestController RequestMapping(/oa/bill) public class BillController extends BaseController { Autowired private IBillService billService; /** * 提交审批单 */ PostMapping(/submit) public AjaxResult submit(RequestBody BizBillEntity bill) { return success(billService.submitBill(bill)); } /** * 审批人处理审批单 */ PostMapping(/approve) public AjaxResult approve(RequestBody ApproveRequest request) { return success(billService.approve(request)); } }看多了之后你会发现Java后端整个流程很简单controller接收前端请求把参数交给service处理业务逻辑service通过mapper操作数据库处理完返回统一格式的JSON。OA系统的代码也无非是在这个骨架基础上填充审批节点的流转判断。2.3 配置文件里暗含的环境依赖打开oa-admin/src/main/resources/application.yml重点关注几个配置项server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/oa_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 password: mybatis: mapperLocations: classpath:mapper/**/*.xml typeAliasesPackage: com.xxx.**.domain这里有两个环境依赖需要注意数据库连接串里的serverTimezoneAsia/Shanghai很多人部署时忘了配结果启动报时区错误或者日期格式对不上。这个参数的作用是告诉MySQL驱动使用哪个时区国内服务器必须配Asia/Shanghai。Redis在部分源码里是可选依赖但很多登录会话和验证码功能依赖Redis。如果启动时Redis连不上系统会报错。如果你本地没装Redis可以先检查验证码逻辑是否依赖或者临时把相关功能关掉但最稳妥的还是在本地把Redis装上Windows版本下载后解压就能用默认端口6379。2.4 数据库初始化脚本怎么导入源码目录下一般会有一个sql/文件夹里面放着初始化脚本。典型的文件有oa_db.sql或者ry_2024.sql这类命名。导入之前先建库CREATE DATABASE oa_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;然后命令行导入mysql -uroot -p oa_db oa_db.sql打开sql文件扫一眼表结构你会发现几类关键表sys_user用户表初始管理员的用户名密码在里面密码通常是MD5加密存储的初始密码是123456这种加密串直接固定。sys_menu菜单表权限控制和前端动态路由的数据源。sys_role、sys_user_role角色表及用户角色关联表。biz_*开头的是业务审批表比如biz_leave请假单、biz_process_record审批记录表。熟悉这些表的结构之后你就知道审批流的数据是怎么组织的后面看代码时脑子里始终有“数据表长什么样、接口在操作哪张表”的概念。3. 核心审批流程的实现细节与实操要点3.1 审批流的数据模型设计审批系统的核心在于“业务数据”和“审批数据”如何解耦。常见的自研方案是两张表配合业务表如biz_leave存申请单自己的业务字段比如请假类型、开始时间、结束时间、事由、附件。审批记录表如biz_process_record每一行代表一个审批节点包括审批人、审批状态、审批意见、审批时间、下一节点。以请假单为例数据流转大概是这样发起人提交 → 插入biz_leave一行status0待审 → 插入biz_process_record一行节点部门主管状态0 部门主管通过 → 更新biz_leave.status0 → 更新当前process_record状态1 → 插入新process_record节点总经理状态0 总经理通过 → 更新biz_leave.status1已通过 → 更新当前process_record状态1 → 流程结束这个设计的好处是单据本身不存复杂的状态机信息审批到了哪一步由process_record表的记录动态决定。后续如果要加会签、加签、转办、撤回等功能也只需要在记录表里增加对应的节点类型字段就行。实际源码里审批状态的枚举一般是这样的public enum BillStatus { DRAFT(0, 草稿), PENDING(1, 待审批), APPROVED(2, 已通过), REJECTED(3, 已驳回), CANCELED(4, 已撤回); private final Integer code; private final String desc; // 构造函数和getter省略 }3.2 审批提交流程的代码实现逻辑打开审批service实现类核心方法submitBill的逻辑通常是校验当前用户是否有发起该类型申请的权限。根据申请类型查询对应流程节点定义。比如请假的流程节点可能是“部门主管 → 总经理”在数据库里这张表叫biz_process_define。保存业务单据初始状态为“待审批”。根据流程节点定义生成第一条审批记录审批人设为部门主管。给审批人发送站内消息/待办提醒。代码骨架类似于Transactional(rollbackFor Exception.class) public Long submitBill(BizBillEntity bill) { // 1. 获取当前登录用户 LoginUser loginUser SecurityUtils.getLoginUser(); Long userId loginUser.getUserId(); // 2. 单据状态设为待审批 bill.setStatus(BillStatus.PENDING.getCode()); bill.setCreatorId(userId); billMapper.insert(bill); // 3. 查询流程定义 ListProcessNode nodes processDefineMapper .selectNodesByType(bill.getBillType()); // 4. 创建第一条审批记录 ProcessRecord record new ProcessRecord(); record.setBillId(bill.getId()); record.setNode(nodes.get(0).getNodeName()); record.setApproverId(nodes.get(0).getApproverId()); record.setStatus(0); processRecordMapper.insert(record); // 5. 发送待办提醒 messageService.sendTodo(userId, nodes.get(0).getApproverId(), bill.getId()); return bill.getId(); }关键点在第3步流程节点不是在前端写死的而是从数据库里查出来。这样后续调整审批层级时只要改数据库配置不需要改代码重新部署这也是OA系统灵活性的一个体现。3.3 审批通过、驳回、撤回的边界处理审批操作的实现难点不在于把状态从0改成1而在于各种边界情况的处理。我来梳理一下源码里常见处理方式通过操作Transactional(rollbackFor Exception.class) public void approve(ApproveRequest request) { // 1. 校验是否是当前审批人 ProcessRecord currentRecord processRecordMapper .selectCurrentRecord(request.getBillId()); if (!currentRecord.getApproverId().equals(SecurityUtils.getUserId())) { throw new ServiceException(非当前审批人无法操作); } // 2. 更新当前节点状态 currentRecord.setStatus(1); currentRecord.setComment(request.getComment()); processRecordMapper.updateById(currentRecord); // 3. 查下一节点 ProcessNode nextNode processDefineMapper .selectNextNode(request.getBillType(), currentRecord.getNodeOrder()); // 4. 如果没有下一节点则单据最终通过 if (nextNode null) { BizBillEntity bill billMapper.selectById(request.getBillId()); bill.setStatus(BillStatus.APPROVED.getCode()); billMapper.updateById(bill); } else { // 5. 否则创建下一条待办记录并通知下一审批人 ProcessRecord nextRecord new ProcessRecord(); nextRecord.setBillId(request.getBillId()); nextRecord.setNode(nextNode.getNodeName()); nextRecord.setApproverId(nextNode.getApproverId()); nextRecord.setStatus(0); processRecordMapper.insert(nextRecord); messageService.sendTodo(/*参数略*/); } }这里有使用到Transactional注解就是事务控制。审批操作涉及“更新当前记录新增下一条记录更新单据状态”三个步骤必须保证全部成功或全部回滚否则会出现单据处于“半审批”状态前面通过了后面没人管。驳回操作一种策略是驳回直接终止流程单据状态改为“已驳回”发起人可以修改后重新提交。另一种策略是驳回到上一节点重新审批。源码里多数情况是第一种简单直接。撤回操作发起人在审批人还没处理时可以撤回申请。实现上要判断当前待办记录是否已经有人处理如果还没处理直接删除或者关闭待办记录单据状态改为“已撤回”。这块逻辑如果能完完整整走通OA审批系统的核心就吃得差不多了剩下的部门管理、用户管理等模块相对常规照着CRUD逻辑理解即可。3.4 审批链与待办列表的联动审批人的“待办列表”在SQL层面其实是查process_record表中当前用户为审批人、状态为0的记录然后关联业务表查出单据的基本信息。这里有一个性能优化点待办列表要用数据库索引process_record表里的approver_id和status字段一定要建联合索引否则数据量大了之后每次打开待办页面都会扫全表越用越卡。在实际源码中这个查询通常是select idselectTodoList resultTypeTodoMap SELECT r.id, r.node, r.bill_id, b.bill_type, b.apply_time, b.amount FROM biz_process_record r INNER JOIN biz_bill b ON r.bill_id b.id WHERE r.approver_id #{userId} AND r.status 0 ORDER BY r.create_time DESC /select前端显示待办列表时每条记录点击进去通过bill_id和bill_type调对应的详情接口展示申请表单。很多新手在这里容易犯迷糊为什么待办列表里没有直接存全量表单数据因为审批系统里“核心是流程流转业务数据要跟着流程走”如果每条待办都冗余全量数据流程一变要同步的地方就太多了麻烦。4. 本地跑通项目的实操过程4.1 环境准备清单在动手跑源码之前先把环境核对一遍不然启动报错时还得回头排查环境问题。按照这套源码的要求本地需要准备组件版本要求用途备注JDK1.8或根据源码要求11/17Java编译与运行必须配置JAVA_HOME环境变量Maven3.6依赖管理与构建打包国内建议配置阿里云镜像MySQL5.7或8.0业务数据存储初始化建库导入脚本Redis任意稳定版本缓存、验证码、会话若源码强依赖则必须开Node.js14仅前端需要Vue前端运行前后端分离时用IDEIDEA或Eclipse开发调试推荐IDEA自带Maven集成4.2 JDK环境变量配置与验证JDK装好后环境变量这块最容易出问题。Windows下的配置要点JAVA_HOME指向JDK安装根目录比如C:\Program Files\Java\jdk1.8.0_202不要配到bin目录。PATH中追加%JAVA_HOME%\bin。配置完成后重新开一个命令行窗口输入java -version和javac -version验证。java -version # 期望输出java version 1.8.0_202 javac -version # 期望输出javac 1.8.0_202这里有个坑如果电脑上装过其他JDK版本java命令可能被Path优先级劫持。用where java看看实际执行的是哪个路径下的命令如果是别的版本调整PATH顺序或者卸载旧版本。4.3 Maven配置与依赖导入Maven下载依赖慢是国内开发者永远的痛。在maven/conf/settings.xml里配置阿里云镜像下载速度快好几倍mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror用IDEA打开源码工程后IDEA会自动识别Maven工程依赖导入需要一点时间。如果遇到某个依赖下载失败不要反复点刷新先检查本地仓库里是否有残留的.lastUpdated文件把失败的文件删掉再重新导入。实操指令# 在本地仓库目录下查找下载失败残留 find ~/.m2/repository -name *.lastUpdated -type f | wc -l # 删除残留 find ~/.m2/repository -name *.lastUpdated -type f -delete4.4 数据库导入与配置修改数据库连接参数在application-druid.yml或application.yml里确认以下三项和你的本地环境一致url: jdbc:mysql://localhost:3306/oa_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你自己的密码如果数据库密码包含、、#这些特殊字符URL里需要进行编码比如要写成%40不然解析会出错。这是非常容易踩的细节。导入sql脚本时如果文件较大命令行导入比用Navicat可视化导入更稳不需要打开脚本等半天mysql -uroot -p oa_db /path/to/oa_db.sql导入完成后登录数据库验证一下核心表的数量和数据USE oa_db; SHOW TABLES; SELECT * FROM sys_user WHERE user_name admin;4.5 启动后端和前端后端启动直接在IDEA里运行OaApplication.main方法。如果源码是前后端分离控制台出现类似Started OaApplication in 8.32 seconds和Tomcat started on port(s): 8080就说明后端起来了。看到这些信息后打开浏览器访问http://localhost:8080正常情况下会在接口层面返回JSON或者如果配置了静态资源直接出现前端页面。前端工程如果单独存在进入目录安装依赖并启动cd ruoyi-ui npm install npm run dev启动成功后Vue默认端口是80或者8081看vue.config.js里的配置。浏览器访问前端地址默认账号密码通常是admin / admin123。登录之后先看“待办事项”和“审批中心”菜单从一个系统使用者的角度先操作一遍熟悉了业务流程之后再回代码里定位对应接口这样读源码的效率会高很多。4.6 首次登录后建议先检查什么登录进去不要急着点来点去先在系统管理菜单里核对部门结构和测试账号。很多源码包的初始化数据里自带测试部门、测试角色、测试流程模板这些数据就是为验证流程准备的。我个人建议的验证路径是新建一个普通用户比如zhangsan→ 用admin给他分配角色和部门 → 退出登录用zhangsan登录 → 发起一条请假申请 → 退出切回admin → 在待办列表里能看到这条申请 → 执行通过 → 再创建一个更高级别的审批人如果流程定义了二级审批→ 继续审批 → 直到流程结束。这条链路走通说明整个审批主流程是好的。5. 常见问题与排查技巧实录5.1 部署启动阶段的问题速查表异常现象根本原因排查与解决启动报java.sql.SQLException: The server time zone value数据库连接串没配时区在url后加serverTimezoneAsia/Shanghai启动报Unable to connect to RedisRedis未启动或密码错误本地启动Redis服务检查spring.redis.password是否配置正确前端白屏、接口404前后端端口/代理未配置检查Vue的vue.config.js里proxy的target是否指向后端8080端口依赖下载失败网络问题或镜像未配置配置阿里云镜像删除本地仓库.lastUpdated残留文件后重试数据库sql导入报错脚本编码或MySQL版本兼容问题确认导入时使用utf8mb4部分脚本在MySQL8.0下需要调整语法登录提示验证码错误Redis缓存没刷新清浏览器缓存或检查Redis key清理策略接口报Invalid bound statementMapper XML没被扫描到检查application.yml中mapperLocations路径是否与XML实际路径一致打包报Out of MemoryMaven构建堆内存不足在IDEA里设置Maven的VM options为-Xmx1024m5.2 文件上传和附件路径的坑OA系统里经常涉及附件上传比如报销单上传发票图片、请假单上传病历证明。源码里文件上传一般保存到服务器本地磁盘或者OSS配置在application.yml的ruoyi.profile参数ruoyi: profile: C:/oa/uploadPath如果上传文件后前端无法预览优先检查这个路径是否存在以及目录是否对应用户有写权限。另外本地调试时绝对不要把路径配成C:\Windows\System32这种系统目录权限不够会直接导致上传失败而且很难排查。5.3 时区、编码、字符集三兄弟时区、编码、字符集是Java Web系统三个最隐蔽的坑很多问题显示出来都很奇怪页面中文乱码JVM启动参数加-Dfile.encodingUTF-8数据库URL加characterEncodingutf8Linux下还要注意locale环境是zh_CN.UTF-8。时间显示差8小时MySQL连接串加serverTimezoneAsia/Shanghai前端如果处理UTC时间需要后端统一返回时间戳或者加JsonFormat(timezone GMT8)注解。导出Excel乱码前端下载blob流时需要指定responseType: blob后端返回时设置Content-Disposition的filename做URL编码。这些都是老生常谈但每次新环境部署都会遇到一遍建议直接抄进自己的检查清单里。5.4 审批流不按预期走的排查思路如果你改了流程定义但前端审批跳转不对不要急着一行行看代码按这个顺序排查第一确认流程定义表里的节点是否配置正确。打开biz_process_define表检查节点顺序、审批人角色、对应单据类型字段是否匹配。第二确认流程记录表里的数据是否脏了。如果之前测试时提交过同一张单据可能有残留的process_record数据导致查询当前节点时取到的是旧记录。清理测试数据后重试。第三断点跟踪service层接口。打断点在approve方法进入时查看currentRecord的nodeOrder和nextNode的字段值这时候基本能确定是数据问题还是代码问题。通常按这个思路走几分钟就能定位。审批流的逻辑本身并不复杂出错的原因九成都在数据上。6. 最后的实操心得整套系统跑通之后我个人最大的感受是这类Java OA源码的价值不在于代码本身有多牛而在于它把“企业里审批业务流程”这件事用技术手段完整地表达了出来。如果你是要做毕业设计把这条链路的业务逻辑和数据库设计说清楚答辩基本就稳了如果你是想在公司内部落地一套轻量审批系统花一个周末把源码读透、改好流程模板就能直接上线试用比从零开发快十倍。最后再分享一个很实用的技巧如果你后续要在OA系统里加新的审批类型比如“外出申请”不要复制粘贴修改原来的请假模块而是先理清楚哪些是通用能力流程记录、待办、通知哪些是业务差异表单字段、审批规则把通用的部分抽象出来复用新业务只写表单本身的CRUD。这套源码里的架构如果设计得好的话已经帮你把这一步做完了你只需要在数据库里加一张业务表、在代码里加一个对应的Controller和Service再给前端加一个表单页面一个新功能就能稳稳接上去。按这个思路去扩展你能越改越顺。本文还有配套的精品资源点击获取
返回列表