activiti初次学习

news2024/11/18 2:39:36

源代码地址:https://gitee.com/ZSXYX/activiti.git​

1、安装插件

首先安装下图所示activiti,不确定是哪个插件有用的,有时间可排除下
在这里插入图片描述
在resources下创建一个文件夹:processes,右键,新建
在这里插入图片描述
生成:
在这里插入图片描述
选中act.bpmn20.xml右键
在这里插入图片描述
展示如下空白面板,右键画图
在这里插入图片描述
在这里插入图片描述

画图完毕,右键保存为act.png图片
在这里插入图片描述

2、配置流程引擎

接下来,我们连接数据库,在resources下新建activiti.cfg.xml在这里插入图片描述
文件内容如下:

<bean id="processEngineConfiguration"
          class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti?serverTimezone=GMT%2B8"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="root"/>
        <!-- activiti数据库表处理策略 -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>

3、创建表

接着:在数据库中新建一个数据库
在这里插入图片描述
执行如下图,在数据库中生成25张表:
在这里插入图片描述
表名如下:
在这里插入图片描述
具体表名:
在这里插入图片描述

生成25张表

代码如下:

  /**
     * 生成 activiti的数据库表
     */
	@Test
	public void testCreateDbTable() {
		//使用classpath下的activiti.cfg.xml中的配置创建processEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		System.out.println(processEngine);
	}

4、部署流程定义

在这里插入图片描述
代码如下:

    /**
     * 部署流程定义
     * 将上面在设计器中定义的流程部署到activiti数据库中,就是流程定义部署。
     * 通过调用activiti的api将流程定义的bpmn和png两个文件一个一个添加部署到activiti中,也可以将两个文件打成zip包进行部署。
     * 单个文件部署方式
     * 分别将bpmn文件和png图片文件部署。
	 * act_re_procdef :id 中会存在一个ProcessInstanceByKey  : act
     */
	@Test
	public void testDeployment(){
//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、得到RepositoryService实例
		RepositoryService repositoryService = processEngine.getRepositoryService();
//        3、使用RepositoryService进行部署
		Deployment deployment = repositoryService.createDeployment()
				.addClasspathResource("processes/act.bpmn20.xml") // 添加bpmn资源
				.addClasspathResource("processes/act.png")  // 添加png资源
				.name("请假申请流程")
				.deploy();
//        4、输出部署信息
		System.out.println("流程部署id:" + deployment.getId());
		System.out.println("流程部署名称:" + deployment.getName());
	}

运行后,会在数据库中生成一条:
在这里插入图片描述
如果你的activiti-spring-boot-starter是7.1.0.M5的话,多半就会报错,很明显sql少字段,这个应该是一个官方的BUG
如果运行报错:

Unknown column 'VERSION_' in 'field list'

解决方式:
在act_re_deployment 中添加两个字段:
VERSION_、PROJECT_RELEASE_VERSION_
在这里插入图片描述
2:
在这里插入图片描述

 /**
     * 3、启动流程实例
     * 针对该流程,启动一个流程表示发起一个新的出差申请单,这就相当于java类与java对象的关系,
     * 类定义好后需要new创建一个对象使用,当然可以new多个对象。对于请出差申请流程,张三发起一个出差申请单需要启动一个流程实例,
     * 出差申请单发起一个出差单也需要启动一个流程实例。
     */
	@Test
	public void testStartProcess(){
//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、获取RunTimeService
		RuntimeService runtimeService = processEngine.getRuntimeService();
		//启动流程的时候【动态设置每个步骤的执行人】,map的key值需要与Leave.bpmn中对应
		Map<String, Object> variables=new HashMap<String, Object>();
		variables.put("user1", "张三");
		variables.put("user2", "李四");
//        3、根据流程定义Id启动流程
		ProcessInstance processInstance = runtimeService
				.startProcessInstanceByKey("aaa","1005",variables);   //会在act_hi_varinst中新增两条数据
//        输出内容
		System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
		System.out.println("流程实例id:" + processInstance.getId());
		System.out.println("当前活动Id:" + processInstance.getActivityId());
	}

在这里插入图片描述

5、启动流程实例

在这里插入图片描述

代码如下:

   /**
     * 启动流程实例
     * 针对该流程,启动一个流程表示发起一个新的出差申请单,这就相当于java类与java对象的关系,
     * 类定义好后需要new创建一个对象使用,当然可以new多个对象。对于请出差申请流程,张三发起一个出差申请单需要启动一个流程实例,
     * 出差申请单发起一个出差单也需要启动一个流程实例。
     */
		@Test
	public void testStartProcess(){
//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、获取RunTimeService
		RuntimeService runtimeService = processEngine.getRuntimeService();
//        3、根据流程定义Id启动流程
		ProcessInstance processInstance = runtimeService
				.startProcessInstanceByKey("act","1001");
//        输出内容
		System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
		System.out.println("流程实例id:" + processInstance.getId());
		System.out.println("当前活动Id:" + processInstance.getActivityId());
	}

启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。会在库中生成:
Activiti的act_ru_execution中存储业务标识
在这里插入图片描述
说明:

流程实例执行,如果当前只有一个分支时,一个流程实例只有一条记录且执行表的主键id和流程实例id相同,如果当前有多个分支正在运行则该执行表中有多条记录,存在执行表的主键和流程实例id不相同的记录。不论当前有几个分支总会有一条记录的执行表的主键和流程实例id相同

一个流程实例运行完成,此表中与流程实例相关的记录删除。

SELECT * FROM act_ru_task #任务执行表,记录当前执行的任务
在这里插入图片描述
说明:启动流程实例,流程当前执行到第一个任务结点,此表会插入一条记录表示当前任务的执行情况,如果任务完成则记录删除。

SELECT * FROM act_ru_identitylink #任务参与者,记录当前参与任务的用户或组
在这里插入图片描述
SELECT * FROM act_hi_procinst #流程实例历史表
在这里插入图片描述
流程实例启动,会在此表插入一条记录,流程实例运行完成记录也不会删除。

SELECT * FROM act_hi_taskinst #任务历史表,记录所有任务
在这里插入图片描述
开始一个任务,不仅在act_ru_task表插入记录,也会在历史任务表插入一条记录,任务历史表的主键就是任务id,任务完成此表记录不删除。

SELECT * FROM act_hi_actinst #活动历史表,记录所有活动
在这里插入图片描述

在这里插入图片描述

6、查询流程实例

流程在运行过程中可以查询流程实例的状态,当前运行结点等信息。
在这里插入图片描述
代码如下:

  /**
     * 查询当前个人待执行的任务
     * 流程启动后,任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
     */
	@Test
	public void testFindPersonalTaskList() {
//        任务负责人
		String assignee = "zhangsan";
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        创建TaskService
		TaskService taskService = processEngine.getTaskService();
//        根据流程key 和 任务负责人 查询任务
		List<Task> list = taskService.createTaskQuery()
				.processDefinitionKey("act") //流程Key
				.taskAssignee(assignee)//只查询该任务负责人的任务
				.list();

		for (Task task : list) {

			System.out.println("流程实例id:" + task.getProcessInstanceId());
			System.out.println("任务id:" + task.getId());
			System.out.println("任务负责人:" + task.getAssignee());
			System.out.println("任务名称:" + task.getName());

		}
	}

需求:
在activiti实际应用时,查询流程实例列表时可能要显示出业务系统的一些相关信息,比如:查询当前运行的出差流程列表需要将出差单名称、出差天数等信息显示出来,出差天数等信息在业务系统中存在,而并没有在activiti数据库中存在,所以是无法通过activiti的api查询到出差天数等信息。
实现:
在查询流程实例时,通过businessKey(业务标识 )关联查询业务系统的出差单表,查询出出差天数等信息。
通过下面的代码就可以获取activiti中所对应实例保存的业务Key。而这个业务Key一般都会保存相关联的业务操作表的主键,再通过主键ID去查询业务信息,比如通过出差单的ID,去查询更多的请假信息(出差人,出差时间,出差天数,出差目的地等)
String businessKey = processInstance.getBusinessKey();
在activiti的act_ru_execution表,字段BUSINESS_KEY就是存放业务KEY的。

7、流程任务处理

任务负责人查询待办任务,选择任务进行处理,完成任务

//	任务负责人查询待办任务,选择任务进行处理,完成任务。
	@Test
	public void completTask(){
//        获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取taskService
		TaskService taskService = processEngine.getTaskService();

//        根据流程key 和 任务的负责人 查询任务
//        返回一个任务对象
		Task task = taskService.createTaskQuery()
				.processDefinitionKey("act") //流程Key
				.taskAssignee("zhangsan")  //要查询的负责人
				.singleResult();
//        完成任务,参数:任务id
		taskService.complete(task.getId());
	}

8、流程定义信息查询

查询流程相关信息,包含流程定义,流程部署,流程定义版本
在这里插入图片描述
结果:在这里插入图片描述
代码:

  // 完成任务
//	任务负责人查询待办任务,选择任务进行处理,完成任务。
	@Test
	public void completTask(){
//        获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取taskService
		TaskService taskService = processEngine.getTaskService();

//        根据流程key 和 任务的负责人 查询任务
//        返回一个任务对象
		Task task = taskService.createTaskQuery()
				.processDefinitionKey("act") //流程Key
				.taskAssignee("zhangsan")  //要查询的负责人
				.singleResult();
//        完成任务,参数:任务id
		taskService.complete(task.getId());
	}


    /**
     * 查询流程定义
     * 查询流程相关信息,包含流程定义,流程部署,流程定义版本
     */
	@Test
	public void queryProcessDefinition(){
		//        获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
//        得到ProcessDefinitionQuery 对象
		ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//          查询出当前所有的流程定义
//          条件:processDefinitionKey =evection
//          orderByProcessDefinitionVersion 按照版本排序
//        desc倒叙
//        list 返回集合
		List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("act")
				.orderByProcessDefinitionVersion()
				.desc()
				.list();
//      输出流程定义信息
		for (ProcessDefinition processDefinition : definitionList) {
			System.out.println("流程定义 id="+processDefinition.getId());
			System.out.println("流程定义 name="+processDefinition.getName());
			System.out.println("流程定义 key="+processDefinition.getKey());
			System.out.println("流程定义 Version="+processDefinition.getVersion());
			System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
		}

	}

9、 流程删除

在这里插入图片描述
在这里插入图片描述

### The error occurred while setting parameters
### SQL: delete from ACT_RE_PROCDEF where DEPLOYMENT_ID_ = ?
### Cause: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`activiti`.`act_ru_execution`, CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`))

说明:

使用repositoryService删除流程定义,历史表信息不会被删除

如果该流程定义下没有正在运行的流程,则可以用普通删除。

如果该流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。

先删除没有完成流程节点,最后就可以完全删除流程定义信息

项目开发中级联删除操作一般只开放给超级管理员使用.

疑问?
当使用了级联删除仍然失败,请大神赐教
在这里插入图片描述
错误日志:

Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`activiti`.`act_ru_execution`, CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`))
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916)
	at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:354)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
	... 78 more

相关代码:

	//流程删除
	@Test
	public void deleteDeployment() {
		// 流程部署id
		String deploymentId = "57501";

		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 通过流程引擎获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
		repositoryService.deleteDeployment(deploymentId);
		//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
		repositoryService.deleteDeployment(deploymentId, true);
	}

10 流程资源下载

现在我们的流程资源文件已经上传到数据库了,如果其他用户想要查看这些资源文件,可以从数据库中把资源文件下载到本地。

解决方案有:

jdbc对blob类型,clob类型数据读取出来,保存到文件目录

使用activiti的api来实现

使用commons-io.jar 解决IO的操作

引入commons-io依赖包

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

通过流程定义对象获取流程定义资源,获取bpmn和png
在这里插入图片描述
结果:
在这里插入图片描述
说明:

deploymentId为流程部署ID
resource_name为act_ge_bytearray表中NAME_列的值
使用repositoryService的getDeploymentResourceNames方法可以获取指定部署下得所有文件的名称
使用repositoryService的getResourceAsStream方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流
最后的将输入流中的图片资源进行输出。

代码:

  /**
     * 现在我们的流程资源文件已经上传到数据库了,如果其他用户想要查看这些资源文件,
     * 可以从数据库中把资源文件下载到本地。
     */
	@Test
	public void  queryBpmnFile() throws IOException {
//        1、得到引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
//        3、得到查询器:ProcessDefinitionQuery,设置查询条件,得到想要的流程定义
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey("act")
				.list();
//        4、通过流程定义信息,得到部署ID
		for (ProcessDefinition processDefinition: list) {
			String deploymentId = processDefinition.getDeploymentId();
//        5、通过repositoryService的方法,实现读取图片信息和bpmn信息
//        png图片的流
			InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
//        bpmn文件的流
			InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());
//        6、构造OutputStream流
			File file_png = new File("D:\\test\\act.bpmn20.xml");
			File file_bpmn = new File("D:\\test\\act.png");
			FileOutputStream bpmnOut = new FileOutputStream(file_bpmn);
			FileOutputStream pngOut = new FileOutputStream(file_png);
//        7、输入流,输出流的转换
			IOUtils.copy(pngInput, pngOut);
			IOUtils.copy(bpmnInput, bpmnOut);
//        8、关闭流
			pngOut.close();
			bpmnOut.close();
			pngInput.close();
			bpmnInput.close();
		}
	}

11流程历史信息的查看

即使流程定义已经删除了,流程执行的历史信息通过前面的分析,依然保存在activiti的act_hi_*相关的表中。所以我们还是可以查询流程执行的历史信息,可以通过HistoryService来查看相关的历史记录。
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述
代码:

 /**
     * 查看历史信息
     * 即使流程定义已经删除了,流程执行的历史信息通过前面的分析,依然保存在activiti的act_hi_*相关的表中。
     * 所以我们还是可以查询流程执行的历史信息,可以通过HistoryService来查看相关的历史记录。
     */
	@Test
	public void findHistoryInfo(){
//      获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取HistoryService
		HistoryService historyService = processEngine.getHistoryService();
//        获取 actinst表的查询对象
		HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//        查询 actinst表,条件:根据 InstanceId 查询
//        instanceQuery.processInstanceId("2501");
//        查询 actinst表,条件:根据 DefinitionId 查询
		instanceQuery.processDefinitionId("act:1:52504");
//        增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
		instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//        查询所有内容
		List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
//        输出
		for (HistoricActivityInstance hi : activityInstanceList) {
			System.out.println(hi.getActivityId());
			System.out.println(hi.getActivityName());
			System.out.println(hi.getProcessDefinitionId());
			System.out.println(hi.getProcessInstanceId());
			System.out.println("<==========================>");
		}
	}

12挂起、激活流程实例

某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。

流程定义可以对应多个流程实例

如:每月最后一天不处理出差申请,需要挂起这个流程定义下的流程实例

当有这种流程实例没有跑完的时候,如果已经被挂起,就不能继续处理了

只有当流程实例激活后,整个流程才能继续向下处理

全部流程实例挂起
操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:

流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。

测试多个实例,则可以再运行一次addBusinessKey,修改1002,表示另一个人发起出差流程申请
在这里插入图片描述
结果:在这里插入图片描述
在这里插入图片描述

再次执行:
在这里插入图片描述
在这里插入图片描述

操作数据库
act_ru_task

act_re_procdef

act_ru_execution

都修改了SUSPENSION_STATE_暂停状态
代码:

 /**
     * 全部流程实例挂起与激活
     * 全部流程实例挂起
     * 操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:
     * 流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。
     * 测试多个实例,则可以再运行一次addBusinessKey,修改1002,表示另一个人发起出差流程申请
     */
	@Test
	public void SuspendAllProcessInstance(){
//        获取流程引擎processEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
//        查询流程定义的对象
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().
				processDefinitionKey("act").
				list();
		for (ProcessDefinition processDefinition : list) {
//        得到当前流程定义的实例是否都为暂停状态
			boolean suspended = processDefinition.isSuspended();
//        流程定义id
			String processDefinitionId = processDefinition.getId();
//        判断是否为暂停
			if (suspended) {
//         如果是暂停,可以执行激活操作 ,参数1 :流程定义id ,参数2:是否激活,参数3:激活时间
				repositoryService.activateProcessDefinitionById(processDefinitionId,
						true,
						null
				);
				System.out.println("流程定义:" + processDefinitionId + ",已激活");
			} else {
//          如果是激活状态,可以暂停,参数1 :流程定义id ,参数2:是否暂停,参数3:暂停时间
				repositoryService.suspendProcessDefinitionById(processDefinitionId,
						true,
						null);
				System.out.println("流程定义:" + processDefinitionId + ",已挂起");
			}
		}

	}

13单个流程实例挂起

操作流程实例对象,针对单个流程执行挂起操作
act_hi_actinst,act_hi_identitylink,act_hi_procinst,act_hi_taskinst,act_ru_identitylink,act_ru_task,act_ru_execution这些表都有流程实例id,字段名都是PROC_INST_ID_,这里我使用act_ru_execution查询**
在这里插入图片描述
在这里插入图片描述
代码:

/**
	 * 单个流程实例挂起与激活
	 */
	@Test
	public void SuspendSingleProcessInstance(){
//        获取processEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        RuntimeService
		RuntimeService runtimeService = processEngine.getRuntimeService();
//        查询流程定义的对象
		ProcessInstance processInstance = runtimeService.
				createProcessInstanceQuery().
				processInstanceId("55001").
				singleResult();
//        得到当前流程定义的实例是否都为暂停状态
		boolean suspended = processInstance.isSuspended();
//        流程定义id
		String processDefinitionId = processInstance.getId();
//        判断是否为暂停
		if(suspended){
//         如果是暂停,可以执行激活操作 ,参数:流程定义id
			runtimeService.activateProcessInstanceById(processDefinitionId);
			System.out.println("流程定义:"+processDefinitionId+",已激活");
		}else{
//          如果是激活状态,可以暂停,参数:流程定义id
			runtimeService.suspendProcessInstanceById( processDefinitionId);
			System.out.println("流程定义:"+processDefinitionId+",已挂起");
		}

	}

14测试完成个人任务,测试暂停了流程实例,是否还可以继续

在这里插入图片描述
对于已完成的任务
在这里插入图片描述

对于新建的任务
在这里插入图片描述
代码:

    /**
     * 测试完成个人任务,测试暂停了流程实例,是否还可以继续下一步,会报错“Cannot complete a suspended task”
     */
	@Test
	public void completTask1(){
//        获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取操作任务的服务 TaskService
		TaskService taskService = processEngine.getTaskService();
//        完成任务,参数:流程实例id,完成zhangsan的任务
		Task task = taskService.createTaskQuery()
				.processInstanceId("77501")
				.taskAssignee("zhangsan")
				.singleResult();


		System.out.println("流程实例id="+task.getProcessInstanceId());
		System.out.println("任务Id="+task.getId());
		System.out.println("任务负责人="+task.getAssignee());
		System.out.println("任务名称="+task.getName());
		taskService.complete(task.getId());
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1594747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCHouse-C

一.概括 1.地域&#xff08;Region&#xff09; 地域&#xff08;Region&#xff09;指腾讯云数据仓库 TCHouse-C 物理服务器所在的地理区域。腾讯云不同地域之间网络完全隔离&#xff0c;购买后不能更换。&#xff08;地域一旦选定&#xff0c;购买后无法更改。&#xff09;…

L3 【哈工大_操作系统】操作系统启动

本节要点&#xff1a; 1、理解 OS 启动过程发生了什么&#xff0c;理解 OS 与 硬件 与 应用 之间的关系 2、本节讲解了 setup 模块 和 system 模块实现的功能 1、计算机上电时&#xff0c;操作系统在硬盘&#xff08;磁盘&#xff09;上&#xff0c;为了“取指执行”&#xff0…

IO流基本流

目录 什么是IO流 IO流的体系 字节流 FileOutputStream FileInputStream 字符集 字符流 FileReader FileWriter 字节流和字符流的使用场景 什么是IO流 内存不能永久化存储,程序停止,数据丢失,所以要添加一个存档功能,存储到硬盘的文件,我们要知道文件在哪里和如何传…

Jmeter配置服务器监控插件

1.安装插件管理器 插件官网地址&#xff1a;JMeter Plugins :: JMeter-Plugins.org 点击 Plugins Manager,如上图所示&#xff0c; &#xff0c;点击jar file下载“plugins-manager.jar”&#xff0c;下载后放到“jmeter\lib\ext”目录下&#xff0c;重启jmeter。 2.安装资源…

静电场中的导体与介质

静电场可能分布于填充了各种媒质的区域。虽然媒质宏观上保持电中性&#xff0c;但其内部的各种微观带电系统不可避免地会与静电场相互作用。 一般而言&#xff0c;媒质可分为三类&#xff1a;导体、介质(绝缘体)和半导体。在静电场中半导体特性与导体类似&#xff0c;因此仅就…

C# Window form 自定义控件的结构和设计(三)

C# Window form 自定义控件的结构和设计(三) 一、前面介绍了如何来创建第一个自定义的控件&#xff0c;以及一个测试程序。下面我们来看下如何在自定义控件中添加属性。 C#和其他.NET语言支持属性作为语言的第一类成员。把属性作为语言的基础属性有两点主要的有点&#xff1a…

Node.js 并发控制

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;它使得 JavaScript 可以脱离浏览器在服务器端运行。由于 Node.js 采用单线程异步非阻塞 I/O 模型&#xff0c;它的并发处理能力也是非常强大的。本文将详细介绍 Node.js 的并发原理、概念、图解、解决方案…

洛谷-P2089 烤鸡

P2089 烤鸡 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using namespace std; const int N30; //const int M1e3*310; const int Mpow(3,10); int n; int arr[N]; //存临时方案 int res; //存方案数 int ans[M][N]; //存所有方案//x表示当前到…

k8s:kubectl 命令设置简写启用自动补全功能

k8s&#xff1a;kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Kubernetes&#xff08;K8s&#xff09;是一个强大的容器编排平台&#xff0…

LangChain安装

安装步骤 1 安装Python环境 这里不介绍Python环境的配置&#xff0c;默认大家是已经安装并配置好Python运行环境的。 2 安装LangChain bash 复制代码 pip install langchain执行以上命令安装LangChain会默认安装LangChain的最新版本 3 测试安装结果 3.1 打印langchain版本…

如何获得easyrecovery软件密钥?2024最新学习步骤教程

如何获得easy recovery密钥&#xff1f;EasyRecovery是一款老牌的数据恢复软件&#xff0c;如果需要使用它来恢复数据&#xff0c;则需要购买密钥激活。然而&#xff0c;如果您只需要使用它一两次而不想花钱购买密钥&#xff0c;那么您可以使用免费的EasyRecovery密钥。请注意&…

贝乐虎儿歌v6.8.0解锁高级版亲子学习儿歌

软件介绍 贝乐虎儿歌免费版app&#xff0c;出自乐擎网络的创意工坊&#xff0c;专为孩子们雕琢了一系列富含创意的动画儿歌内容。这款app通过贝乐虎兄弟的可爱形象&#xff0c;让孩子们在愉快的观看中接触到各种儿歌和故事。不仅如此&#xff0c;app还巧妙地将古诗、英语等学习…

Java代码基础算法练习-求奇数和-2024.04.14

任务描述&#xff1a; 输入n个整数&#xff08;n从键盘输入&#xff0c;n>0&#xff0c;整数取值范围&#xff1a;0~1000&#xff09;&#xff0c;输出它们的奇数和。 任务要求&#xff1a; 代码示例&#xff1a; package April_2024;import java.util.Scanner;// 输入n个…

【Leetcode】1702. 修改后的最大二进制字符串

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个二进制字符串 b i n a r y binary binary &#xff0c;它仅有 0 0 0 或者 1 1 1 组成。你可以使用下面的操作任意次对它进行修改&#xff1a; 操作 1 &#xff1a;如果…

Nacos 入门篇---服务端如何处理客户端的服务注册请求?(三)

一、引言 ok呀&#xff0c;上个章节我们讲了Nacos客户端的服务自动注册&#xff0c;今天我们来看看服务端接收到了客户端的服务注册请求&#xff0c;服务端都做了哪些事情&#xff5e; 二、目录 目录 一、引言 二、目录 三、回顾上节内容&#xff1a; 四、Nacos 服务代码入…

Linux 网络排查命令

端口相关服务检查 netstat -ntpl|grep [$Port]说明&#xff1a;[$Port]为相应的端口号。 0.0.0.0代表本机上可用的任意地址。比如&#xff0c;0.0.0.0:80表示本机上所有地址的80端口。 tcp 0.0.0.0:80表示在所有的可用接口上监听TCP的80端口 如果返回结果为空&#xff0c;说明…

Java 入门教程||Java 关键字

Java 关键字 Java教程 - Java关键字 Java中的关键字完整列表 关键词是其含义由编程语言定义的词。 Java关键字和保留字&#xff1a; abstract class extends implements null strictfp true assert const false import package super try …

奥尔波特、卡特尔、大五人格的特质流派,预测你是内向还是外向

了解特质&#xff0c;可以预测人的行为&#xff0c;可以预测你的性格是内向还是外向。 特质论并不把人格分为绝对的类型&#xff0c;通常认为存在一些特质维度。人们之间的差异&#xff0c;就在于这些维度上表现程度的不同所形成的不同特质构型。 特质&#xff08;trait&…

Python数据结构与算法——算法(贪心算法、动态规划

贪心算法 介绍&#xff1a;贪心算法又称贪婪算法&#xff0c;是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;它所做出的是在某种意义上的局部最优解。 贪心算法并不保证会得到最优解&#xff0c;但…

发誓不在黄金周旅游,可惜管不住自己,看看景区可视化,觉悟了。

2023-10-04 23:29贝格前端工场 景区可视化大屏可以起到以下几个作用&#xff1a; 数据监控和分析&#xff1a;景区可视化大屏可以实时监控景区的各项数据指标&#xff0c;如游客数量、门票销售情况、景区设备运行状态等&#xff0c;通过可视化展示&#xff0c;管理人员可以快…