十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

SpringBoot OA办公系统设计与实现:从权限认证到审批流实战

SpringBoot OA办公系统设计与实现:从权限认证到审批流实战 2026年再做OA办公系统很多人第一反应是这不就是管理系统那点事儿吗但实际上OA恰恰是企业级后端设计里最锻炼人的业务场景——组织架构、权限模型、审批流、消息推送、文件流转、操作日志每一个模块拆开都能写一篇长文。我去年到今年陆续搭过两套基于SpringBoot的OA系统一套自用一套给客户交付踩了不少坑也沉淀了不少可复用的设计思路。这篇文章就把这套系统的设计与实现完整拆一遍从需求边界、技术选型到认证权限、审批引擎、消息与文件处理再到最后的部署上线按实际开发顺序来写适合正在做毕业设计、或者准备从零搭建企业办公系统的后端同学参考。先说清楚这套系统解决什么问题企业内部的请假审批、差旅报销、公文流转、公告通知、会议室预约、任务分派全部要在网页上完成而且要支持PC和移动端浏览器访问。技术栈上层出个架构图很简单但落到每个模块的实现细节需要注意的点比想象中多得多。1. 立项先别急着写代码OA系统的需求边界与模块划分做这类系统最容易犯的错就是一上来就建表、写CRUD。OA系统表面看是信息管理本质是流程驱动 组织协同如果不先把业务边界和角色关系理清楚后面改起来会非常痛苦。我建议开工前先花两三天时间做两件事画系统架构图、画核心流程图。1.1 用ProcessOn把角色-功能矩阵先定下来很多用户看到原型第一反应是再加个模块所以需求阶段就要把系统边界画死。你可以用ProcessOn画一张顶层架构图把系统拆成六大块基础管理用户、部门、职位、权限中心角色、菜单、按钮、审批中心流程定义、我的待办、我的已办、协同中心公告、日程、任务、文档中心上传、预览、分享、系统管理日志、字典、参数。每一块背后对应一个SpringBoot的模块包这个结构从后端代码层面也要一一对应方便后续维护。ProcessOn画图还有个额外价值它导出的图片可以直接放进系统需求说明书里。不少高校的毕业论文都要求此处插入系统架构图创业公司做技术方案评审也需要这玩意儿。架构图不需要画得多炫但一定要把数据流向画清楚——用户请求从前端路由进来经过SpringBoot的Controller层再经过Service层调用Mapper层访问数据库审批流引擎单独走一套Flowable的API消息推送走WebSocket通道这样一个闭环图比花里胡哨的3D立体图有用得多。1.2 核心流程梳理请假审批是OA的Hello World需求阶段必须把审批流抽出来单独设计。拿请假审批举例常见的流转是员工提交申请 - 直属主管审批 - 部门负责人审批 - 人事归档其中还可能包含驳回撤回转审加签这些特殊动作。这些动作如果在业务代码里硬编码状态字段来实现系统跑到后期基本没法维护——状态多了以后每个分支都要写if-else而且流程图一变代码就要跟着烂一次。所以从需求阶段就要想明白审批流是一个独立引擎不是OA系统里的一个普通CRUD模块。至于是用Flowable、Activiti还是自己写一个轻量状态机我放到第4节详细讲。这里先强调流程图必须画到状态 事件的粒度比如待审批 - 通过 - 已归档是一条链路待审批 - 驳回 - 已退回修改又是一条链路把这些动作画清楚后面引擎选型和表结构设计才会顺利。1.3 需求边界对照表哪些必须做哪些可以砍这节分享一张我实际用过的需求优先级表格项目正式开发前可以按这个思路和用户对齐模块优先级核心功能备注组织架构P0部门树、用户维护、职位管理权限分配的地基认证与权限P0登录、token、角色权限不做等于裸奔审批中心P0请假、报销、用章申请先用请假打通链路通知消息P1站内信、待办提醒有条件的上WebSocket文档中心P1文件上传、在线预览权限校验必须做会议室预约P2资源日历、时段冲突检测可以作为加分项考勤打卡P2上下班打卡、统计依赖硬件谨慎引入P0模块做不好系统没法用P1做不好体验差P2做不好最多被吐槽两句。我在实际交付中经常主动把P2砍掉或做成二期把精力留在审批和权限这两个核心上。说实话一套OA系统只要审批流和权限模型稳了其他模块都是时间问题。2. 2026年的SpringBoot工程应该怎么搭版本选型与骨架准备技术选型是个需要拍板的事。SpringBoot现在已经到了3.5.x但很多企业的存量项目还在2.7.x上躺着——这背后是javax和jakarta命名空间的分水岭还有其他第三方框架的兼容性问题。2026年做新项目我建议按下面的思路选型。2.1 SpringBoot 2.7.18还是3.5.x关键在于生态兼容先看一张对比表对比项SpringBoot 2.7.18SpringBoot 3.5.xJDK要求8 ~ 2117命名空间javax.*jakarta.*三方生态兼容性几乎无痛MyBatis-Plus、Flowable需用新版本性能稳定启动略快、GraalVM支持更好学习成本大多数教程都是这个版本网上部分老教程会踩坑如果做毕业设计或企业内部工具型OA我强烈建议选SpringBoot 2.7.18 JDK8/11的组合理由很简单教程多、踩坑少、兼容性强、也不会因为版本问题浪费大量时间。知道为什么2.7.18还能打比盲目追新更重要。如果要做长时间演进的产品且团队熟悉JDK17可以上3.5.x但要做好心理准备——网上那些基于javax的代码段不能直接抄。我实际开发中用的是2.7.18JDK1.8。用IDEA创建项目时遇到过不能使用JDK1.8的问题原因是新版IDEA内置的Spring Initializr对新项目的SpringBoot版本约束导致处理办法是手动修改pom.xml里的parent版本号或者直接到Spring Initializr官网选版本生成压缩包再导入。这个细节很多教程不会提但你迟早会撞上。2.2 基础工程的包结构与依赖清单单一工程按模块化包结构组织不用一开始就上微服务——OA系统老老实实单体应用就够了省掉一堆分布式麻烦。包结构这样划分com.company.oa ├── config // 全局配置跨域、拦截器、WebSocket ├── controller // 控制层按业务域分包 │ ├── auth │ ├── user │ ├── process │ └── document ├── service // 业务层接口 实现 ├── mapper // MyBatis数据访问层 ├── entity // 数据实体 ├── dto // 传输对象入参出参 ├── common // 通用工具、常量、统一返回体 └── handler // 全局异常处理依赖方面核心是starter-web、starter-security、mybatis-spring-boot-starter、mysql-connector-java、flowable-spring-boot-starter、hutool-all工具集、lombok、jjwt。这里有两个容易踩的坑第一hutool-all版本要选新不选旧老版本里一些工具方法在JDK8下会有坑比如TOTP算法在旧版本没有实现想要用两步验证直接升级到较新版本。第二不要一次性把engine-spring-boot-starter等Flowable相关依赖全部引入按需引入。Flowable只引入一个flowable-spring-boot-starter-process就能覆盖99%的审批场景引入一整套会导致启动时自动建几十张Activiti/Flowable的ACT_表数据库会变得很乱。2.3 yml配置里的学问多环境Profile才是标配不要写一个application.yml一把梭。真实项目至少拆成三个环境dev本地开发、test测试服、prod生产通过spring.profiles.active切换。配置最核心的内容包括数据源、Redis、文件存储路径和Flowable的配置项。spring: datasource: url: jdbc:mysql://localhost:3306/oa_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver servlet: multipart: max-file-size: 50MB max-request-size: 100MB flowable: database-schema-update: true async-executor-activate: false其中database-schema-update: true表示Flowable会自动建表本地开发省心但生产环境建议改成false用脚本方式管理。async-executor-activate建议先设成false不然Flowable的后台异步线程在开发时会打印大量日志干扰排查问题。3. 登录认证与权限控制从JWT到TOTP的实现链路OA系统的认证环节绝对不能省。很多校园类管理系统项目用简单的session或干脆不鉴权放到企业场景完全不合格。我这边用的是Spring Security JWT Redis作为主认证链路再对接TOTP实现账号密码动态口令的双因子认证这套组合兼顾了安全性和开发效率。3.1 为什么用JWT而不是传统的Session单服务器部署Session好像够用但OA系统前端会拆成PC端、移动端H5以后还可能接企业微信JWT无状态、跨域友好、与Spring Security集成方便这些特性更适合。JWT的缺点也很明显服务端不好主动失效——所以我把Token同时存在Redis里做登出时删除Redis中的key来实现伪失效既保留无状态优势又弥补了不可控的问题。3.2 Spring Security过滤器链与自定义登录接口Spring Security默认的登录流程走的是表单登录但这个默认行为在前后端分离项目里非常鸡肋。我的做法是开放/api/auth/login和/api/auth/refresh两个接口其余全部走JWT过滤器认证。核心代码是自定义一个JwtAuthenticationTokenFilter它继承OncePerRequestFilter在每个请求进来时解析请求头中的TokenComponent public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token request.getHeader(Authorization); if (StringUtils.hasText(token) token.startsWith(Bearer )) { token token.substring(7); String username JwtUtil.parseToken(token); if (username ! null SecurityContextHolder.getContext().getAuthentication() null) { UserDetails userDetails userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } }把这段代码放进SecurityConfig的过滤链中并配置/api/auth/**、/process/query/**等几个白名单路径其余接口全部要求登录。注意这类过滤器写法在2.7.18和3.x都是一样的但类所在包名不同2.x下很多类还在org.springframework.security.web.authentication包下到3.x变成jakarta.servlet相关内容写代码时留意一下IDEA自动补全的import来源。3.3 拦截器验证Token和过滤器验证Token的区别标题相关热词里一直在提SpringBoot拦截器验证token这里要把拦截器Interceptor和过滤器Filter的定位掰开说清楚。Filter是Servlet容器层面的东西所有请求都会经过它可以对静态资源、ajax请求一视同仁地处理Interceptor是SpringMVC层面的东西可以由addPathPatterns精确控制拦截哪些路径还能拿到HandlerMethod对象做细粒度方法级别权限判断。在我这套系统里两套都用了Filter承担Token合法性校验Interceptor承担接口操作权限校验比如判断当前用户是否拥有某个按钮权限没有就直接返回403。Interceptor的好处是它可以注入Spring容器中的Service去查询数据库做权限比对Filter里用Service会比较别扭。TOTP双因子认证这块网上现成的库很多比如Hutool的TOTP类可以生成和校验动态验证码。核心流程是用户在个人中心绑定手机号或邮箱时后端生成一个密钥Base32编码前端用谷歌身份验证器App扫码保存登录时除了密码还要填6位动态验证码后端用同密钥和时间窗口校验。这个功能加上以后OA系统的安全等级会高很多对外交付时也更有说服力。3.4 权限模型落地一套RBAC需要几张表OA系统的权限模型用标准的RBAC基于角色的访问控制就够了用户表、角色表、权限表加用户-角色关联表、角色-权限关联表。权限资源又分菜单权限和按钮权限两个粒度。接口返回给前端的菜单树需要带上code前端根据code控制按钮显隐后端在Interceptor里根据当前用户的权限code集合判断是否能调用某个接口。这套设计最核心的技巧是用户从数据库中加载出来的权限集合一定要缓存到Redis避免每个请求都去查用户角色、角色权限的关联查询。缓存key可以设计成login:user:permissions:{userId}登录时加载、修改角色时刷新、登出时删除。权限把缓存做上以后接口响应速度会明显提升。4. 审批流模块为什么我选了Flowable而不是从零造轮子审批流是OA系统的灵魂模块也是最容易做砸的部分。刚到项目时很多人第一反应是请假审批不就是换个状态字段吗等真的把驳回、追回、会签、转办、委派都做一遍就会明白审批流是一个独立的复杂子领域。我的取舍是不自研流程引擎直接用Flowable理由有四点4.1 自研状态机 vs Flowable引擎取舍分析维度自研状态机Flowable灵活性流程一变就要改代码流程定义用BPMN文件动态部署复杂度简单流程够用上手曲线陡一些会签/转办等高级功能自己实现非常痛苦引擎原生支持系统开销轻量引入一张ACT_表体系和引擎线程适合场景只有请假一种流程OA有5种以上流程如果你只需要一个请假申请自研状态机完全没问题代码还清爽但OA系统一定会演进到报销、用章、出差、采购审批——每种流程的拓扑都不一样用Flowable这类BPMN引擎可以把流程设计和业务代码解耦后续新增流程只需要画一个流程图并部署不用改Java代码这是最核心的价值。4.2 Flowable集成的基础套路三步走Flowable集成其实不复杂理解三个核心API就够了部署流程定义把.shop文件BPMN XML上传到系统调用repositoryService.createDeployment().addString(...).deploy()流程定义就注册进引擎了。启动流程实例用户提交申请时调用runtimeService.startProcessInstanceByKey(leave, businessKey, variables)variables中放入发起人、表单数据等。完成任务并推动节点审批人点击通过/驳回时调用taskService.complete(taskId, variables)引擎自动根据BPMN的连线SequenceFlow判断下个节点。一个请假流程的BPMN核心片段大概长这样process idleaveProcess name请假流程 startEvent idstartEvent/ userTask idmanagerTask name主管审批 flowable:assignee${managerUser}/ userTask idhrTask name人事归档 flowable:assignee${hrUser}/ endEvent idendEvent/ sequenceFlow sourceRefstartEvent targetRefmanagerTask/ sequenceFlow sourceRefmanagerTask targetRefhrTask conditionExpression xsi:typetFormalExpression ![CDATA[${approved true}]] /conditionExpression /sequenceFlow sequenceFlow sourceRefmanagerTask targetRefendEvent conditionExpression xsi:typetFormalExpression ![CDATA[${approved false}]] /conditionExpression /sequenceFlow /process启动流程时在variables里传入managerUser和hrUser引擎就知道第一个任务应该分配给谁。4.3 会签、驳回与撤回的实现思路Flowable原生支持的任务节点类型里普通UserTask用于单人审批bpmn:parallelGateway并行网关和bpmn:inclusiveGateway包容网关可以组合出会签场景。更省事的做法是直接用Flowable的多实例特性在UserTask里配置flowable:multiInstanceLoopCharacteristics并指定collection和elementVariable就能实现多个审批人依次审批全部通过才进入下一节点或任意一个通过即进入下一节点的效果。驳回和撤回我用的是更贴近业务的做法在流程变量里加approvalStatus标记驳回时不调用引擎的底层API而是用runtimeService.createChangeActivityStateBuilder().moveActivityIdTo(...)把一个任务节点挪回上一个节点——这个操作对应Flowable的ChangeActivityState迁移能力底层就是对当前活动节点做状态变更。刚开始用容易麻爪建议先在测试环境对单节点流程反复试验确认节点ID拼写正确再套到业务上。流程进度查询也是个常见需求。我的流程列表中总是要显示当前到哪个节点了这个可以通过taskService.createTaskQuery().processInstanceId(...)查当前活动任务再关联BPMN节点名称展示给用户没必要把整个历史轨迹全查出来。5. 站内消息与文件处理模块的工程化细节审批跑通了下一步就是让用户感知到有事要办。待办提醒和消息中心是OA使用率最高的功能之一文件模块则承担合同、附件、制度文档的流转。这两个模块看起来容易落地时细节很多。5.1 WebSocket还是SSEOA站内消息的推送选型OA系统里最典型的场景是用户A提交了一个请假申请用户B审批人的页面上应该实时弹出您有1条新的待办。实现实时推送的方案主要有两种WebSocket真正的全双工通道服务端可以主动推消息。SpringBoot里用spring-boot-starter-websocket很熟练就能上手但需要处理连接鉴权、心跳检测、离线消息补发。SSEServer-Sent Events基于HTTP的单向推送服务端往客户端推消息实现更轻浏览器兼容性也够用。内部OA场景建议用WebSocket因为后面除了消息提醒还可能做在线聊天和会议室状态同步。需要注意WebSocket握手时URL上带上token参数在HandshakeInterceptor中做鉴权连接建立后把userId - WebSocketSession的映射存在一个并发Map中消息推送时遍历该用户的session发送。用户不在线时消息不能丢——把消息先存数据库用户登录后查询未读列表。5.2 文件上传与预览存储策略和权限校验要连起来做文件模块不要把所有文件堆在一个文件夹里。按业务域分目录存储比如/upload/avatar/、/upload/process/、/upload/document/文件名用UUID改名原始文件名存数据库避免中文名和路径穿越问题。文件路径绝不能直接暴露在接口返回里应该返回一个带时效签名的下载地址后端在下载接口里校验当前用户是否有该文件的访问权限。在线预览方面PDF用浏览器原生embed或iframe就能看Office文档.docx/.xlsx稍微麻烦想省事就直接用浏览器内置的Office Viewer插件能力或者在后端用OnlyOffice/Zipkin那套太重性价比最高的方案还是转换成PDF再预览。实测下来用LibreOffice命令做转换是稳定可靠的libreoffice --headless --convert-to pdf --outdir /data/oa/convert /data/oa/upload/document/xxx.docx这条命令在服务器上跑转换几十MB的文档会有几秒延迟业务上可以做成异步文件上传后先生成任务转换完把结果路径写库前端轮询状态。5.3 全局过滤器处理上传PDF时的XSS攻击热词里反复出现全局过滤器处理上传PDF文件时XSS攻击这个需求其实是很多安全测试会卡的点。攻击者会构造一个含恶意JavaScript的PDF文件上传到系统如果系统直接把文件用浏览器打开且未做内容类型校验恶意脚本可能在同源策略下执行造成XSS。我的处理方案是三层防守第一层上传时校验Content-Type和魔数不信任前端传的MIME类型读取文件头字节判断真实文件类型。PDF文件头固定是%PDF开头以此确定文件类型。第二层下载时强制附件下载除预览场景外响应头加Content-Disposition: attachment避免浏览器直接解析执行。第三层通过过滤器统一清理请求参数自定义一个XssFilter继承OncePerRequestFilter对请求体中的JSON参数做HTML标签转义。注意这里不能用单一的全局字符串替换因为OA系统里有些字段比如富文本公告是要允许部分HTML的否则功能直接被搞瘫。合理的做法是提供一个SafeHtml之类的注解或白名单字段集合默认识别出危险标签script、iframe、object、embed并清除富文本字段走单独的白名单放行。简单说全局过滤器解决默认安全白名单解决合法业务不受影响。6. 前后端分离联调中的分页、跨域与接口规范SpringBoot后端写好了前端基于Vue3 Element Plus做了PC端管理界面。前后端分离的联调是项目中最耗时间的阶段这里有几个老生常谈但必须处理干净的点。6.1 MyBatis分页插件的正确姿势列表页翻页是躲不掉的。用MyBatis-Plus自带的IPage最省事如果只想用原生MyBatis就上PageHelper分页插件。用法非常固定先引入依赖然后配置拦截器Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }使用的时候PageApplyInfoVO page new Page(pageNum, pageSize); LambdaQueryWrapperApplyInfo wrapper Wrappers.lambdaQuery(); // 拼接查询条件 IPageApplyInfo applyPage applyInfoMapper.selectPage(page, wrapper); return Result.ok(new PageResult(applyPage.getRecords(), applyPage.getTotal()));分页插件使用时有一个常见坑不要对嵌套查询或带group by的复杂SQL套用自动分页分页插件会把原SQL包一层LIMIT导致数据错乱。OA系统的待办列表经常要join流程表这种场景建议单独手写count SQL和page SQL。6.2 统一返回体与全局异常处理前后端对接要约定一套统一的JSON结构我惯用的是ResultTpublic class ResultT { private Integer code; private String message; private T data; // 构造方法、setter/getter }业务异常通过自定义的BusinessException抛出被RestControllerAdvice全局捕获转换成对应的错误码。这样前端只需要处理一种数据结构——code为200时取data否则弹message。千万避免有的接口返回data是数组、有的返回对象、有的直接返回null但前端又要去取列表字段这种接口设计在联调时最容易吵架。6.3 跨域配置的三个细节前后端分离必然遇到CORS跨域资源共享。SpringBoot里配置CORS最简单的方法是写一个WebMvcConfigurerConfiguration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }细节有三处第一allowedOriginPatterns和allowCredentials同时配置时不能用allowedOrigins(*)否则浏览器会拒绝带cookie的请求第二预检请求OPTIONS必须放行不能拦截器一刀切拦截掉否则前端报CORS错误找半天都定位不了第三如果后面Nginx反向代理了后端服务跨域配置也可能要挪到Nginx层做SpringBoot那层加不加会影响排查方向。6.4 接口设计文档先行没有一台API文档管理工具前后端联调会变成灾难。搜狐的YApi或者开源的knife4j基于Swagger都行。我用knife4j只需要在SpringBoot里引入依赖然后配合注解把接口地址、入参、出参标注清楚前端就能根据swagger-ui页面自己调试。需要提醒一句OA系统的接口数量一多文档要按模块分组编排controller命名要和前端页面一一对应否则找接口的时间比写接口的时间还长。7. 部署上线与后续迭代Docker、多环境与版本升级注意点写完代码只是第一步。部署阶段我走了不少弯路这里直接分享一套已经验证过多次的部署方案以及SpringBoot项目在2.x到3.x演进中的关键差异。7.1 Docker部署SpringBoot应用一次构建处处运行开发完成后用Docker部署是最省心的方式。先把项目打成jar包写一个精简的DockerfileFROM eclipse-temurin:8-jre WORKDIR /app COPY target/oa-system.jar app.jar EXPOSE 8080 ENV TZAsia/Shanghai ENV SPRING_PROFILES_ACTIVEprod ENTRYPOINT [java, -jar, app.jar]再配一个docker-compose.yml把MySQL、Redis、后端服务一起编排起来version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: oa_system volumes: - /data/mysql:/var/lib/mysql ports: - 3306:3306 redis: image: redis:7 ports: - 6379:6379 oa-server: build: . ports: - 8080:8080 depends_on: - mysql - redis environment: SPRING_PROFILES_ACTIVE: prod部署时最常遇到的问题就是时区。容器默认是UTC时间数据库里存的时间和自己本地时间差8小时折腾半天才发现是容器时区问题。所以Dockerfile里显式加上ENV TZAsia/ShanghaiMySQL连接串里也加上serverTimezoneAsia/Shanghai这两个坑填上后时间问题基本绝迹。7.2 日志链路与线上排查系统上线后发现问题靠的还是日志。我在项目中集成了logback按天滚动切割每天一个日志文件同时搭配一套简单的ELKElasticsearch Logstash Kibana或Loki做集中查询。如果不想引入那么重的日志体系至少要做到两点第一在拦截器或Filter里对每个请求打印耗时日志格式固定为method|url|耗时|当前用户排查慢接口一搜就能看到。第二业务关键操作通过审批、驳回、删文件必须输出审计日志包括操作人、操作时间、操作对象、操作前后状态。OA系统非常依赖审计日志出了问题要能还原谁在什么时候做了什么。这个属于系统设计的一部分不是附加功能。7.3 SpringBoot从2.x升级到3.5.x的迁移要点如果你的项目未来要升级到3.x提前看清几个迁移点javax换成jakarta所有import javax.*的代码、第三方库都得换包括servlet、validation、annotation这些。JDK必须17及以上JDK8直接不支持IDEA里用JDK1.8启动3.x项目会报错。参数校验API变更javax.validation变成了jakarta.validationNotNull等注解包名变了。MyBatis-Plus、Flowable等中间件的适配版本老版本不兼容必须换对应的新版本。Spring Security默认配置有变化配置方式大体一致但要小调尤其过滤链写法。如果是一个稳定运行中的系统升级的收益不明显不建议为了升级而升级。2026年新项目可以直接3.5.x起步历史项目稳定优先。7.4 基于SpringBoot的OA项目的后续扩展方向OA系统开发完以后最容易延展的点有三个对接企业微信或钉钉实现移动审批、引入HanLP分词做知识库与公文检索、集成EMQX这类MQTT中间件实现智能硬件的数据接入比如会议室传感器状态联动。这些扩展在架构上都留好了口子——SpringBoot本来就是面向组件化集成的框架后面哪个方向业务需求最强烈就往哪个方向加模块即可。回到这个项目本身基于SpringBoot搭建OA系统并不算什么黑科技真正的价值在于把业务边界划分清楚、认证权限做扎实、审批流引擎用对、部署运维可落地这四件事做完整。如果你正在参考这篇文章做类似系统我的建议是直接用自己最熟悉的技术版本把第一版跑通把请假流程作为最优先的P0功能一边做一边补需求等核心模块稳定后自然会知道第二版该怎么优化。
返回列表