SpringBoot2.x简单集成Flowable

news2025/2/25 11:25:23

环境和版本

window10
java1.8
mysql8
flowable6
springboot 2.7.6

配置

使用IDEA创建一个SpringBoot项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>flowable-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>flowable-demo</name>
    <description>flowable-demo</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.7.6</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter</artifactId>
            <version>6.4.1</version>
            <exclusions>
            <!--        这里要排除mybatis,否则会覆盖mybatis-plus引入的mybatis版本        -->
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--    mybatis-plus    -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--    mybatis-plus generator    -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.example.flowable.demo.FlowableDemoApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

application.yml中配置

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/flowable_demo?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: qk123
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 15
      auto-commit: true
      idle-timeout: 30000
      pool-name: DatebookHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1

  # jackson 配置
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    locale: zh
    time-zone: GMT+8

#server.servlet.context-path=/
# swagger2使用,不配置这个项目报错 Failed to start bean ‘documentationPluginsBootstrapper‘
flowable:
  # 第一次改为true,创建完数据库表结构后,改为false
  database-schema-update: true
  async-executor-activate: false
server:
  port: 11000
# 设置flowable日志级别
logging:
  level:
    org.flowable: debug
#spring.mvc.pathmatch.matching-strategy=ant-path-matcher

再创建一个数据库
在这里插入图片描述
然后运行
在这里插入图片描述
数据库中会自动生成表结构
在这里插入图片描述

表结构位置

在这里插入图片描述

常用的类

flowable的autoconfig包已经自动配置好了需要的类
在这里插入图片描述
在这里插入图片描述
直接@Resource就可以使用
在这里插入图片描述

使用

部署一个简单流程

import com.example.flowable.demo.controller.vo.DefinitionRequest;
import com.example.flowable.demo.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.List;


@Slf4j
@RestController
@RequestMapping("/modeler")
public class ModelerController {
    @Resource
    private RepositoryService repositoryService;

    /**
     * 部署流程
     * @param definitionRequest
     * @return
     */
    @PutMapping("/deploy")
    public R deployModeler(@RequestBody DefinitionRequest definitionRequest) {
        String xmlDefinition = definitionRequest.getXmlDefinition();
        DeploymentBuilder deployment = repositoryService.createDeployment();
        byte[] bytes = xmlDefinition.getBytes(StandardCharsets.UTF_8);
        int i = RandomUtils.nextInt();
        String key = "demo_flow_" + i;
        String name = "示例流程";
        String category = "hello_" + i;
        // 流程定义的名称,必须是特定的结尾,否则不会解析
        String resourceName = "demo_flow_name_" + i + "." + ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0];
        String id = deployment.addBytes(resourceName, bytes)
                .key(key)
                .category(category)
                .name(name)
                .deploy()
                .getId();
        log.info("部署后id为:{}", id);
        Model model = repositoryService.newModel();
        model.setDeploymentId(id);
        model.setCategory("model_" + category);
        model.setKey("model_key_" + i);
        model.setName("model_name_" + i);
        model.setVersion(1);
        repositoryService.saveModel(model);
        log.info("模型保存后id:{}", model.getId());
        // 设置模型可编辑资源
        repositoryService.addModelEditorSource(model.getId(), bytes);
        return R.success(id);
    }

    /**
     * 查看流程模型列表
     * @return
     */
    @GetMapping("/list")
    public R list() {
        ModelQuery modelQuery = repositoryService.createModelQuery();
        List<Model> list = modelQuery.list();
        return R.success();
    }

}

用postman发送一个请求

{
  "xmlDefinition": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\"\n             xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n             xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n             xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\"\n             xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\"\n             xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\"\n             xmlns:flowable=\"http://flowable.org/bpmn\"\n             typeLanguage=\"http://www.w3.org/2001/XMLSchema\"\n             expressionLanguage=\"http://www.w3.org/1999/XPath\"\n             targetNamespace=\"http://www.flowable.org/processdef\">\n\n    <process id=\"holidayRequest\" name=\"Holiday Request\" isExecutable=\"true\">\n\n        <startEvent id=\"startEvent\"/>\n        <sequenceFlow sourceRef=\"startEvent\" targetRef=\"approveTask\"/>\n\n        <userTask id=\"approveTask\" name=\"Approve or reject request\"/>\n        <sequenceFlow sourceRef=\"approveTask\" targetRef=\"decision\"/>\n\n        <exclusiveGateway id=\"decision\"/>\n        <sequenceFlow sourceRef=\"decision\" targetRef=\"externalSystemCall\">\n            <conditionExpression xsi:type=\"tFormalExpression\">\n                <![CDATA[\n    ${approved}    ]]>\n            </conditionExpression>\n        </sequenceFlow>\n        <sequenceFlow  sourceRef=\"decision\" targetRef=\"sendRejectionMail\">\n            <conditionExpression xsi:type=\"tFormalExpression\">\n                <![CDATA[\n    ${approved}    ]]>\n            </conditionExpression>\n        </sequenceFlow>\n\n        <serviceTask id=\"externalSystemCall\" name=\"Enter holidays in external system\"\n                     flowable:class=\"org.flowable.CallExternalSystemDelegate\"/>\n        <sequenceFlow sourceRef=\"externalSystemCall\" targetRef=\"holidayApprovedTask\"/>\n\n        <userTask id=\"holidayApprovedTask\" name=\"Holiday approved\"/>\n        <sequenceFlow sourceRef=\"holidayApprovedTask\" targetRef=\"approveEnd\"/>\n\n        <serviceTask id=\"sendRejectionMail\" name=\"Send out rejection email\"\n                     flowable:class=\"org.flowable.SendRejectionMail\"/>\n        <sequenceFlow sourceRef=\"sendRejectionMail\" targetRef=\"rejectEnd\"/>\n\n        <endEvent id=\"approveEnd\"/>\n\n        <endEvent id=\"rejectEnd\"/>\n    </process>\n\n</definitions>"
}

在这里插入图片描述
在数据库中会出现对应的数据

在这里插入图片描述
接着发起流程

import com.example.flowable.demo.controller.vo.DefinitionRequest;
import com.example.flowable.demo.controller.vo.ProcessDefinitionResp;
import com.example.flowable.demo.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/process")
public class ProcessController {
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private RepositoryService repositoryService;

    /**
     * 查看流程定义列表
     * @return
     */
    @GetMapping("/list")
    public R list() {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list = processDefinitionQuery.list();
        log.info("得到流程定义数量:{}", list.size());
        // ProcessDefinition无法序列化,需要自己转
        List<ProcessDefinitionResp> respList = new ArrayList<>();
        for (ProcessDefinition processDefinition : list) {
            respList.add(ProcessDefinitionResp.copy(processDefinition));
        }
        return R.success(respList);
    }

    /**
     * 启动流程
     * @param definitionRequest
     * @return
     */
    @PutMapping("/create")
    public R create(@RequestBody DefinitionRequest definitionRequest) {
        String deploymentId = definitionRequest.getDeploymentId();
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        ProcessDefinition processDefinition = processDefinitionQuery.deploymentId(deploymentId).singleResult();
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee","张三") ;// 谁申请请假
        variables.put("nrOfHolidays",3); // 请几天假
        variables.put("description","工作累了,想出去玩玩"); // 请假的原因
        ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables);
        String id = holidayRequest.getId();
        log.info("启动的流程实例id:{}, 流程定义id:{}", id, processDefinition.getId());
        return R.success(id);
    }
}

查看任务

import com.example.flowable.demo.controller.vo.TaskResp;
import com.example.flowable.demo.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/task")
public class TaskController {
    @Resource
    private TaskService taskService;

    /**
     * 查看所有待办任务
     * @return
     */
    @GetMapping("/list")
    public R list() {
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> list = taskQuery.list();
        List<TaskResp> list1 = new ArrayList<>();
        for (Task task : list) {
            list1.add(TaskResp.copy(task));
        }
        return R.success(list1);
    }
}

其他类

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.io.Serializable;


@Getter
@Setter
@Accessors(chain = true)
public class R implements Serializable {
    private int code;
    private String message;
    private Object data;

    public static R gen(int code, String message, Object data) {
        return new R().setCode(code).setMessage(message).setData(data);
    }
    public static R success() {
        return R.success(null);
    }
    public static R success(Object data) {
        return R.success("请求成功", data);
    }
    public static R success(String message, Object data) {
        return R.gen(0, message, data);
    }
    public static R fail() {
        return R.fail(null);
    }
    public static R fail(Object data) {
        return R.fail("请求失败", data);
    }
    public static R fail(String message, Object data) {
        return R.gen(-1, message, data);
    }
}
import lombok.Getter;
import lombok.Setter;

/**
 * 流程定义请求
 */
@Getter
@Setter
public class DefinitionRequest {
    // 流程xml定义,部署流程用
    private String xmlDefinition;
    // 部署id,创建流程用
    private String deploymentId;
}
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.flowable.engine.repository.ProcessDefinition;

import java.io.Serializable;

/**
 * 流程定义
 */
@Getter
@Setter
@Accessors(chain = true)
public class ProcessDefinitionResp implements Serializable {
    String id;
    String category;
    String name;
    String key;
    String description;
    int version;
    String resourceName;
    String deploymentId;
    String diagramResourceName;
    boolean hasStartFormKey;
    boolean hasGraphicalNotation;
    boolean suspended;
    String tenantId;
    String derivedFrom;
    String derivedFromRoot;
    int derivedVersion;
    String engineVersion;
    public static ProcessDefinitionResp copy(ProcessDefinition processDefinition) {
        ProcessDefinitionResp definitionResp = new ProcessDefinitionResp();
        definitionResp.setId(processDefinition.getId());
        definitionResp.setCategory(processDefinition.getCategory());
        definitionResp.setName(processDefinition.getName());
        definitionResp.setKey(processDefinition.getKey());
        definitionResp.setDescription(processDefinition.getDescription());
        definitionResp.setVersion(processDefinition.getVersion());
        definitionResp.setResourceName(processDefinition.getResourceName());
        definitionResp.setDeploymentId(processDefinition.getDeploymentId());
        definitionResp.setDiagramResourceName(processDefinition.getDiagramResourceName());
        definitionResp.setHasStartFormKey(processDefinition.hasStartFormKey());
        definitionResp.setHasGraphicalNotation(processDefinition.hasGraphicalNotation());
        definitionResp.setSuspended(processDefinition.isSuspended());
        definitionResp.setTenantId(processDefinition.getTenantId());
        definitionResp.setDerivedFrom(processDefinition.getDerivedFrom());
        definitionResp.setDerivedFromRoot(processDefinition.getDerivedFromRoot());
        definitionResp.setDerivedVersion(processDefinition.getDerivedVersion());
        definitionResp.setEngineVersion(processDefinition.getEngineVersion());
        return definitionResp;
    }
}

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.flowable.task.api.Task;

import java.io.Serializable;
import java.util.*;

/**
 * 任务
 */
@Getter
@Setter
@Accessors(chain = true)
public class TaskResp implements Serializable {

    String id;
    String name;
    String description;
    int priority;
    String owner;
    String assignee;
    String processInstanceId;
    String executionId;
    String taskDefinitionId;
    String processDefinitionId;
    String scopeId;
    String subScopeId;
    String scopeType;
    String scopeDefinitionId;
    Date createTime;
    String taskDefinitionKey;
    Date dueDate;
    String category;
    String parentTaskId;
    String tenantId;
    String formKey;
    Map<String, Object> taskLocalVariables;
    Map<String, Object> processVariables;
    List<IdentityLinkInfoResp> identityLinks;
    Date claimTime;

    public static TaskResp copy(Task task) {
        TaskResp taskResp = new TaskResp();
        taskResp.setId(task.getId());
        taskResp.setName(task.getName());
        taskResp.setDescription(task.getDescription());
        taskResp.setPriority(task.getPriority());
        taskResp.setOwner(task.getOwner());
        taskResp.setAssignee(task.getAssignee());
        taskResp.setProcessInstanceId(task.getProcessInstanceId());
        taskResp.setExecutionId(task.getExecutionId());
        taskResp.setTaskDefinitionId(task.getTaskDefinitionId());
        taskResp.setProcessDefinitionId(task.getProcessDefinitionId());
        taskResp.setScopeId(task.getScopeId());
        taskResp.setSubScopeId(task.getSubScopeId());
        taskResp.setScopeType(task.getScopeType());
        taskResp.setScopeDefinitionId(task.getScopeDefinitionId());
        taskResp.setCreateTime(task.getCreateTime());
        taskResp.setTaskDefinitionKey(task.getTaskDefinitionKey());
        taskResp.setDueDate(task.getDueDate());
        taskResp.setCategory(task.getCategory());
        taskResp.setParentTaskId(task.getParentTaskId());
        taskResp.setTenantId(task.getTenantId());
        taskResp.setFormKey(task.getFormKey());
        taskResp.setTaskLocalVariables(task.getTaskLocalVariables());
        taskResp.setProcessVariables(task.getProcessVariables());
//        List<? extends IdentityLinkInfo> identityLinks1 = task.getIdentityLinks();
        taskResp.setIdentityLinks(new ArrayList<>());
//        if (Objects.nonNull(identityLinks1) && !identityLinks1.isEmpty()) {
//            for (IdentityLinkInfo identityLinkInfo : identityLinks1) {
//                taskResp.getIdentityLinks().add(IdentityLinkInfoResp.copy(identityLinkInfo));
//            }
//        }
        taskResp.setClaimTime(task.getClaimTime());
        return taskResp;
    }
}

Flowable基本的模块

Modeler 模型
Process 流程
Task 任务

模型部署后,就是流程定义。
从流程定义创建流程实例。
流程实例中有多个任务,任务有很多种类。

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

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

相关文章

GitHub下载太慢的解决方案

修改hosts文件&#xff1a; windows的hosts文件在 C:\Windows\System32\drivers\etc\hosts cmd管理员运行命令notepad C:\Windows\System32\drivers\etc\hosts 然后cmd命令重启网络ipconfig /flushdns windows修改hosts Ubuntu22.04修改hosts sudo vim /etc/hosts # This fil…

RK3288 Android11 mini-pcie接口 4G模组EC200A适配(含自适应功能)

这里写目录标题 1、修改驱动内核配置①使能USBNET功能②使能 USB 串口 GSM、CDMA 驱动③使能 USB 的 CDC ACM模式④使能PPP功能 2、使用lsusb命令查看是否识别到usb接口的“EC200A”4G模组3、在drivers/usb/serial/option.c添加VID和PID信息①添加VID和PID定义②在option_ids 数…

找寻openSUSE的前世今生

找寻开始的地方 在一些资产管理平台、网管系统&#xff0c;完全依赖资产录入资产&#xff0c;假如存在SUSE类型网元&#xff0c;能否将SLES和openSUSE一同接入到SUSE类型下&#xff0c;就有待商榷了。 SLES和openSUSE是两个不同的Linux发行版&#xff0c;更准确说是两个不同的…

基于PHP的蛋糕甜品商店管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

python读写.pptx文件

1、读取PPT import pptx pptpptx.Presentation(rC:\Users\user\Documents\\2.pptx) # ppt.save(rC:\Users\user\Documents\\1.pptx) # slideppt.slides.add_slide(ppt.slide_layouts[1])# 读取所有幻灯片上的文字 for slide in ppt.slides:for shape in slide.shapes:if shape…

[尚硅谷React笔记]——第4章 React ajax

目录&#xff1a; 脚手架配置代理_方法一 server1.js开启服务器server1:App.js解决跨域问题&#xff1a;脚手架配置代理_方法二 ​​​​​​​server2.js开启服务器server2第一步&#xff1a;创建代理配置文件编写setupProxy.js配置具体代理规则&#xff1a;App.js运行结果&a…

js实现红包雨功能(canvas,react,ts),包括图片不规则旋转、大小、转速、掉落速度控制、屏幕最大红包数量控制等功能

介绍 本文功能由canvas实现红包雨功能&#xff08;index.tsx&#xff09;本文为react的ts版。如有其他版本需求可评论区观赏地址&#xff0c;需过墙 import React, { Component } from react; // import ./index.css; import moneyx from /assets/images/RedEnvelopeRain/bal…

SEO业务适合什么代理IP?2023海外代理IP推荐排名

随着数字营销趋势的变化&#xff0c;搜索引擎优化仍然是企业在网络世界中努力繁荣的重要组成部分。为了实现 SEO 成功&#xff0c;从搜索引擎获取准确且多样化的数据至关重要&#xff0c;然而可能会受到诸如基于位置的限制和被检测风险等限制的阻碍&#xff0c;IP代理则可以帮助…

百度开源分布式id生成器集成--真香警告

百度开源分布式id生成器集成–真香警告 文章目录 [toc] 1.为什么需要分布式id生成器&#xff1f;2.常见id生成方案2.1 数据库表主键自增2.2 uuid2.3 雪花算法2.3.1 实现代码2.3.2 缺点的解决方案百度开源的分布式唯一ID生成器UidGenerator(本文重点讲解这个)Leaf--美团点评分布…

gnome-terminal禁止关闭确认

当你想要关闭一个终端时&#xff0c;弹出“确认关闭&#xff1f;”多少有些烦。 比如当前为root下&#xff0c;要么一路exit&#xff0c;要么就点击确认&#xff1a; 解决方法&#xff1a; 安装一个配置编辑器来帮我们方便地编辑配置项 sudo apt install dconf-editor找到…

小程序搭建OA项目首页布局界面

首先让我们来学习以下Flex布局 一&#xff0c;Flex布局简介 布局的传统解决方案&#xff0c;基于盒状模型&#xff0c;依赖 display属性 position属性 float属性 Flex布局简介 Flex是Flexible Box的缩写&#xff0c;意为”弹性布局”&#xff0c;用来为盒状模型提供最大的…

tomcat、nginx实现四层转发+七层代理+动静分离实验

实验环境&#xff1a; nginx1——20.0.0.11——客户端 静态页面&#xff1a; nginx2——20.0.0.21——代理服务器1 nginx3——20.0.0.31——代理服务器2 动态页面&#xff1a; tomcat1——20.0.0.12——后端服务器1 tomcat2——20.0.0.22——后端服务器2 实验步骤&…

什么是4K三路虚拟情景互动教学软件?

4K三路虚拟情景互动教学软件具备了AI对话&#xff0c;场景库丰富自定义选择&#xff0c;画面色差调节&#xff0c;人物滤镜调节&#xff0c;截图编辑&#xff0c;视频录制与编辑&#xff0c;视频直播&#xff0c;画中画控制功能&#xff0c;字幕&#xff0c;图片和特效录入功能…

sqlmap --os-shell选项原理解析

文章目录 sqlmap --os-shell选项原理解析原理解析总结 sqlmap --os-shell选项原理解析 以sqli第一关为例。 --os-shell 是 SQLMap 工具的一个参数&#xff0c;用于在成功注入数据库后&#xff0c;执行操作系统命令并获取其输出。 sqlmap -u "http://192.168.188.199/sq…

学信息系统项目管理师第4版系列31_信息系统工程

1. 信息系统战略三角突出了业务战略、信息系统和组织机制之间的必要一致性 1.1. 【高23上选07】 2. 软件工程 2.1. 软件工程方法是完成软件工程项目的技术手段&#xff0c;它支持整个软件生命周期 2.2. 软件工程使用的工具是人们在开发软件的活动中智力和体力的扩展与延伸 …

React合成事件

一、合成事件 event 是 SyntheticEvent &#xff0c;模拟出来 DOM 事件所有能力 event.nativeEvent 是原生事件对象 所有的事件&#xff0c;都被挂载到 document 上&#xff08;React ≤ 16&#xff09;&#xff0c;React17之后是挂载到root组件 和 DOM 事件不一样&#xff…

[1Panel]开源,现代化,新一代的 Linux 服务器运维管理面板

测评介绍 本期测评试用一下1Panel这款面板。1Panel是国内飞致云旗下开源产品。整个界面简洁清爽&#xff0c;后端使用GO开发&#xff0c;前端使用VUE的Element-Plus作为UI框架&#xff0c;整个面板的管理都是基于docker的&#xff0c;想法很先进。官方还提供了视频的使用教程&…

Spring Security配置多个数据源并添加登录验证码(7)

1、配置多个数据源 多个数据源是指在同一个系统中&#xff0c;用户数据来自不同的表&#xff0c;在认证时&#xff0c;如果第一张表没有查找到用户&#xff0c;那就去第二张表中査询&#xff0c;依次类推。 看了前面的分析&#xff0c;要实现这个需求就很容易了&#xff0c;认…

【计算机网络笔记】计算机网络体系结构概念

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

GO 语言的函数??

函数是什么&#xff1f; 学过编程的 xdm 对于函数自然不会陌生&#xff0c;那么函数是什么呢&#xff1f; 函数是一段可以重用的代码块&#xff0c;可以被多次调用&#xff0c;我们可以通过使用函数&#xff0c;提高咱们代码代码的模块化&#xff0c;提高程序的可读性和可维护…