Java工作流管理系统(activity6.0)

article/2025/9/30 8:32:32

activity6.0工作流系统知识点文章

第一章 activity流程部署(自动部署与动态BPMN部署)
第二章 activity变量使用
第三章 activity权限控制(代办任务查询)
第四章 activity审核任务(签领、完成任务、跳过节点、新增节点、设置委托人)
第五章 activity节点任意跳转(包含多实例)
第六章 activity新增节点(包含多实例)
第七章 activity多实例节点
第八章 activity流程监听器在项目中使用
第九章 activity自定义增删查改


文章目录

  • activity6.0工作流系统知识点文章
  • 前言
  • 一、工作流管理系统
      • 1.部分源码功能分析
        • 1、动态创建bpmn,并创建流程实例
        • 2、查询代办任务
        • 3、审核任务(签领、任意跳过节点、新增节点、完成任务)
        • 4、历史流程数据查询
        • 5、激活或挂起
        • 6、修改节点办理人(代办)
      • 2.提供的接口方式
    • 2.业务系统对接工作流功能(工作流客户端)
      • 1.流程节点配置
      • 2.流程待办任务与审核页面
      • 3.流程监控(终止流程、跳过、增减节点、修改审批人等)
  • 三、测试用例
    • 发起流程->查询待办任务->审核(新增节点、跳过节点、多实例参数赋值)->获取历史流程信息
  • 参考资料


前言

提示:流程设计器相对比较专业,客户一般不会用,也使得程序复杂化,加大维护成本。通过业务系统实现配置节点,动态构建流程BPMN文件来代替流程设计器,操作简单易用。

	工作流只是协助进行业务流程管理,对业务系统的业务流程进行自动化管理。没有工作流管理系统对业务系统影响不大,只不过有了工作流可以更好的管理业务流程,提高系统的可扩展性。作为流程管理,工作流可以独立部署为独立程序,通过接口与业务系统进行对接。下面我分两部分进行分析,一个是工作流管理系统,另一个是业务系统对接工作流功能(也可称为工作流客户端)。

工作流系统核心功能:
1、动态创建bpmn,并创建流程实例
2、查询代办任务
3、审核任务(签领、任意跳过节点、新增节点、完成任务)
4、历史流程数据查询

业务系统对接工作流功能:
1、定义业务流程,配置流程节点
2、审核流程任务(查询代办任务,完成流程任务)
3、监控流程(对在运行中的流程终止、新增任务、跳过任务等)

程序实现方式:
为了简化流程,对工作流制定规则如下:
1、动态创建bpmn固定为:开始节点—用户节点—排它网关—满足下一个用户节点或不满足结束节点。如图:
在这里插入图片描述

备注:如果需要控制特殊流向,可通过任意跳转、新增节点等来实现。

2、用户节点关键属性(审核人、候选人、候选组),设置为全局参数,来实现用户数据权限。
2.1第一个节点为发起人,流程启动时自动完成(谁发起就作为发起人)。
2.1候选组(组内人员都看到,其中一个审核通过即完成)
2.3候选人只有一个审核人时为单实例节点,候选人有多个审核人为多实例节点
备注:不采用activity提供的用户与组功能,减少系统复杂度。

举个例子:
报销单据审批流程,配置如下:发起人–》经费来源部门–》领导审核

要求:“经费来源部门”节点,需要经费大于10万才需要经过它审核

  1. 当金额大于10万,传给工作流节点为:
    发起人–》经费来源部门–》领导审核
  2. 当金额小于等于10万,传给工作流节点为:
    发起人–》领导审核

在创建流程实例前确认金额,工作流客户端确认好流程节点,就完成基本流程实例。
如果流程已发起,可通过流程监控对现有的流程进行终止、新增节点、跳过节点等等。

那如果创建流程前不知道,该如何做呢?
可以通过任意跳过节点、新增节点等功能控制代码,实现特殊流程流向;
还不满足的,你还可以通过流程设计器进行设置,把bpmn放在resources\processes路径下即可,然后特殊处理(特殊情况,自行扩展)。


一、工作流管理系统

工作流管理系统是独立部署,通过接口为业务系统提供api。如果业务系统也为Java,可以考虑采用RMI,目前工作流管理系统就是采用rmi接口。

系统采用SpringBoot2.3.4+activity6.0,源码结构图如下:
在这里插入图片描述
备注:具体功能,有兴趣可以通过下载源码进行研究

1.部分源码功能分析

1、动态创建bpmn,并创建流程实例

// 创建bpmn文件并部署流程
public class BuildFlowDeploymentService {@Resource private RepositoryService repositoryService;@Resource private RuntimeService runtimeService;private static final Map<String, List<ProcessTask>> processKeyCache = Maps.newHashMap();
public String createFlowDeployment(StartProcessInput input) {log.info("开始动态创建部署流程...input = {}", input);String processId = input.getProcessDefineKey();if (processKeyCache.containsKey(processId)) {//如果配置节点一样,采用缓存配置文件,避免重复创建Set<ProcessTask> processTasks = Sets.newHashSet(processKeyCache.get(processId));Set<ProcessTask> newProcessTasks = Sets.newHashSet(input.getProcessTasks());Set<ProcessTask> diff = Sets.symmetricDifference(processTasks, newProcessTasks);if (CollectionUtils.isEmpty(diff)) return processId;processKeyCache.remove(processId);}// 1. 建立模型BpmnModel model = new BpmnModel();Process process = new Process();List<ActivitiListener> executionListeners = Lists.newArrayList(addTaskListener("start"),addTaskListener("end"));process.setExecutionListeners(executionListeners);model.addProcess(process);process.setId(processId);process.setName(input.getProcessName());process.setDocumentation(input.getProcessName());//拼接节点信息createFlowElement(process, input.getProcessTasks());//部署流程repositoryService.createDeployment().addBpmnModel(process.getId() + FILE_SUFFIX, model).name(process.getId() + "_deployment").deploy();//        createProcessBpmn(model, processId); 尽在测试时打印查看效果图使用,正式用时需要注释掉processKeyCache.put(processId, input.getProcessTasks());return processId;}
    // 流程启动,创建流程实例public String startFlow(StartProcessInput input) {Map<String, Object> vars = Maps.newHashMap();vars.putAll(input.getConditionExpression());//添加条件参数vars.put(VARS_TITLE, input.getTitle());vars.put(VARS_SEND_UNIT_NAME, input.getSendUnitName());vars.put(VARS_SEND_USER_NAME, input.getSendUserName());vars.put(VARS_TASK_UNIT_ID, input.getTaskUnitId());vars.put(VARS_USER_TASK_NAME, input.getUserTaskName());vars.put(VARS_PROCESS_DEFINITION_ID, input.getProcessDefinitionId());vars.put(VARS_SECONDARY_UNIT_ID, input.getSecondaryUnitId());vars.put(VARS_REMARK, input.getRemark());// ...自定义表单数据input.getCustomForm().forEach((key, val) -> vars.put(VARS_PREFIX_FORM_PROPERTY.concat(key), val));String businessId = input.getBusinessId() + SPLIT_COMMA + input.getSendId() + SPLIT_COMMA + input.getProcessDefinitionId();log.debug("businessId->[{}]", businessId);String processInstanceId = startProcessInstance(input.getAssignee(), input.getProcessDefineKey(),input.getClassPrefix(), businessId, vars);log.info("流程已启动, 入参信息[{}], 流程id[{}]", input, processInstanceId);setProcessName(processInstanceId, input.getProcessName());List<Task> tasks = findTaskByProcInsId(processInstanceId);if (CollectionUtils.isEmpty(tasks)) {log.error("流程配置不符合规则,设置第一个节点发起人");BusinessException.throwConstraintException("流程配置不符合规则,设置第一个节点发起人");}Task task = tasks.get(0);// 默认第一个节点发起人,永远存在值completeAutoClaimTask(task.getId(), input.getAssignee(), processInstanceId, input.getComment(), vars);log.info("任务[{}]已完成", task);return processInstanceId;}

备注:如果想了解更多内容,可查看《第一章 activity流程部署(自动部署与动态BPMN部署)》

2、查询代办任务

 /*** 获取待办列表*/public TodoTaskSearchOutput todoTaskSearch(TodoTaskSearchInput input) {TaskQuery taskQuery;//CandidateGroups、CandidateUser同时为空时,返回全部数据(流程监控)if (CollectionUtils.isEmpty(input.getCandidateGroups()) && Strings.isNullOrEmpty(input.getCandidateUser())) {taskQuery = taskService.createTaskQuery().includeProcessVariables().active().orderByTaskCreateTime();} else {if (CollectionUtils.isEmpty(input.getCandidateGroups()))throw BusinessException.withMessage(ErrorCode.ERR_10001, "角色不能为空");taskQuery = taskService.createTaskQuery()
//                .taskCandidateUser(input.getCandidateUser()).taskCandidateOrAssigned(input.getCandidateUser()).taskCandidateGroupIn(input.getCandidateGroups())//支持多个角色.includeProcessVariables().active().orderByTaskCreateTime();}// 设置查询条件taskQuery(taskQuery, input);long total = taskQuery.count();int page = Math.max(input.getPager().getPage() - 1, 0);List<Task> toClaimList = taskQuery.listPage(page * input.getPager().getSize(), input.getPager().getSize());//分页查询

备注:如果想了解更多内容,可查看《activity权限控制(代办任务查询)》

3、审核任务(签领、任意跳过节点、新增节点、完成任务)

@Transactionalpublic AuditTaskEndSearchOutput taskAudit(TaskAuditInput input) {Task task = workFlowService.getTask(input);if (task == null) throw BusinessException.with(ErrorCode.ERR_40103);log.info("任务[{}]已完成", task.getId());Map<String, Object> vars = taskAuditBuildVars(input);// 流程自带表单数据log.debug("流程自带表单数据 count = {}", input.getCustomData().size());input.getCustomData().forEach((k, v) -> vars.put(VARS_PREFIX_FORM_PROPERTY + k, v));log.info("开始为用户[{}]自动签领任务[{}]", input.getAssignee(), task.getId());workFlowService.claim(task.getId(), input.getAssignee());workFlowService.complete(task.getId(), input, vars);// 1、当审核不通过时,流程结束if (0 == input.getIsPass()) {taskNotPassService.activityCompleted(input.getId());return findAuditTaskEndSearchOutput(input);}// 2、下一个节点被删除或新增节点处理workFlowService.addOrJumpProcessTask(input);// 3、设置下一个节点委托人if (!Strings.isNullOrEmpty(input.getEntrustedAgent())) {UpdateTaskAgentInput agentInput = new UpdateTaskAgentInput();agentInput.setProcessInstanceId(input.getId());agentInput.setEntrustedAgent(input.getEntrustedAgent());agentInput.setOriginalHandler(input.getOriginalHandler());workFlowService.updateTaskAgent(agentInput);}return findAuditTaskEndSearchOutput(input);}

备注:如果想了解更多内容,可查看《activity审核任务(签领、任意跳过节点、新增节点、设置委托人、完成任务)》

4、历史流程数据查询

public FindHistoricTaskOutput findHistoricTask(ProcInsIdInput input) {FindHistoricTaskOutput result = new FindHistoricTaskOutput();List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery().processInstanceId(input.getId()).includeProcessVariables().includeTaskLocalVariables().orderByHistoricTaskInstanceStartTime().asc().list();if (CollectionUtils.isEmpty(hisTasks)) return result;
// 返回历史数据内容,这里省略

5、激活或挂起

代码如下(示例):

// 激活
runtimeService.activateProcessInstanceById(processId);// 挂起
runtimeService.suspendProcessInstanceById(processId);

6、修改节点办理人(代办)

代码如下(示例):

public void updateTaskAgent(UpdateTaskAgentInput input) {if (Strings.isNullOrEmpty(input.getEntrustedAgent())) return;Task task = taskService.createTaskQuery().processInstanceId(input.getProcessInstanceId()).singleResult();if (task == null) {log.debug("流程已结束,不需要再设置委托人");return;}log.debug("设置负责人或委托人");taskService.setAssignee(task.getId(), input.getEntrustedAgent());//委托人if (!Strings.isNullOrEmpty(input.getOriginalHandler()))taskService.setOwner(task.getId(), input.getOriginalHandler());}

2.提供的接口方式

1、RMI接口;
2、webservice服务接口

接口服务端RMI配置:

@Slf4j
@Configuration
public class RmiConfiguration implements InitializingBean {@Value("${app.rmi.registryPort}")private int registryPort;@Value("${app.rmi.servicePort}")private int servicePort;@Resource private IWorkflowEndPoint workflowPoint;@Beanpublic RmiServiceExporter workflowPointExporter() {return export(IWorkflowEndPoint.class, workflowPoint, "flow");}private RmiServiceExporter export(Class<?> serviceInterface, Object instance, String instanceName) {RmiServiceExporter exporter = new RmiServiceExporter();exporter.setServiceInterface(serviceInterface);exporter.setService(instance);exporter.setServiceName(instanceName);exporter.setRegistryPort(registryPort); //注册端口exporter.setServicePort(servicePort); //通讯端口return exporter;}@Overridepublic void afterPropertiesSet() {log.info("--------------RMI Server started@RegistryPort[{}], ServicePort[{}] ---------------------", registryPort, servicePort);}
}

以下提供接口类:

public interface IWorkflowEndPoint {/*** 启动流程*/ApiResult<String> startProcess(RmiCommand command);/*** 根据流程实例id删除流程实例*/ApiResult<String> deleteProcessInstance(RmiCommand command);/*** 开始审核任务(完成任务节点)*/ApiResult<String> taskAudit(RmiCommand command);/*** 判断流程是否即将结束(当前任务完成后结束)*/ApiResult<String> isProcessEnd(RmiCommand command);/*** 根据流程id,返回当前流程实例的历史数据*/ApiResult<String> findHistoricTask(RmiCommand command);/*** 根据业务id,返回所有历史数据并根据实例进行分组*/ApiResult<String> findMergeHisProcess(RmiCommand command);/*** 获取待办数量*/ApiResult<String> todoTaskTotal(RmiCommand command);/*** 待办列表左侧的快捷查询标签*/ApiResult<String> todoTaskQueryTags(RmiCommand command);/*** 获取待办列表*/ApiResult<String> todoTaskSearch(RmiCommand command);/*** 获取待办任务信息(审核人、候选组、单位等等)*/ApiResult<String> todoTaskInfo(RmiCommand command);/*** 获取已办--经办(曾经审核过)*/ApiResult<String> auditTaskSearch(RmiCommand command);/*** 发件(没有办理结束)*/ApiResult<String> processSendSearch(RmiCommand command);/*** 办结(办理结束)*/ApiResult<String> processEndSearch(RmiCommand command);/*** 办理激活或挂起*/ApiResult<String> activeOrSuspendProcess(RmiCommand command);/*** 修改节点办理人*/ApiResult<String> updateTaskAgent(RmiCommand command);/*** 添加节点为代办任务*/ApiResult<String> addUserTasks(RmiCommand command);/*** 自由跳转节点(跳过代办任务时需要)*/ApiResult<String> freeNodeJump(RmiCommand command);
}

2.业务系统对接工作流功能(工作流客户端)

提供截图以及备注,直观了解业务系统与工作流对接功能,这里只是简单介绍能做什么,重点在讲解工作流系统功能。

1.流程节点配置

在这里插入图片描述

备注:动态节点类型,用于程序控制该节点是否保留

2.流程待办任务与审核页面

首页可放一个提醒是否有代办任务
在这里插入图片描述
进入代办任务页面:
在这里插入图片描述
点击办理
在这里插入图片描述

3.流程监控(终止流程、跳过、增减节点、修改审批人等)

查看所有的待办任务,可以终止流程,提醒审核人等;
在这里插入图片描述
进入流程督办,可以对流程节点进行跳过、增减节点、修改审批人等
在这里插入图片描述

三、测试用例

发起流程->查询待办任务->审核(新增节点、跳过节点、多实例参数赋值)->获取历史流程信息

代码如下(示例):

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("localdev")
public class WorkFlowTestService{@Resource private WorkFlowApp workFlowApp;@Testpublic void setMngWorkflowService() {StartProcessInput input = new StartProcessInput();input.setProcessDefinitionId("leaveId");input.setProcessDefineKey("WF0007");input.setProcessName("测试请假流程");// 流程节点配置input.setProcessTasks(findTasks());input.setAssignee("ceshi");// 业务idinput.setBusinessId("businessId");// 业务需要,这个业务实现类前缀input.setClassPrefix("leave");// 单位,用于数据权限的控制,现在在哪个单位中input.setTaskUnitId(VARS_CURRENCY_UNIT_VALUE);input.setUserTaskName("节点1");input.setTitle("标题");input.setComment("备注");// 如果第二个节点为多实例时,需要传值Map<String, Object> map = Maps.newHashMap();List<String> assignList = Lists.newArrayList("multiUser1", "multiUser2", "multiUser3");map.put("assignList", assignList);map.put("loopCardinality", assignList.size());input.setConditionExpression(map);StartProcessOutput output = workFlowApp.startProcess(input);log.error("返回对象:{}", output);}/*** 从当前的待办任务直接跳转到多实例节点*/@Testpublic void jump_multi_test() {FreeNodeJumpInput input = new FreeNodeJumpInput();input.setProcessInstanceId("7");input.setTargetNodeId("taskId3");Map<String, Object> vars = Maps.newHashMap();vars.put("taskUnitId", "currencyUnitValue");List<String> assignList = Lists.newArrayList("addMultiUser1", "addMultiUser2");vars.put("assignList", assignList);vars.put("loopCardinality", assignList.size());input.setVars(vars);FreeNodeJumpOutput taskOutput = workFlowApp.freeNodeJump(input);System.out.println(taskOutput.getSendUserId());}// 历史数据查询@Testpublic void his_test() {String id = "7";ProcInsIdInput insIdInput = new ProcInsIdInput();insIdInput.setId(id);FindHistoricTaskOutput taskOutput = workFlowApp.findHistoricTask(insIdInput);System.out.println(taskOutput.getItems());}//执行任务@Testpublic void taskAudit_test() {TaskAuditInput input = new TaskAuditInput();input.setId("7");input.setIsPass(1);input.setAssignee("multiUser2");input.setIsUserForCurrentTask(true);
//        input.setCandidateGroups(Lists.newArrayList("startRole"));input.setTaskUnitId("currencyUnitValue");input.setHandleUnitName("节点multiUser2单位");input.setHandleUserName("节点multiUser2有用户");input.setNexTaskUnitId("currencyUnitValue");// 如果下一个节点为新增节点,需要设置下一个节点配置,setTaskModelList这里就是配置
//        input.setNexTaskName("新增节点");
//        input.setLastNodeId("taskId3");
//        input.setTaskModelList(findAddTasks());
//        input.setNextCandidateUser("mUser1,mUser2");
//        input.setNextCandidateGroups(Lists.newArrayList("roleEnd"));// 如果下一个节点为多实例节点
//        Map<String, Object> map = Maps.newHashMap();
//        List<String> assignList = Lists.newArrayList("multiUser1", "multiUser2", "multiUser3");
//        map.put("assignList", assignList);
//        map.put("loopCardinality", assignList.size());
//        input.setConditionExpression(map);AuditTaskEndSearchOutput output = workFlowApp.taskAudit(input);log.error("返回参数[{}]", output);}@Testpublic void isProcessEnd_test() {TaskAuditInput input = new TaskAuditInput();input.setId("7");input.setIsPass(1);input.setAssignee("multiUser3");input.setIsUserForCurrentTask(true);
//        input.setCandidateGroups(Lists.newArrayList("startRole"));input.setTaskUnitId("currencyUnitValue");input.setHandleUnitName("节点multiUser3单位");input.setHandleUserName("节点multiUser3有用户");input.setNexTaskUnitId("currencyUnitValue");input.setNexTaskName("节点2");ProcessEndOutput output = workFlowApp.isProcessEnd(input);log.info("节点是否完成:" + (output.getIsTaskCompleted() ? "是" : "否"));log.info("流程是否结束:" + (output.getIsProcessEnd() ? "是" : "否"));}//获取待办任务@Testpublic void todoTaskSearch_test() {TodoTaskSearchInput input = new TodoTaskSearchInput();input.setProcInsId("7");
//        input.setCandidateUser("user1");
//        input.setCandidateGroups(Lists.newArrayList("startRole"));TodoTaskSearchOutput output = workFlowApp.todoTaskSearch(input);log.info("返回参数[{}]", output.getItems());}/*** 测试数据*/private List<ProcessTask> findTasks() {List<ProcessTask> tasks = Lists.newArrayList();// 第一个(i = 1)节点固定为发起人for (int i = 1; i <= 4; i++) {ProcessTask task = new ProcessTask();task.setTaskId("taskId" + i);if (i == 2) {// 流程发起就确认通过率、并行等条件task.setMultiInstanceTask(true);MultiInstanceInput multiTask = new MultiInstanceInput();multiTask.setCompletionRatio(BigDecimal.valueOf(0.51));multiTask.setSequential(true);task.setMultiTask(multiTask);}if (i == 3) {task.setCandidateUser("2021001");}// 不是多实例与候选人,那默认就是根据组判断权限tasks.add(task);}return tasks;}private List<ProcessTask> findAddTasks() {List<ProcessTask> tasks = Lists.newArrayList();ProcessTask task = new ProcessTask();task.setTaskId("addTaskId1");// 流程发起就确认通过率、并行等条件task.setMultiInstanceTask(true);MultiInstanceInput multiTask = new MultiInstanceInput();multiTask.setCompletionRatio(BigDecimal.valueOf(0.51));multiTask.setSequential(false);task.setMultiTask(multiTask);tasks.add(task);return tasks;}}

参考资料

中文操作文档参考地址:
https://blog.csdn.net/Nought_Love/article/details/100081893


http://chatgpt.dhexx.cn/article/loMmp9ki.shtml

相关文章

JAVA实现一个工作流引擎

介绍 工作流是一种将一系列相关的任务和活动组织起来的技术&#xff0c;以便在企业或组织中自动化或半自动化地管理业务流程。工作流技术可以帮助企业或组织更好地管理和优化业务流程&#xff0c;提高生产效率和质量&#xff0c;降低成本和风险。 JAVA作为一种面向对象编程语…

Java 3个常用工作流引擎

一&#xff1a;Java工作流框架是一种用于设计、执行和管理工作流程的技术。以下是几个常见的Java工作流框架&#xff1a; Activiti&#xff1a;Activiti是一款流行的开源Java工作流引擎&#xff0c;它基于BPMN 2.0标准&#xff0c;支持复杂的工作流程设计和管理。Activiti具有高…

Java 流行的工作流引擎

Java 流行的工作流引擎 JBPM 工作流 JBPM 是一个Java业务流程管理系统&#xff0c;是JBoss中一款开源的工作流引擎&#xff0c;是一个轻量级的&#xff0c;使用BPMN 2规范可扩展的 工作流引擎&#xff0c;也是一个工作流管理系统&#xff0c;它可以运行在任何java环境&#x…

Java工作流有哪些?如何快速掌握Java技术

工作流是什么?工作流是指两个或两个以上的人&#xff0c;为了共同的目标&#xff0c;连续的以串行或并行的方式去完成某一业务。Java工作流就是一个基于Java开发的流程框架&#xff0c;是每一个参加郑州Java软件开发培训的学员需要掌握的入门知识。那么常见的Java工作流有哪些…

JAVA工作流

一、 什么是工作流 以请假为例&#xff0c;现在大多数公司的请假流程是这样的 员工打电话&#xff08;或网聊&#xff09;向上级提出请假申请——上级口头同意——上级将请假记录下来——月底将请假记录上交公司——公司将请假录入电脑 采用工作流技术的公司的请假流程是这样…

java工作流详解

什么是工作流&#xff1f; 工作流&#xff1a;两个或两个以上的人&#xff0c;为了共同的目标&#xff0c;连续的以串行或并行的方式去完成某一业务。 业务&#xff1a;工作流所指业务涵盖了与经营相关的活动。 串行或并行&#xff1a;业务中的步骤也许以一步接着一步的方式…

Java开源工作流框架对比

什么是工作流&#xff1f; 工作流&#xff0c;是指“业务​过程的部分或整体在​计算机应用环境下的自动化”。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。 在计算机中&#xff0c;工作流属于计算机支持的协同工作&#xff08;CSCW&#xff09;的一部分。 工作流…

极简 Java 工作流概念入门

1. 为什么需要工作流 假设我有一个请假需求&#xff0c;流程如下&#xff1a; 请假可以提交给我的上司&#xff0c;上司可以选择批准或者拒绝&#xff0c;无论批准还是拒绝&#xff0c;都会给我一个通知。 这个流程比较简单&#xff0c;我们很容易想到解决方案&#xff0c;不…

Java工作流详解(附6大工作流框架对比)

目录 1.什么是工作流 2.工作流应用场景 3.工作流实现方式 4.有哪些工作流框架? 5.1.Activiti6. 2.Flowable7. 3.Camunda8.4.jBPM9. 5.osworkflow&#xff0c;6.jflow. 10.工作流框架对比 什么是工作流工作流(Worklow) 工作流是对工作流程及其各操作步骤之间业务规则的…

smalldatetime类型

1、MS Sql Server 的smalldatetime 与datetime类型的区别 原来数据库字段为smalldatetime类型&#xff0c; update table set column 11:59:30 发现commit后db中的值为12:00:00 update table set column 11:59:29 发现commit后db中的值为11:59:00 原来smalldatetime是不存储秒…

SQL Server中smalldatetime的日期范围为何是[1900-01-01,2079-06-06]

本文目录列表&#xff1a; 1、SQL Server中的基准日期 2、smalldatetime的日期范围 3、smalldatetime的日期范围和无符号2字节整数的关系 4、总结语 5、参考清单列表 SQL Server中的基准日期 SQL Server 中针对datetime和smalldatetime这两个日期时间数据类型提供一个基准日期&…

smalldatetime mysql_SQL 中 date 与datetime的区别

潇潇雨雨 我们看看这几个数据库中(mysql、oracle和sqlserver)如何表示时间mysql数据库&#xff1a;它们分别是 date、datetime、time、timestamp和year。date &#xff1a;“yyyy-mm-dd”格式表示的日期值 time &#xff1a;“hh:mm:ss”格式表示的时间值 datetime&#xff1a;…

SQL datetime和smalldatetime区别

datetime 存储大小8个字节&#xff0c;精确到分后的3为小数&#xff0c;日期范围从1753 年 1 月 1 日到 9999 年 12 月 31 日&#xff1b;而 smalldatetime存储大小为4个字节&#xff0c;精确到分&#xff0c;日期范围从1900 年 1 月 1 日到 2079 年 6 月 6 日。 参考 http://m…

170406回顾-SQL Server的smalldatetime类型比较

在比较SQL Server的类型为smalldatetime字段时出现下面的错误:将 expression 转换为数据类型 smalldatetime 时出现算术溢出错误 正确的比较方法如下:将long型转换为时间格式的字符串,再与smalldatetime类型的字段比较 SELECT * FROM tablename WHERE EditFlag > 2017/…

【SQL Server】将字符串转换为 smalldatetime 数据类型时失败

如下图&#xff0c;我在执行下列语句时遇到了“将字符串转换为 smalldatetime 数据类型时失败”的报错 然后去搜了一下&#xff0c;原来是存储过程的问题,我看的是其他博主的解答&#xff08;但是还没有按照博主的方法实践过&#xff09;&#xff0c;内容详情有需要的自己去搜一…

android笔记1(activity跳转)

1.利用Android studio创建一个新项目&#xff0c;项目结构如下。 2.创建一个新的activity&#xff0c;用于跳转。 3.修改两个activity的布局&#xff0c;主activity中有一个输入文本框和一个按钮&#xff0c;实现点击按钮发送文本框的内容到第二个activity。第二个activity中有…

Activity 跳转的生命周期变化

1&#xff09;Activity1跳转到Activity2的生命周期流程 1.Activity1启动&#xff1a;Activity1: onCreate()Activity1: onStart()Activity1: onResume()2.点击按钮跳转到Activity2:Activity1: onPause()Activity2: onCreate()Activity2: onStart()Activity2: onResume()Activit…

android activity跳转生命周期,Android中从一个Activity跳转到另一个Activity所经历的生命周期........

凡是Android开发人员都知道“Activity”是非常重要的&#xff1b;对其该“Activity”生命周期相信大家也比较熟悉了。 这篇文章主要探讨的是“从一个Activity启动跳转到另一个Activity中&#xff0c;所经历的生命周期中的过程” 实例&#xff1a; 1、MainActivity 启动 Secon…

Android开发之Activity(实现Activity跳转)

文章目录 基本框架新建activity实现activity跳转 基本框架 首先&#xff0c;每当我们新建一个APP工程&#xff0c;AS都会默认为我们创建一系列文件&#xff0c;比如MainActivity.java&#xff0c;该activity就是用户打开APP时默认弹出的activity&#xff0c;且该类一定要继承自…

activity跳转

1. 显示跳转 <Buttonandroid:layout_width"wrap_content"android:layout_centerHorizontal"true"android:layout_marginTop"20dp"android:text"页面跳转"android:onClick"intentClick"android:layout_height"wrap_c…