2023最新版本Activiti7系列-流程中的任务

news2024/11/22 5:52:06

在这里插入图片描述

流程中的任务

1.用户任务

用户任务:用于定义流程中需要人工参与的任务。

用户任务可以在流程中创建并分配给特定的用户或用户组。当流程执行到用户任务时,流程将暂停,并等待相应的用户完成该任务。完成用户任务后,流程将继续执行。

用户任务可以有以下属性:

  • 名称:用户任务的名称,用于标识任务。
  • 分配人:用户任务分配给的具体用户或用户组。
  • 优先级:用户任务的优先级,用于确定任务的重要程度。
  • 截止日期:用户任务的截止日期,用于确定任务的完成期限。
  • 表单:用户任务需要填写的表单,用于指导用户完成任务。

在 Activiti7 中,可以使用 BPMN(业务流程建模与标记语言)来定义用户任务。以下是一个使用 Activiti7 定义用户任务的 BPMN 示例:

在这里插入图片描述

<process id="userTaskProcess" name="User Task Process" isExecutable="true">
  <startEvent id="startEvent" name="Start Event"></startEvent>
  <userTask id="userTask" name="User Task" activiti:assignee="user1"></userTask>
  <endEvent id="endEvent" name="End Event"></endEvent>
  <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="userTask"></sequenceFlow>
  <sequenceFlow id="flow2" sourceRef="userTask" targetRef="endEvent"></sequenceFlow>
</process>

在上述示例中,定义了一个名为 “User Task Process” 的流程,其中包含了一个用户任务 “User Task”,并将其分配给 “user1”。流程从 “Start Event” 开始,经过用户任务后,最终到达 “End Event”。

通过 Activiti7 用户任务,可以有效管理和跟踪流程中需要人工参与的任务,并提高流程的效率和可靠性。

部署流程后启动流程

@SpringBootTest
class Activiti7Demo02ApplicationTests {

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private TaskService taskService;

    private RepositoryService repositoryService;

    /**
     * 部署流程
     */
    @Test
    void deployFlow() {
        Deployment deploy = processEngine.getRepositoryService().createDeployment()
                .addClasspathResource("flow/user-task-demo.bpmn20.xml")
                .name("用户任务")
                .deploy();
        System.out.println(deploy.getId());
    }

    /**
     * 发起流程
     */
    @Test
    void startFlow(){
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceById("event-compensation:2:340003");
        String description = processInstance.getDescription();
        System.out.println("description = " + description);
        System.out.println("processInstance.getId() = " + processInstance.getId());
    }

}

act_ru_task可以看到我们定义的过期时间

在这里插入图片描述

然后我们也可以通过API来查询对应的任务信息

/**
 * 任务查询
 */
@Test
void queryTask(){
    Task task = taskService.createTaskQuery().taskId("342505").singleResult();
    System.out.println("task.getDescription() = " + task.getDescription());
    System.out.println("task.getDueDate() = " + task.getDueDate());
}

  这里需要注意dueDate属性只是标识该用户任务何时过期,但过期后不会自动完成。我们可以利用这个字段做相关的逻辑处理

2. 手动任务

  在Activiti 7中,手动任务是一种用户任务,需要人工干预才能完成的任务。手动任务不需要任何自动化逻辑,只需要一个人工干预的环节。

  手动任务可以用来引导用户参与流程的执行。当流程执行到手动任务时,流程将会暂停,直到有人手动完成该任务。

  手动任务可以有多种形式,比如填写表单、审批文件、上传附件等。根据实际需求,可以自定义手动任务的表单和处理逻辑。

在这里插入图片描述

在手动任务中我们通过executionListener来监听任务的执行

public class ManualTaskExecutionListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) {
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("当前的节点:"+currentFlowElement.getName());

    }
}

在这里插入图片描述
部署审批任务后手动任务是直接走过。而且在act_hi_taskinst中也不会有相关的记录信息
在这里插入图片描述

3. 接收任务

  接收任务手动任务类似,不同之处在于手动任务会直接通过,而接收任务则会停下来等待触发,只有被触发才会继续流转。Activiti7 中的接收任务用于在流程中等待特定的消息或事件的到来,然后继续流程的执行。接收任务可以看作是一个等待状态,直到接收到相关的消息或事件,然后流程会根据接收到的消息或事件继续向下执行。

在这里插入图片描述

然后我们正常的部署->启动->审批到了接收任务这个节点。在act_ru_task是没有对应的待办任务的。当是在act_ru_execution中是可以看到相关的执行实例的。

在这里插入图片描述

处理完线下的逻辑后我们就可以触发这个节点的执行了

/**
 * 触发接收任务
 */
@Test
public void test9() throws Exception{
    ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = engine.getRuntimeService();
    runtimeService.trigger("362502"); // 触发 接收任务
}

当然我们也可以在接收任务节点绑定相关的监听器来记录相关的信息

在这里插入图片描述

public class ReceiveTaskListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) {
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("当前任务节点:"+currentFlowElement.getName());
        System.out.println("接收任务节点已被触发...");
    }
}

触发任务后可以看到相关的日志信息

在这里插入图片描述

4. 服务任务

  服务任务是一种自动执行的活动,无须人工参与,可以通过调用Java代码实现自定义的业务逻辑。

4.1 基本应用

通过案例来介绍
在这里插入图片描述

  在服务任务中我们可以通过三种方式来设置对应的处理对象。

  • 通过activiti:class来指定Java类
  • 通过activiti:delegateExpression类使用委托表达式
  • 通过activiti:expression来使用UEL表达式

上面的案例中我们就可以使用这三种方式来处理:

在这里插入图片描述

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

然后对应的java类:

public class MyFirstDelegate implements JavaDelegate {
    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("服务任务1..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
    }
}

@Component
public class MySecondDelegate implements JavaDelegate {
    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("服务任务2..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
    }
}

@Component
public class MyThirdDelegate  {
    /**
     * 处理方法
     * @param execution
     */
    public void handleFun1(DelegateExecution execution) {
        System.out.println("服务任务3..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
    }
}

后面两种情况我们需要把对象注入到Spring容器中。第二种情况需要实现JavaDelegate接口。然后测试即可。

部署流程后的启动操作可以看到相关的日志信息

在这里插入图片描述

当然在通过UEL表达式处理的时候我们是可以声明相关的变量的。

@Component
public class MyThirdDelegate  {
    /**
     * 处理方法
     * @param execution
     */
    public void handleFun1(DelegateExecution execution,Integer age) {
        System.out.println("服务任务3..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
    }
}

比如上面的handleFun1中既有DelegateExecution也有自定义的Integer属性。这时我们在声明的时候就需要同步的声明

<serviceTask id="sid-185E2348-E3FC-437E-8DC1-E71A9750F507" 
             name="服务任务3" activiti:expression="${myThirdDelegate.handleFun1(execution,age)}">
</serviceTask>

上面的第一个参数是DelegateExecution在表达式中默认的名称是execution,第二个参数是当前流程实例中的名称为age的流程变量。

4.2 属性信息

  在针对服务任务的处理中,有时需要接收相关的属性信息。这块我们介绍下具体应该要如何的实现。首先针对的是需要传递的是常量信息或者是固定值的方式,比如下面的情况

/**
 * 自定义的委托类
 */
public class MyFirstDelegate implements JavaDelegate {

    @Setter
    private Expression name;

    @Setter
    private Expression age;

    @Setter
    private Expression desc;

    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("服务任务1..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
        System.out.println("name.getExpressionText() = " + name.getExpressionText());
        System.out.println("age.getExpressionText() = " + age.getExpressionText());
        System.out.println("desc.getExpressionText() = " + desc.getExpressionText());
        
    }
}

那么我们就可以通过class:field来指定

在这里插入图片描述

这块我们在class fields 中通过固定值的方式来绑定

在这里插入图片描述

具体的xml中的定义信息:

<serviceTask id="sid-33AB5184-9C6A-4061-A2BF-CF2E7272AFAF" name="服务任务1" activiti:class="com.boge.activit.delegate.MyFirstDelegate">
  <extensionElements>
    <activiti:field name="name">
      <activiti:string><![CDATA[波哥]]></activiti:string>
    </activiti:field>
    <activiti:field name="age">
      <activiti:string><![CDATA[18]]></activiti:string>
    </activiti:field>
    <activiti:field name="desc">
      <activiti:string><![CDATA[这是一个励志的故事]]></activiti:string>
    </activiti:field>
  </extensionElements>
</serviceTask>

启动流程后通过日志信息可以看到相关的数据获取到了

在这里插入图片描述

上面的例子中通过固定值的方式来处理显然不是太灵活。这时我们同样可以通过UEL表达式的方式来注入:

在这里插入图片描述

对应绑定的JavaDelegate类为:

public class MyFirstDelegate implements JavaDelegate {
    @Setter
    private Expression name;

    @Setter
    private Expression age;

    @Setter
    private Expression desc;

    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("服务任务1..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
        System.out.println("name.getExpressionText() = " + name.getExpressionText());
        System.out.println("age.getExpressionText() = " + age.getExpressionText());
        System.out.println("desc.getExpressionText() = " + desc.getExpressionText());
        System.out.println("name = " + name.getValue(execution));
        System.out.println("age = " + age.getValue(execution));
        System.out.println("desc = " + desc.getValue(execution));
    }
}

然后在绑定class field中我们设置相关的表达式:

在这里插入图片描述

然后我们在部署流程后发起流程实例。在进入该服务任务前我们需要设置相关的流程变量信息

/**
 * 发起流程
 */
@Test
void startFlow(){
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 启动流程实例的时候就需要绑定相关的流程变量
    Map<String,Object> map = new HashMap<>();
    map.put("name","boge3306");
    map.put("age",66);
    map.put("desc","服务任务的动态属性...");
    ProcessInstance processInstance = runtimeService
            .startProcessInstanceById("demo1:1:3",map);

}

触发JavaDelegate后可以看到相关的日志信息:
在这里插入图片描述

4.3 执行结果

  有些情况下我们在服务任务处理完相关业务后在下一个节点中也需要服务任务执行的返回值,这时可以通过服务执行的返回值处理,具体通过为服务任务定义的activiti:resultVariable属性设置为流程变量,它可以是新的流程变量,也可以是已经存在的流程变量。如果指定为已存在的流程变量,则流程变量的值会被服务执行的结果覆盖。如果不指定返回变量名,则服务任务的结果值将被忽略。

在这里插入图片描述

在服务任务中我们通过表达式来定义了${businessStu.getTotalScore()},并通过Result variable name来绑定方法的返回信息

<serviceTask id="sid-CF377576-9674-432F-B950-044EBD097E07" name="服务任务1" activiti:expression="${businessStu.getTotalScore()}" activiti:resultVariableName="totalScore">

然后对应的定义相关的Java类。并注入到Spring容器中。

@Component
public class BusinessStu {

    public Integer getTotalScore(){
        System.out.println("BusinessStu....执行了");
        return 999;
    }
}

然后在第二个服务任务中绑定JavaDelegate。并获取返回的信息

public class MySecondDelegate implements JavaDelegate {


    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("服务任务1..." + LocalDateTime.now().toString());
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement = " + currentFlowElement);
        Object totalScore = execution.getVariable("totalScore");
        System.out.println("totalScore = " + totalScore);
    }
}

流程执行后的日志输出
在这里插入图片描述

4.4 异常处理

  使用服务任务,当执行自定义逻辑时,经常需要捕获对应的业务异常,并在流程中进行处理。对于该问题,Activiti提供了多种解决方式。

  可以在服务任务或脚本任务的用户代码中抛出BPMN错误。可以在Java委托、脚本、表达式与委托表达式中,抛出特殊的FlowableException:BpmnError。引擎会捕获这个异常,并将其转发至合适的错误处理器,如错误边界事件或错误事件子流程。

public class MySecondDelegate implements JavaDelegate {


    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        try {
            System.out.println("服务任务1..." + LocalDateTime.now().toString());
            FlowElement currentFlowElement = execution.getCurrentFlowElement();
            System.out.println("currentFlowElement = " + currentFlowElement);
            Object totalScore = execution.getVariable("totalScore");
            System.out.println("totalScore = " + totalScore);
        } catch (Exception e) {
            throw new BpmnError("BusinessExceptionOccurred");
        }
    }
}

  在这个JavaDelegate类的execute()方法中,执行自定义业务逻辑发生异常时,抛出了BpmnError(加粗部分的代码),该构造函数的参数是业务错误代码,用于决定由哪个错误处理器来响应这个错误。
 需要注意的是,这种方式只适用于业务错误,需要通过流程中定义的错误边界事件或错误事件子流程进行处理。而技术上的错误应该使用其他异常类型,通常不在流程内部处理。

4.5 JavaDelegate中使用Activiti服务

  有的时候,需要在Java服务任务中使用Activiti7服务(例如调用活动(call activity)不满足需要的场景下,使用RuntimeService启动流程实例)。

    /**
     * 回调方法
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        RuntimeService runtimeService = Context.getProcessEngineConfiguration().getRuntimeService();
        runtimeService.startProcessInstanceById("myProcess");
    }

  在以上代码中,JavaDelegate类的execute()方法通过调用Context.getProcessEngineConfiguration()获取了RuntimeService服务,然后调用了其startProcessInstanceByKey(String processDefinitionKey)方法。可以通过这种方式访问所有Activiti服务的API。

5.脚本任务

  脚本任务(script task)是自动执行的活动。当流程执行到达脚本任务时,会执行相应的脚本。Activiti7 脚本任务的作用是允许开发者在工作流程中嵌入脚本语言的代码,以执行特定的任务。脚本任务可以使用多种脚本语言,如JavaScript、Groovy、Python等,根据具体需求选择合适的脚本语言。

脚本任务的主要作用包括:

  1. 执行复杂的业务逻辑:脚本任务可以执行复杂的计算、条件判断和数据处理等操作,以满足特定的业务需求。

  2. 数据转换和处理:脚本任务可以对输入的数据进行转换、处理和验证,以确保数据的有效性和一致性。

  3. 接口调用和集成:脚本任务可以调用外部系统的接口,实现与外部系统的集成和交互。

  4. 自定义行为和规则:脚本任务可以根据特定的业务规则和条件,执行自定义的行为和操作。

  5. 动态决策和流程控制:脚本任务可以根据动态的条件和数据,实现流程的动态决策和控制,以适应不同的业务场景。

总之,脚本任务是Activiti7中非常有用的工具,可以在工作流程中执行复杂的业务逻辑和操作,以实现灵活性和可扩展性。

在这里插入图片描述

在使用脚本任务时需要指定Script formatScript,其中,scriptFormat属性表示脚本格式,其值必须兼容JSR-223(Java平台的脚本语言)。Activiti支持三种脚本任务类型:javascript、groovy和juel。使用groovy需要单独的添加相关的依赖

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.4.16</version>
</dependency>

脚本的具体代码为
在这里插入图片描述

然后在启动流程中我们需要设置inputArray的这个流程变量。注意这个是一个Integer的数组哦

/**
 * 任务审批
 */
@Test
void completeTask(){
    Map<String,Object> map = new HashMap<>();
    map.put("inputArray",new Integer[]{1,2,3,4,5,6,7,8,9});
    taskService.complete("32505",map);
}

然后执行任务后可以看到相关的日志信息

在这里插入图片描述

6.邮件服务

6.1 开启邮箱设置

  以QQ邮箱为例我们需要设置开启相关的服务。设置–》账户 然后往下面找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务
在这里插入图片描述

 开启服务。并且记住相关的授权码信息:

在这里插入图片描述

这块我们需要记住对应的授权码信息。https://wx.mail.qq.com/list/readtemplate?name=app_intro.html#/agreement/authorizationCode 官方的说明信息

6.2 服务配置

  然后我们需要在自己的服务中配置对应的邮箱服务。
在这里插入图片描述

6.3 流程案例

  然后我们来绘制相关的流程图来讲解。

在这里插入图片描述

部署流程后启动实例我们在相关的邮箱账号中就可以接收到相关的邮件信息:
在这里插入图片描述

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

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

相关文章

系统架构设计师视频教程笔记

根据历年真题倒翻官方教程&#xff0c;发现好多内容没有&#xff0c;据说2022新版改动很大 既然是真题&#xff0c;肯定有参考价值&#xff0c;那就看看旧视频吧 考试分享 软考高级架构师&#xff0c;有用但不大【通过后分享】 up主公司要接政府项目&#xff0c;有考证需求 …

Spring:Annontation

Bean 配置注解Autowired 注解context:component-scan 标签 配置 在 Spring 中&#xff0c;配置 bean 实例一般使用 xml 配置方式或注解&#xff08;Annontation&#xff09; 方式进行配置。 注解 注解&#xff08;Annontation&#xff09;&#xff0c;是在原有代码和逻辑下通…

数据库字段变更监控平台设计开发

序&#xff1a; 在开发过程中&#xff0c;在值班解决客服问题时&#xff0c;在分析定位别人写的业务代码问题时&#xff0c;重点是不是自己写的代码&#xff0c;只看到了数据库中落库最终数据&#xff0c;并不知道业务逻辑问题发生时数据库表中当时数据情况&#xff1f;如果能知…

虚拟机 NAT模式联网 重启断网的解决方法

1、虚拟机NAT模式联网 这个博客写的很清楚:按照他的方法可以ping通www.baidu.com 三分钟完成虚拟机联网 小白看了都说好&#xff01;&#xff01;&#xff01; 虚拟机超详细联网教程/步骤 SDN软件定义网络实验_虚拟机联网教程_九号迷妹的博客-CSDN博客 但是虚拟机重启几次之后…

九种分布式ID解决方案,总有一款适合你!

1、UUID 2、数据库自增ID 2.1、主键表 2.2、ID自增步长设置 3、号段模式 4、Redis INCR 5、雪花算法 6、美团(Leaf) 7、百度(Uidgenerator) 8、滴滴(TinyID) 总结比较 背景 在复杂的分布式系统中&#xff0c;往往需要对大量的数据进行唯一标识&#xff0c;比如在对…

2023牛客暑期多校训练营3

A.World Fragments I 将两个二进制数先转换成十进制数,因为只要二进制中有1,就加或减1(加减0是没有用的),所以求两个二进制的差的绝对值(这是在有1的情况下,其实只要不等于0就有1,数是非负整数) 所以需要特判,如果第一个二进制数为0,第二个二进制数不为0,那么就不能转化,输出…

甄云质量管理解决方案——插上数字“羽翼”,实现PPAP落地

导语 质量管理是供应链管理中非常重要的一环&#xff0c;通过制定和开展质量相关的活动&#xff0c;确保产品符合质量标准和一致性要求。质量管理水平的高低直接影响供应链的整体效率和最终效益&#xff0c;关乎企业形象和品牌声誉&#xff0c;已然是企业的生命线。 作为采购…

Redis超详细入门教程(基础篇)

目录 一、什么是Redis 二、安装Redis 1、Windows系统安装 2、Linux系统安装 三、Redis通用命令 四、Redis基本命令 五、五种数据结构类型 5.1、String类型 5.2、List集合类型 5.3、Set集合类型 5.4、Hash集合类型 5.5、Zset有序集合类型 六、总结 一、什么是Redi…

leecode 98验证二叉搜索树

​​​​ 这次的性能真的是超乎想象的好 题目描述 98二叉树 第一种方法 中序遍历 大体的思想就是将遍历的结果存放到数组中 检查数组是否是有序 判断是否符合条件 特点是时间和空间消耗都很大 /*** Definition for a binary tree node.* struct TreeNode {* int val;*…

常见面试题之设计模式--工厂方法模式

1. 概述 需求&#xff1a;设计一个咖啡店点餐系统。 设计一个咖啡类&#xff08;Coffee&#xff09;&#xff0c;并定义其两个子类&#xff08;美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】&#xff09;&#xff1b;再设计一个咖啡店类&#xff08;CoffeeStore&…

DAY51:动态规划(十五)买卖股票最佳时机Ⅲ+买卖股票最佳时期Ⅳ

文章目录 123.买卖股票最佳时机Ⅲ&#xff08;注意初始化&#xff09;思路DP数组含义递推公式初始化遍历顺序最开始的写法&#xff1a;初始化全部写成0debug测试&#xff1a;解答错误&#xff0c;第0天实际上是对应prices[0]和dp[0] 完整版总结 188.买卖股票最佳时机Ⅳ思路DP数…

【wxWidgets】剪贴板和拖放操作

【wxWidgets】剪贴板和拖放操作 使用剪贴板传输数据时应用程序间的一种交互方式 剪贴板和拖放操作在wxWidgets中共享了一些类来实现数据的传输 数据对象 wxDataObject类时剪贴板操作和拖放操作的核心&#xff0c;该类实例代表了拖放操作中鼠标拖拽的事物和剪贴板中拷贝和粘贴…

【git学习2】多人合作中git的使用

提交代码 中间打勾&#xff1a;commit提交代码 最后点击向上的箭头 push到远程仓库。 团队开发中git的使用 第一步先从远程仓库中某个分支拉下来代码&#xff0c;比如下图只有一个分支master 新建文件夹&#xff0c;存放这个拉下来的项目&#xff0c;克隆项目地址&#xff…

JDK8版本接口的改进(heima)

JDK8版本接口的改进&#xff08;heima&#xff09; public class InterfaceTest1 {/*JDK8版本接口改进1.允许编写带有方法体的方法&#xff08;默认方法&#xff09;2.允许编写静态方法目的&#xff1a;解决接口的升级问题---------------------------------------注意事项&…

HDFS的设计目标和重要特性

HDFS的设计目标和重要特性 设计目标HDFS重要特性主从架构分块存储机制副本机制namespace元数据管理数据块存储 设计目标 硬件故障(Hardware Failure)是常态&#xff0c;HDFS可能有成百上千的服务器组成&#xff0c;每一个组件都有可能出现故障。因此古见检测和自动快速恢复的H…

基本数据类型和引用数据类型

数据类型的分类 java中的 变量 按照数据类型来分类&#xff1a; Java语言是 强 类型语言&#xff0c;对于每一种数据都给出了明确的数据类型&#xff0c;不同的数据类型也分配了不同的内存空间&#xff0c;所以它们表示的数据大小也是不一样的。基本数据类型&#xff08;4类8种…

[Python] flask运行+wsgi切换生产环境+supervisor配置指南

文章目录 问题背景flask启动方式1&#xff08;编写main函数&#xff09;&#xff1a;方式2&#xff08;编译器&#xff09;&#xff1a;方式3&#xff08;命令行&#xff09;&#xff1a;方法4&#xff08;重命名文件法&#xff09;&#xff1a;方法5&#xff08;使用flask命令…

欧盟新规,燃油噩梦?2025年起,高速公路每60公里设立一处快充站

根据外媒The Verge报道&#xff0c;欧洲电动汽车用户将获得更多便捷的待遇&#xff0c;同时还能减少有害温室气体排放&#xff0c;这得益于欧盟理事会最新通过的法规。 根据欧盟的法规要求&#xff0c;自2025年起&#xff0c;TEN-T高速公路系统在欧洲将需要每隔60公里设立一座高…

WEB:ics-07

背景知识 php弱类型 文件上传漏洞 一句话木马 floatval函数 题目 点击项目管理 点击查看源代码&#xff0c;发泄一个view-source.php 访问该网页 进行代码审计 <?php session_start();if (!isset($_GET[page])) {show_source(__FILE__);die(); }if (isset($_GET[page]) &…

ant design vue a-table表格中插入操作按钮(以switch开关 [a-switch]为例)

1.给columns添加列属性 columns() {sortedInfo sortedInfo || {};return [{title: "工程",dataIndex: "outputProject",width: 80},{title: "是否显示小数",dataIndex: "showDecimalsOrnot",width: 80,scopedSlots: { customRender:…