java中的工作流流程管理和流转思路

本文详细阐述了如何设计和实现一套灵活的流程管理系统,通过引入五个关键类:数据字典、流程、流程节点、流程流转规则和流程流转信息,使得流程的定制与流转变得简单可控。实现了对流程的定义、节点的跳转以及流转状态的跟踪,适用于各种审批流程的自动化处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做某个管理项目时,被要求实现一套流程管理,比如请假的申请审批流程等,在参考了很多资料,并和同事讨论后,得到了一个自主实现的流程管理。
 
  以下提供我的设计思路,知道了思路,实现起来就简单很多了。
 
  首先我设计了5个类来实现流程的自主设置,主要是对流程的定义和流程流转。
 
  
 
注:这是设计的图,并不是实现
 
Dictionary:数据字典,不多说,流程类型存在这里面
 
Flow:流程,即流程的定义,其中包括流程名称,描述,类型,启用时间,备注等;目前是通过判断某个类别的流程启用时间来进行判断当前流程是否启用的。
 
    一个类别只启用一个流程。所以只需要通过流程类别即可确定流程,并不要特定的状态字段。
 
FlowInfoMovingNode:流程节点,在分析流程流转的时候,我们发现,流转一步就相当于从一个节点跳到另一个节点,所以我们设计这个流程节点类来表示每一步。
 
    其中包括,所属流程,节点名称,节点描述,监听权限。
 
    解释下监听权限是什么. 由于我们做的大部分是审核的流程,所以每个节点都需要有个审核的过程才进入下一个节点,所以我们要这个handlerRole属性来确定这个节点究竟是什么权限来审核。我们也知道,审核一般是某个人审核,这个我们后面说。这里是规定某个权限,即可以审核这个节点的权限。
 
FlowInfoMovingRole:流程流转规则,为了解决从节点出来的各个分支,我们设计了这个流转规则,本来其实可以一起放到FlowInfoMovingNode中,但这样话无论从数据上    还是管理上来说都不如加流转规则方便清楚。FlowInfoMovingRole主要用来确定流转规则,比如某个节点通过了应该去哪个节点,某个节点没通过应该去哪个节点,这样无论是分支还是单支还是循环都可以通过相同的方式来进行设置。transition为变换规则,参照shiro验证权限的方式,我们也使用纯字符串格式来进行判断变换规则。
 
FlowInfoMoving:流程流转信息,这里是每一步流转信息的存放,基本在进行流程流转的过程中,都是通过此类,其中包括:所属节点(得到所属节点同时也就得到所属流      程),申请源(因为我们不知道申请源是什么,我们只是管流程是怎么运转的,其申请源跟我们没有任何关系,我们保存申请源的唯一标识,若是想在审核的过程中进行查看申请源信息,则可以请求在Flow中监听的Url(handlerUrl),来进行查看,我会把申请源的唯一标识当做参数传递到Url中)。
 
    由于这个是操作最频繁的,所以我来具体解释下这个类。
 
  以下为本人具体实现的类设计,属性字段均有注释进行解释:
 
 
复制代码
/**
 * 流程流转信息
 * @author lichao *
 */
@Entity
@Table(name = FlowInfoMoving.TABLE_NAME)
public class FlowInfoMoving extends BaseAuditEntity {
 
    private static final long  serialVersionUID = 1L;
 
    public static final String TABLE_NAME       = "t_flowInfoMoving";
 
    // 流程节点,标识此流转信息是流转到了哪个节点
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "node_id",nullable = true)
    private FlowInfoMovingNode node;
 
    // 申请源,具体申请信息的唯一标识
    @Column
    private Long               applyId;
 
    // 申请人,具体申请信息的申请人
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "applyuser_id",nullable = false)
    private User               applyUser;
 
    // 申请信息,具体申请信息的简要概述,由申请提供
    @Column(length = 50)
    @Size(max = 50)
    private String             discription;
 
    // 申请类别,即申请的流程的类型
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "flowtype_id",nullable = false)
    private Dictionary         applyType;
 
    // 变换的结果,即审核通过未通过等条件,此条件同FlowInfoMovingRole种的transition,
    // 但有一些区别,因为有添加待审核,已结束等其他信息条件
    @Column(length = 50)
    @Size(max = 50)
    private String             transition;
 
    // 处理信息,即审核信息,由审核人添加
    @Column(length = 100)
    @Size(max = 100)
    private String             handlerInfo;
 
    // 处理人,即此流转应该由谁来申请,由FlowInfoMovingNode中的handlerRole来进行筛选,
     //并由上一个节点的处理人来进行选择具体审核人。
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "handleruser_id",nullable = false)
    private User               handlerUser;
 
    // 此流转信息的状态,用于查询,0未审核,1已审核,2本申请已经结束
    @Column()
    private int                status;
 
  //getter...and setter....
 
}
复制代码
 
 
这样整个流程定义就结束了,我们可以自由设置流程的流程规则,来设置流程的流转方式。这样无论任何复杂的流程都可以进行自定义,并且可以随意的修改。
 
这样设计的结果首先是可以任意的自定义流程,其次是申请源不需要去管流程的流转了,只需要提交一份申请,其他的事情均由流程进行操作实现。
 
那么我们来看看一个流程是如何进行运转的。
 
 
 
1.首先通过一个接口来传递具体的一些申请信息。
 
2.通过接口中的getType()来确定是哪个流程
 
3.查询到开始的流程节点。
 
4.将开始的信息保存到流转信息中,并等待处理
 
5.由审核人处理,指定下一个审核人
 
6.通过处理结果来获得下一个流程节点
 
7.查找下一个节点
 
8.将这次的处理信息和下一个节点的信息保存到流转信息中,并等待处理
 
9.由审核人处理,这样一直循环知道流程结束
 
10.通过审核信息查找的下一个节点为null,则表示此流程已经结束,
 
11.将结束的信息保存到流程流转信息中
 
12.将整个流程流转的状态改为已结束。
 
 
 
首先是Applyable是怎么设计的:其实一个接口,用于提供一些申请的信息
 
 
复制代码
public interface Applyable {
 
    // 得到申请的id,与类别进行联合查询,用于确定具体是哪个流程
    Long getId();
 
    // 得到申请的类别,用于确定具体是哪类流程
    String getApplyType();
 
    // 得到变换条件,用于确定申请后的第一个步骤
    String getTransition();
 
    // 得到此次申请的描述
    String getDiscription();
 
    // 得到审批人,即第一个步骤由谁审批
    User getHandlerUser();
 
}
复制代码
 
 
然后是主要的控制流程流转和申请的接口
 
 
复制代码
/**
 * 
 *@Description:处理流程业务的Service
 *@Author:lichao
 *@Since:Oct 10, 201412:02:39 PM
 */
public interface FlowMainService {
 
    /**
     * 
     *@Description: 用于申请
     *@Author: lichao
     *@Since: Oct 10, 20143:19:07 PM
     *@param applyable
     *@return
     * @throws Exception 
     */
    public void applyFlow(Applyable applyable) throws Exception;
 
    /**
     * 
     *@Description: 查找当前所处的流转信息
     *@Author: medees
     *@Since: Oct 13, 20148:56:00 AM
     *@param applyid 申请源
     *@param applytype 申请类别
     *@return
     */
    public FlowInfoMoving findNowMoving(Long applyid,Dictionary applyType);
 
    /**
     * 
     *@Description: 查找某一流程下的所有走过的流程 按创建时间升序排序
     *@Author: lichao
     *@Since: Oct 13, 20141:46:54 PM
     *@param applyid 申请源
     *@param applytype 申请类别
     *@return
     */
    public List<FlowInfoMoving> findAllMoving(Long applyid,Dictionary applyType);
 
    /**
     * 
     *@Description: 获取所有变换条件
     *@Author: lichao
     *@Since: Oct 13, 20144:27:41 PM
     *@param nodeid 所处节点的id
     *@return
     */
    public List<String> findNextTransition(Long nodeid);
 
    /**
     * 
     *@Description: 得到此节点可以审核的所有用户
     *@Author: lichao
     *@Since: Oct 14, 201410:22:50 AM
     *@param nodeid 节点id
     *@param applyid 申请源
     *@param applyUserId 申请人id
     *@return
     */
    public List<User> findNextAppUser(Long nodeid,String transition,Long applyUserId);
 
    /**
     * 
     *@Description: 分页查询自己所审批的流程
     *@Author: lichao
     *@Since: Oct 14, 20141:39:50 PM
     *@return
     */
    public Page<FlowInfoMoving> findMyMoving(Pageable pageRequest);
 
    /**
     * 
     *@Description: 进行审核的方法
     *@Author: lichao
     *@Since: Oct 15, 20142:11:18 PM
     *@param moving
     * @throws Exception 如果审核出错则抛出异常
     */
    public boolean approval(FlowInfoMoving moving) throws Exception;
 
    /**
     * 
     *@Description: 查找一个流程的所有流转
     *@Author: lichao
     *@Since: Oct 16, 201411:04:03 AM
     *@param applyid
     *@param applytype
     *@return
     */
    public Page<FlowInfoMoving> findAllMoving(Long applyid,Long applytype,Pageable Pageable);
 
    /**
     * 
     *@Description: 重新申请
     *@Author: lichao
     *@Since: Oct 17, 20141:43:03 PM
     *@return
     */
    public void resetApply(Applyable applyable) throws Exception;
 
    /**
     * 
     *@Description: 是否需要重新申请
     *@Author: lichao
     *@Since: Oct 17, 20141:43:03 PM
     *@return
     */
    public boolean isNeedReset(Long applyid,Dictionary dic);
 
}
前 言 1 1 概 述 2 1.1 选题背景 2 1.2 组织结构 2 2 所用相关技术方法 3 2.1 工作流 3 2.1.1 什么叫工作流 3 2.1.2 工作流发展 3 2.1.3 工作流的优点 3 2.2 MVC工作模式 4 2.2.1 MVC设计思想 4 2.2.2 MVC的具体实现 5 2.2.3 MVC的不足 6 2.3 JSP技术介绍 6 2.3.1 JSP的运行原理 7 2.3.2 JSP的生命周期 8 2.3.3 ServletJavaBean技术介绍 8 2.3.4 Java 虚拟机 9 2.3.5 JSP访问SQL Server 2000数据库 9 2.4 数据库后台环境配置 10 2.5 系统开发工具简介 10 2.5.1 Dreamweaver 10 2.5.2 MyEclipse 10 2.5.3 Tomcat 11 2.5.4 SQL Server2000 11 2.5.5 chs_sql2ksp3 12 3 系统需求分析 13 3.1 系统功能分析 13 3.2 系统性能分析 13 3.3 系统方案的确定评价 13 4 系统总体设计 15 4.1 系统层次模块图 15 4.1.1 营业厅模块 15 4.1.2 收费管理模块 16 4.2 系统数据流程图 16 4.3 数据表设计 18 5 详细设计及编码 21 5.1 编写JAVABEAN 21 5.2 营业厅实现函数 21 5.3 收费厅主要的实现函数 22 5.4 JAVABEAN主要实现模块 22 5.4.1 中文字符格式的转换模块(Stringto.java) 22 5.4.2 自动生成验证码(Ran.java) 22 5.4.3 数据库的连接(ConnectionFactory.java) 23 5.4.4 数据库连接的关闭(DatabaseUtils.java)--只提供接口 23 5.4.5 密码修改模块(Common_fuction.java) 24 5.4.6 时间格式转换(timeBean.java) 24 5.4.7 数据统计(counthander.java) 25 5.4.8 营业厅的接口(luruaction.java) 27 5.4.9 营业厅的主要函数实现(luruhander.java) 28 5.4.10 收费厅的主要函数接口 32 5.5 管理员登陆模块 33 5.5.1 管理员登录 33 5.6 营业厅管理模块 36 5.6.1 Left.jsp页面 36 5.6.2 Work.jsp 40 5.6.3 customerlistinfo.jsp 41 5.6.4 allinfo.jsp 41 5.7 收费厅管理模块 42 5.7.1 Left.jsp 42 5.7.2 Work.jsp 43 5.7.3 Customerlistinfo.jsp 43 5.7.4 gongdan.jsp 43 6 系统测试与维护 45 6.1 测试目的 45 6.2 测试环境 45 6.3 系统测试 45 6.4 系统维护 45 7 开发难点与技术 46 7.1 主要程序实现的代码描述 46 7.1.1 验证码的自动生成 46 7.1.2 生成WORD工单 46 7.1.3 以一定的时间刷新页面 47 7.1.4 JSP中文问题的解决 47 7.2 在程序编码过程遇到的主要问题: 48 7.3 代码编写风格 49 7.4 我的不足: 49 结束语 50 致 谢 50
### Java 工作流引擎设计思路实现方案 Java 工作流引擎的核心目标是通过抽象封装业务流程,使开发者能够更高效地管理自动化复杂的业务逻辑。以下是关于工作流引擎的设计思路实现方法的具体探讨。 --- #### 1. **核心设计理念** - **状态驱动**:工作流本质上是一个状态机,其中每个任务或活动都可以视为一个状态[^3]。通过定义清晰的状态转换规则,可以有效描述业务流程的流转路径。 - **模块化结构**:为了增强可维护性扩展性,通常将工作流划分为多个独立的子模块,例如: - **节点定义**:表示具体的业务动作或任务。 - **执行上下文**:保存当前流程实例的相关数据变量。 - **调度平台**:负责协调不同节点之间的顺序执行。 - **事件监听器**:捕获并响应流程中的重要事件(如开始、结束、异常等)。 - **动态配置**:现代工作流引擎强调灵活性,允许用户在运行时修改流程定义而无需重启系统[^4]。这可以通过引入 JSON 或 YAML 文件作为外部配置文件来实现。 --- #### 2. **关键技术选型** ##### (1)后端框架 - **Spring Framework**:提供依赖注入、事务管理等功能,简化了复杂组件间的协作[^1]。 - **MyBatis**:作为一种 ORM 框架,它可以帮助我们将 SQL 查询语句与对象模型绑定起来,从而轻松访问数据库中的流程元数据。 ##### (2)持久化层 - 数据库表设计至关重要,主要包括以下几个方面: - **流程定义表**:存储预设好的流程模板信息。 - **实例记录表**:追踪正在运行或者已完成的各个流程实例。 - **日志审计表**:保留每次状态变更的历史痕迹以便后续查询分析。 ##### (3)构建工具 - 使用 Maven 来统一管理项目依赖项,并制定标准化的编译打包流程[^1]。 --- #### 3. **主要功能模块** ##### (1)流程解析器 该模块的主要职责是从指定格式(比如 BPMN XML)加载流程定义,并将其转化为内部可用的数据结构形式。在此过程中还需要校验语法合法性以及参数完整性。 ```java public class BpmnParser { public WorkflowDefinition parse(String bpmnXmlContent) throws ParseException { // 实际解析逻辑省略... return new WorkflowDefinition(); } } ``` ##### (2)任务分配策略 根据不同角色权限自动指派待办事项给相关人员。此部分可能涉及 LDAP/AD 集成以获取最新的组织架构信息。 ##### (3)通知提醒机制 当某个环节超期未完成时触发邮件/SMS等形式的通知消息提示责任人尽快处理。 ##### (4)统计报表生成 定期汇总各项指标数据绘制图表展示整体运营状况趋势变化情况。 --- #### 4. **典型应用场景下的实现细节** 假设我们要开发一套审批类 OA 系统,则可以从如下几个角度切入: - **初始页面渲染**:利用前端框架 Vue.js 展示可视化编辑界面让用户拖拽组建拼接出理想的审批链条; - **后台接口对接**:编写 Restful Api 控制器接收客户端提交过来的新建请求并将之存入对应队列等待下一步操作; - **异步回调处理**:每当上级领导同意之后立即告知下一位审核者继续往下推进直至最终归档结案为止; --- #### 5. **挑战与应对措施** 尽管采用成熟的第三方库能快速搭建原型验证概念可行性,但在面对高度定制化需求时常面临诸多难题,诸如性能瓶颈、兼容性冲突等问题亟待解决。因此建议采取渐进式的演进路线逐步完善产品形态。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值