前言
工作流思想在上世纪60年代就有人提出过;70年代就有人开始尝试,但是由于当时许多的限制,工作流一直没有成功的被实现;80年代才出现第一批成功的工作流系统;90年代工作流技术走向了第一个发展高峰期;90年代后至今工作流出现了很多版本,但是主旨还是不变的,为了使我们的工作变得更加高效。
通俗点,我们经常使用的OA系统上。关于一个材料的申报,又或者个人的请假。这些流程就属于工作流(工作审批流)。其中对于审批人和各个节点是可以动态操作的。
工作流可以通过数据库设计的形式实现,也可以使用第三方的框架Elsa,Workflow Core。本文使用第二种,并详细的介绍一下代码实现和json实现工作流程。
安装
使用Nuget包管理工具安装以下的包:
Workflow Core 3.10.0 核心包不解释
WorkflowCore.DSL 3.10.0 json或者yaml注入需要
WorkflowCore.Persistence.MySQL 持久化
文档
JSON / YAML Definitions - Workflow Core
https://workflow-core.readthedocs.io/en/latest/json-yaml/
WorkFlowCore 加载Json文件 - 编程代码 (cscoder.cn)
https://www.cscoder.cn/docs/dotnet-core-projects-workflow-core/workflow-core-json.html
例子
1、创建项目
控制台或者WebApi项目均可,这里拿WebApi项目举例。(版本用的是.net 6)
2、添加工步
工步文件需要继承StepBody。现在添加一个Hello.cs和Goodbye的工步,代码如下:
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespaceWorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
public classHello : StepBody
{
publicoverride ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Hello World!");
return ExecutionResult.Next();
}
}
}
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespaceWorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
public classGoodbye : StepBody
{
publicoverride ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Goodbye World!");
return ExecutionResult.Next();
}
}
}
3、添加工作流文件
工作流文件需要继承IWorkflow。现在开始添加:
using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.HelloWord.Steps;
namespaceWorkFlowCore_Test.WorkFlows.HelloWord
{
public classHelloWorldWorkflow : IWorkflow
{
publicstring Id => "HelloWorld";
publicint Version => 1;
publicvoidBuild(IWorkflowBuilder<object> builder)
{
builder
.StartWith<Hello>()
.Then<Goodbye>();
}
}
}
4、配置和启动
基本数据都准备好了之后,在项目启动文件进行一下配置。代码如下:
using Microsoft.AspNetCore.Mvc;
using System.Xml.Linq;
using WorkflowCore.Interface;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave;
using WorkFlowCore_Test.WorkFlows.HelloWord;
using WorkFlowCore_Test.WorkFlows.IfStatement;
using WorkFlowCore_Test.WorkFlows.IfStatement.Model;
using WorkFlowCore_Test.WorkFlows.Json.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision;
namespaceWorkFlowCore_Test
{
public classProgram
{
publicstaticvoidMain(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddLogging(); // WorkflowCore需要用到logging service
//持久化
builder.Services.AddWorkflow(cfg =>
{
cfg.UseMySQL("server=127.0.0.1;Database=Workflow;Uid=root;Pwd=xunpai123.", true, true);
});
builder.Services.AddWorkflowDSL();//用来注入json和yaml
var app = builder.Build();
//核心注入方法
UseWorkflow(app);
app.UseAuthorization();
app.MapControllers();
app.Run();
}
publicstaticvoidUseWorkflow(WebApplication app)
{
var host = app.Services.GetService<IWorkflowHost>();
#region 工步注册
//c#代码注册
host?.RegisterWorkflow<HelloWorldWorkflow>();
//json注册
#endregion
host?.Start();
// 通过DI获取IHostApplicationLifetime实例
var applicationLifetime = app.Services.GetService(typeof(IHostApplicationLifetime)) as IHostApplicationLifetime;
applicationLifetime?.ApplicationStopping.Register(() =>
{
host?.Stop();
});
}
}
}
这个时候我们添加api控制器进行调用这个helloworld的流程。代码如下:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.SimpleDecision;
namespaceWorkFlowCore_Test.Controllers
{
[Route("api/[controller]")]
[ApiController]
public classTestApiController : ControllerBase
{
private IWorkflowController WorkflowService;
private IWorkflowHost WorkflowHost;
publicTestApiController(IWorkflowController workflowService, IWorkflowHost workflowHost)
{
WorkflowService = workflowService;
WorkflowHost = workflowHost;
}
[Route("WorkFlowCoreTestDemo")]
[HttpGet]
publicstringWorkFlowCoreTestDemo()
{
//var initialData = new LeaveRequestData
//{
// RequestId = "11111",
// RequestMsg = "开始请假"
//};
//WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);
WorkflowService.StartWorkflow("HelloWorld");
return"true";
}
}
}
5、效果展示
启动后调用我们的控制器方法,然后观看console 的变化,如图:
6、请假单流程
请假单的流程创建的话需要用到等待的函数,等待管理员进行审核后进行下一步的操作。请假单的流程代码如下:
public classLeaveRequestData
{
publicstring RequestId { get; set; }
publicbool ManagerApproved { get; set; }
publicbool HRApproved { get; set; }
publicstring RequestMsg { get; set; }
}
using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision.Steps;
namespaceWorkFlowCore_Test.WorkFlows.AskForLeave
{
public classAskForLeaveWorkflow : IWorkflow<LeaveRequestData>
{
publicstring Id => "LeaveRequestWorkflow";
publicint Version => 1;
publicvoidBuild(IWorkflowBuilder<LeaveRequestData> builder)
{
builder.StartWith(context => Console.WriteLine("提交请假申请"))
.Activity("manage-audit", (data) => data.RequestMsg)
.Output(data => data.ManagerApproved, step => step.Result)
.Then<ManagerApprovalStep>().Input(step => step.AuditDataInfo, data => data)
.If(data => data.ManagerApproved)
.Do(then => then.StartWith(context => Console.WriteLine("经理审核")));
}
}
}
然后创建好之后,在启动文件进行注册一下:
host?.RegisterWorkflow<AskForLeaveWorkflow, LeaveRequestData>();
好了,接下来我们就可以用接口的形式进行模拟了。首先我们新增一个接口用来模拟申请请求代码如下:
[Route("WorkFlowCoreTestDemo")]
[HttpGet]
publicstringWorkFlowCoreTestDemo()
{
var initialData = new LeaveRequestData
{
RequestId = "11111",
RequestMsg = "开始请假"
};
WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);
//WorkflowService.StartWorkflow("HelloWorld");
return"true";
}
然后创建一个管理员的审批方法,用来审核通过或者拒绝。代码如下:
[Route("WorkFlowCoreTestDemo4")]
[HttpGet]
publicasync Task<string> WorkFlowCoreTestDemo4()
{
//获取待决活动
var approval = await WorkflowHost.GetPendingActivity("manage-audit", "worker1");
if (approval != null)
{
Console.WriteLine("需要批准的" + approval.Parameters);
//提交活动成功
await WorkflowHost.SubmitActivitySuccess(approval.Token, true);//true,代表审批通过。逻辑验证在步骤里面
}
return"请假工作流";
}
好了,这样就形成闭环了。大家可以在postman上请求测试一下,观察console的变化了。
7、json注入
最后就是json注入的方式了,这种方式也是目前我比较倾向的方式,和前端对接就很方便的。前端按照固定的格式给后端传入json数据,后端根据json数据解析工步进行开启工作流。
首先需要创建一个json文件,json文件代码如下:
{
"Id": "HelloWorldJson",
"Version": 1,
"Steps": [
{
"Id": "Hello",
"StepType": "",
"NextStepId": "Bye"
},
{
"Id": "Bye",
"StepType": ""
}
]
}
然后在启动文件配置,注入一下json工作流:
//json注册
var loader = app.Services.GetService<IDefinitionLoader>();
var json = System.IO.File.ReadAllText("WorkFlows/Json/JsonYaml.json");// 假设文件位于程序运行目录
// 【json注入时候,stepType写这个程序集的类名】获取并打印全限定名,包括程序集名称
//Type my classType = typeof(HelloWorldStep);
//string fullAssembly className = my classType.AssemblyQualifiedName;
loader?.LoadDefinition(json, Deserializers.Json);
到这里就可以了,创建一个api方法来调用看看:
[Route("WorkFlowCoreTestDemo6")]
[HttpGet]
publicstringWorkFlowCoreTestDemo6()
{
WorkflowHost.StartWorkflow("HelloWorldJson", 1, null);
return"";
}
到这里就可以实现json注入工作流了。不过细心的朋友就发现了,我给的json文件中的step的type为什么是空的呢?
是因为StepType取的是项目程序集工步的类名称,因为我的电脑项目和你们的项目不一样,所以这里没有写。
大家可以自行百度搜搜看,我这里还是放一下我的json例子吧。
{
"Id": "HelloWorldJson",
"Version": 1,
"Steps": [
{
"Id": "Hello",
"StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"NextStepId": "Bye"
},
{
"Id": "Bye",
"StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
}
]
}
总结
例子备注写的比较多,就不多赘述了。有问题的话就留言!
转自:黄金程序员
链接:cnblogs.com/BFMC/p/18233359
- EOF -
推荐阅读 点击标题可跳转
看完本文有收获?请转发分享给更多人
推荐关注「DotNet」,提升.Net技能
点赞和在看就是最大的支持❤️