第20讲:若依生态插件与扩展——工作流、报表、支付与第三方登录
第20讲:若依生态插件与扩展——工作流、报表、支付与第三方登录
若依框架企业级实战指南 | 基于 RuoYi-Vue(v3.9.2)作者:码海忠航
一、若依生态概览
若依之所以在国内企业级开发中广受欢迎,不仅因为框架本身扎实,更因为围绕它形成了一个丰富的生态体系。当基础功能满足不了业务需求时,你不需要从零造轮子,直接集成现成方案即可。
官方扩展(若依官方维护):
|
|
|
|
| RuoYi-Flowable |
|
|
| RuoYi-Report |
|
|
| RuoYi-Cloud |
|
|
| RuoYi-App |
|
|
社区扩展(第三方维护,质量参差不齐):
-
• RuoYi-Pay:支付集成(支付宝、微信) -
• RuoYi-OAuth:第三方登录(JustAuth) -
• RuoYi-SMS:短信平台集成 -
• RuoYi-OSS:对象存储集成 -
• RuoYi-Gen-Plus:增强版代码生成器
选择建议:官方扩展优先考虑,稳定性和兼容性有保障;社区扩展使用前务必看Star数、最近更新时间、Issue活跃度,避免引入”烂尾项目”。本讲重点讲四个高频场景:工作流、报表、支付、第三方登录。
二、工作流集成(Flowable)
2.1 RuoYi-Flowable介绍
企业系统中,审批流程是最常见的需求之一。请假要审批、报销要审批、合同要审批——这些场景用硬编码实现,每次流程变更都要改代码、重新发布,维护成本极高。
RuoYi-Flowable 是若依官方的工作流扩展,基于 Flowable 6.x 引擎,核心特性:
-
• 内置流程设计器,拖拽式绘制流程图,无需手写XML -
• 完整支持 BPMN 2.0 规范,标准通用 -
• 提供流程部署、发起、审批、驳回、挂起等全套API -
• 与若依权限体系打通,审批人可直接关联系统用户和角色
2.2 典型应用场景
|
|
|
| 请假审批 |
|
| 报销审批 |
|
| 合同审批 |
|
| 采购审批 |
|
2.3 集成步骤
第一步,引入依赖。在 ruoyi-admin 的 pom.xml 中添加:
<dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>6.8.0</version></dependency>
第二步,配置Flowable。在 application.yml 中添加:
flowable:# 关闭定时任务引擎(不需要时)async-executor-activate:false# 流程定义文件位置process-definition-location-prefix:classpath*:/processes/# 自动部署流程database-schema-update:true
第三步,设计流程。通过内置的流程设计器(前端组件),拖拽节点绘制流程图。设计完成后导出BPMN XML文件,放入 resources/processes/ 目录,项目启动时会自动部署。
第四步,开发审批接口。核心代码示例:
@ServicepublicclassLeaveServiceImplimplementsILeaveService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;/** * 发起请假流程 */@Overridepublic String startLeaveProcess(LeaveApply apply) {// 保存请假申请 leaveMapper.insertLeave(apply);// 设置流程变量 Map<String, Object> variables = newHashMap<>(); variables.put("applicant", apply.getApplicant()); variables.put("days", apply.getDays());// 启动流程实例ProcessInstanceinstance= runtimeService.startProcessInstanceByKey("leaveProcess", apply.getId().toString(), variables);return instance.getId(); }/** * 审批通过 */@Overridepublicvoidapprove(String taskId, String comment) { taskService.addComment(taskId, null, "APPROVE", comment); taskService.complete(taskId); }/** * 审批驳回 */@Overridepublicvoidreject(String taskId, String comment) { taskService.addComment(taskId, null, "REJECT", comment);// 驳回到发起人 Map<String, Object> variables = newHashMap<>(); variables.put("approved", false); taskService.complete(taskId, variables); }}
关键点:流程变量(variables)是流程流转的”数据载体”,通过它可以实现条件分支——比如请假天数超过3天需要总经理审批,就是在排他网关上配置 ${days > 3} 的条件表达式。
三、报表集成
3.1 RuoYi-Report介绍
业务系统离不开报表。销售要看业绩报表、仓库要看库存报表、财务要看收支报表——如果每个报表都手写SQL + 前端图表,开发量巨大且难以维护。
RuoYi-Report 基于开源的 JimuReport(积木报表),核心优势:
-
• 在线设计报表,拖拽式操作,无需编码 -
• 支持复杂报表:分组报表、交叉报表、明细报表 -
• 内置多种图表:柱状图、折线图、饼图、雷达图等 -
• 支持导出Excel、PDF、Word -
• 可直接连接若依的数据源,SQL即查即用
3.2 典型应用场景
|
|
|
|
| 销售报表 |
|
|
| 库存报表 |
|
|
| 财务报表 |
|
|
| 自定义查询 |
|
|
3.3 集成步骤
第一步,引入依赖:
<dependency><groupId>com.jimureport</groupId><artifactId>spring-boot-starter-jimureport</artifactId><version>1.6.0</version></dependency>
第二步,配置数据源。积木报表默认使用若依的主数据源,在 application.yml 中添加:
jeecg:jmreport:# 是否开启认证(建议开启,与若依权限打通)open-auth:true# 自定义SQL白名单(安全防护)sql-white-list:-"select"-"from"-"where"
第三步,设计报表。访问 /jmreport 路径进入积木报表设计器,选择数据源、编写SQL、拖拽字段到画布,配置图表样式,保存即可。设计完成后生成报表ID,前端通过iframe嵌入:
<template> <iframe :src="reportUrl" frameborder="0" style="width:100%;height:800px;"></iframe></template><script>export default { data() { return { reportUrl: '/jmreport/view/' + this.reportId + '?token=' + this.getToken() } }}</script>
安全提醒:积木报表允许用户编写SQL,存在SQL注入风险。生产环境务必开启SQL白名单过滤,限制可执行的SQL类型。
四、支付集成
4.1 支付宝集成
企业系统接入支付是常见需求。以支付宝为例,核心步骤如下:
引入SDK:
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.38.157.ALL</version></dependency>
配置参数(application.yml):
alipay:app-id:你的AppIDprivate-key:你的应用私钥alipay-public-key:支付宝公钥gateway:https://openapi.alipay.com/gateway.donotify-url:https://yourdomain.com/api/pay/alipay/notifyreturn-url:https://yourdomain.com/pay/success
支付接口核心代码:
@ServicepublicclassAlipayServiceImplimplementsIPayService {@Value("${alipay.app-id}")private String appId;@Value("${alipay.private-key}")private String privateKey;@Value("${alipay.alipay-public-key}")private String alipayPublicKey;@Value("${alipay.gateway}")private String gateway;@Overridepublic String createOrder(String orderId, BigDecimal amount, String subject) {AlipayClientclient=newDefaultAlipayClient( gateway, appId, privateKey, "json", "UTF-8", alipayPublicKey, "RSA2");AlipayTradePagePayRequestrequest=newAlipayTradePagePayRequest(); request.setNotifyUrl(notifyUrl); request.setReturnUrl(returnUrl);// 构建业务参数JSONObjectbizContent=newJSONObject(); bizContent.put("out_trade_no", orderId); bizContent.put("total_amount", amount.toString()); bizContent.put("subject", subject); bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); request.setBizContent(bizContent.toString());// 返回支付表单HTML,前端直接渲染即可跳转支付return client.pageExecute(request).getBody(); }}
4.2 微信支付集成
微信支付的接入思路类似,引入SDK后调用统一下单接口:
<dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-java</artifactId><version>0.2.12</version></dependency>
核心流程:构建请求参数 → 调用统一下单API → 获取支付二维码或H5跳转链接 → 用户支付 → 接收异步回调通知 → 验签并更新订单状态。
4.3 统一支付接口设计
当系统需要同时支持支付宝和微信支付时,建议用策略模式做统一抽象,避免业务代码到处 if-else:
/** * 支付策略接口 */publicinterfacePayStrategy {/** 创建支付订单,返回支付凭证(表单HTML/二维码URL等) */ String createPayOrder(String orderId, BigDecimal amount, String subject);/** 处理异步回调 */booleanhandleNotify(HttpServletRequest request);/** 查询订单状态 */ PayStatus queryOrder(String orderId);}/** * 支付宝策略实现 */@Service@ConditionalOnProperty(name = "pay.type", havingValue = "alipay")publicclassAlipayStrategyimplementsPayStrategy { ... }/** * 微信支付策略实现 */@Service@ConditionalOnProperty(name = "pay.type", havingValue = "wechat")publicclassWechatPayStrategyimplementsPayStrategy { ... }/** * 支付上下文——对外统一入口 */@ServicepublicclassPayContext {@Autowiredprivate Map<String, PayStrategy> strategyMap;public PayStrategy getStrategy(String payType) {PayStrategystrategy= strategyMap.get(payType + "Strategy");if (strategy == null) {thrownewServiceException("不支持的支付方式: " + payType); }return strategy; }}
好处:新增支付渠道只需加一个实现类,业务代码完全不用改。这就是开闭原则的典型实践。
五、第三方登录
5.1 JustAuth集成
第三方登录(微信扫码登录、QQ登录、GitHub登录等)几乎是现代系统的标配。手动对接各家OAuth接口非常繁琐,JustAuth 是国内最流行的第三方登录SDK,一行代码搞定。
支持的第三方平台:GitHub、微信、QQ、钉钉、飞书、Gitee、微博、百度等,覆盖主流平台。
5.2 集成步骤
第一步,引入依赖:
<dependency><groupId>me.zhyd.oauth</groupId><artifactId>JustAuth</artifactId><version>2.1.6</version></dependency>
第二步,配置第三方应用。以GitHub为例,在GitHub Settings → Developer settings → OAuth Apps中创建应用,获取 Client ID 和 Client Secret,回调地址填写 https://yourdomain.com/auth/callback/github。
第三步,编写登录接口:
@RestController@RequestMapping("/auth")publicclassSocialLoginController {@Value("${justauth.github.client-id}")private String githubClientId;@Value("${justauth.github.client-secret}")private String githubClientSecret;@Value("${justauth.github.redirect-uri}")private String githubRedirectUri;/** * 获取第三方授权跳转地址 */@GetMapping("/render/{source}")public R<Map<String, String>> render(@PathVariable String source) {AuthRequestauthRequest= getAuthRequest(source);StringauthorizeUrl= authRequest.authorize(AuthStateUtils.createState()); Map<String, String> result = newHashMap<>(); result.put("authorizeUrl", authorizeUrl);return R.ok(result); }/** * 第三方授权回调 */@GetMapping("/callback/{source}")public R<?> callback(@PathVariable String source,@RequestParam String code,@RequestParam String state) {AuthRequestauthRequest= getAuthRequest(source);AuthResponseresponse= authRequest.login(callback);if (response.ok()) {AuthUserauthUser= (AuthUser) response.getData();// 根据第三方用户信息登录或绑定账号return handleSocialLogin(authUser, source); }return R.error("第三方登录失败"); }private AuthRequest getAuthRequest(String source) {switch (source) {case"github":returnnewAuthGithubRequest( AuthConfig.builder() .clientId(githubClientId) .clientSecret(githubClientSecret) .redirectUri(githubRedirectUri) .build());// 其他平台类似...default:thrownewServiceException("不支持的登录方式"); } }}
第四步,绑定已有账号。第三方登录返回的用户信息(头像、昵称)需要与若依系统用户关联。常见做法是在用户表中增加 social_id 和 social_source 字段,首次第三方登录时自动注册或引导绑定已有账号:
private R<?> handleSocialLogin(AuthUser authUser, String source) {// 查询是否已绑定系统用户SysUseruser= userService.selectUserBySocialId( authUser.getUuid(), source);if (user != null) {// 已绑定,直接登录Stringtoken= loginService.login( user.getUserName(), "", null);return R.ok(token); }// 未绑定,返回第三方用户信息,前端引导绑定 Map<String, String> info = newHashMap<>(); info.put("uuid", authUser.getUuid()); info.put("nickname", authUser.getNickname()); info.put("avatar", authUser.getAvatar()); info.put("source", source);return R.ok(info, "BIND_REQUIRED");}
六、其他常用扩展
除了上述四大场景,以下扩展在企业开发中也经常用到:
短信平台:阿里云短信和腾讯云短信是主流选择。若依的短信验证码功能可以基于 ruoyi-common 模块扩展一个 SmsService 接口,不同厂商实现不同策略,与前面支付集成的策略模式思路一致。
OSS对象存储:若依默认将文件存在本地服务器,生产环境建议切换到对象存储。阿里云OSS和MinIO是两个常用方案,只需实现若依的 ISysFileService 接口,将上传逻辑从本地文件系统改为OSS SDK调用即可。
消息队列:当系统需要异步处理(如发送邮件、生成报表、处理回调),RabbitMQ和Kafka是首选。若依项目中建议在 ruoyi-common 模块封装消息发送的通用组件,业务模块只需调用API,不直接依赖MQ客户端。
WebSocket实时通信:若依内置了WebSocket配置(WebSocketConfig),支持在线用户数统计等基础功能。如需扩展(如即时消息、实时通知),在此基础上增加消息处理器即可。
七、常见问题
|
|
|
| Flowable流程部署失败 |
processes/ 目录在classpath下;查看启动日志中的Flowable异常信息 |
| 积木报表SQL注入风险 |
|
| 支付宝沙箱环境连不上 |
openapi-sandbox.dl.alipaydev.com |
| 微信支付回调验签失败 |
|
| 第三方登录回调404 |
state 参数校验 |
| OSS上传超时 |
|
| 多个扩展依赖冲突 |
mvn dependency:tree 排查冲突版本;通过 <exclusions> 排除冲突依赖 |
小结
本讲系统梳理了若依生态中四个高频扩展场景:工作流解决审批流程问题,报表解决数据展示问题,支付解决商业变现问题,第三方登录解决用户接入问题。几个核心要点:
-
1. 优先选官方扩展,社区扩展务必评估活跃度后再引入 -
2. 策略模式是集成多渠道(支付、短信、OSS)的最佳实践,新增渠道只加实现不改业务 -
3. 安全意识不能丢——报表SQL白名单、支付回调验签、OAuth State防CSRF,每一步都要做好防护 -
4. 扩展不是越多越好,按需引入,避免项目臃肿
关注”码海忠航”,持续获取若依框架实战干货。有问题欢迎评论区交流,有问必答!
夜雨聆风