springboot整合flowable工作流引擎的简单使用

news2025/4/7 20:10:38

内容来自网络整理,文章最下有引用地址,可跳转至相关资源页面。若有侵权请联系删除

环境:

mysql5.7.2
springboot 2.3.9.RELEASE
flowable 6.7.2

采坑:

1.当前flowable sql需要与引用的pom依赖一致,否则会报library version is '6.6.0.0', db version is 5.99.0.0 Hint: Set <property name="databaseSchemaUpdate" to value="true" or value="create-drop" (use create-drop for testing only!) in bean processEngineConfiguration in flowable.cfg.xml
在这里插入图片描述
在这里插入图片描述2.启动的时候会报类型转换异常,跟了断点是这里数据库是datetime类型,源码中是直接用Object接收(实际类型是LocalDateTime),然后当做String类型强转使用
在这里插入图片描述

很奇怪的是公司的项目同样的版本,没有做任何修改都是正常的,难道是我的mysql版本问题?

service:


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Api(tags = "工作流接口")
@RestController
@RequestMapping("/Flow")
public class FlowController {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessEngine processEngine;


    /**
     * 添加报销
     *
     * @param userId    用户Id
     * @param money     报销金额
     */
    @ApiOperation(value = "添加报销")
    @GetMapping(value = "add")
    public String addExpense(@RequestParam String userId, @RequestParam Integer money) {
        //启动流程
        HashMap<String, Object> map = new HashMap<>();
        map.put("taskUser", userId);
        map.put("money", money);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Expense2", map);
        return "提交成功.流程Id为:" + processInstance.getId();
    }


    /**
     * 获取审批管理列表
     */
    @ApiOperation(value = "获取审批管理列表")
    @GetMapping(value = "/list")
    public Object list(@RequestParam String userId) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        for (Task task : tasks) {
            System.out.println(task.toString());
        }
        return tasks.toArray().toString();
    }

    /**
     * 批准
     *
     * @param taskId 任务ID
     */
    @ApiOperation(value = "批准")
    @GetMapping(value = "/apply")
    public String apply(@RequestParam String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new RuntimeException("流程不存在");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "通过");
        taskService.complete(taskId, map);
        return "processed ok!";
    }


    /**
     * 拒绝
     */
    @ApiOperation(value = "拒绝")
    @GetMapping(value = "reject")
    public String reject(@RequestParam String taskId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "驳回");
        taskService.complete(taskId, map);
        return "reject";
    }



    /**
     * 生成流程图
     *
     * @param processId 任务ID
     */
    @ApiOperation(value = "生成流程图")
    @GetMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, @RequestParam String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, false);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }


}
public class BossTaskHandler implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("老板");// 这里就是接入我们自己的项目需要自定义的审批人
    }

}

public class ManagerTaskHandler implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("经理");
    }

}


config

import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * 字体设置
 */
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {

    @Autowired
    private RepositoryService repositoryService;


    @Override
    public void configure(SpringProcessEngineConfiguration engineConfiguration) {
        engineConfiguration.setActivityFontName("宋体");
        engineConfiguration.setLabelFontName("宋体");
        engineConfiguration.setAnnotationFontName("宋体");

    }



    /**
     * 通过 InputStream 流部署流程定义
     * @return 部署流程对象,是流程定义、图像、表单等资源的容器
     */
    @Bean
    public Deployment deploy() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("报销流程.bpmn20.xml")
                .name("ExpenseProcess")
                .deploy();
        System.out.println("deploy.getId() = " + deploy.getId());
        System.out.println("deploy.getName() = " + deploy.getName());
        return deploy;
//        return createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in)
//                .name(name).tenantId(tenantId).category(category).deploy();
    }

}

resource:

pom文件

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>mybatis</artifactId>
                    <groupId>org.mybatis</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--flowable工作流依赖-->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter-process</artifactId>
            <version>6.7.2</version>
        </dependency>
        <!--swagger ui 框架-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.9</version>
            <exclusions>
                <exclusion>
                    <artifactId>springfox-swagger2</artifactId>
                    <groupId>io.springfox</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
    </dependencies>

application.yaml(其中xxxx部分替换成自己的)

server:
  port: 8082
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: xxxx
    password: xxxxx
    url: jdbc:mysql://xxxxxx.top:9306/flow?characterEncoding=utf-8&useSSL=false&useTimezone=true
    hikari:
      read-only: false
      #客户端等待连接池连接的最大毫秒数
      connection-timeout: 60000
      #允许连接在连接池中空闲的最长时间(以毫秒为单位)
      idle-timeout: 60000
      #连接将被测试活动的最大时间量
      validation-timeout: 3000
      #池中连接关闭后的最长生命周期
      max-lifetime: 60000
      #最大池大小
      maximum-pool-size: 60
      #连接池中维护的最小空闲连接数
      minimum-idle: 10
      #从池返回的连接的默认自动提交行为。默认值为true
      auto-commit: true
      #如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性
      connection-test-query: SELECT 1
      #自定义连接池名称
      pool-name: myHikarCp

flowable:
  database-schema-update: false
  #关闭定时任务JOB
  async-executor-activate: false

swagger:
  enabled: true

log4j.properties

log4j.rootLogger=DEBUG

log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

报销流程.bpmn20.xml(其中xxxx部分替换成自己的)

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">
    <process id="Expense2" name="ExpenseProcess" isExecutable="true">
        <documentation>报销流程</documentation>
        <startEvent id="start" name="开始"></startEvent>
        <userTask id="fillTask" name="出差报销" flowable:assignee="${taskUser}">
            <extensionElements>
                <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler">
                    <![CDATA[false]]></modeler:initiator-can-complete>
            </extensionElements>
        </userTask>
        <exclusiveGateway id="judgeTask"></exclusiveGateway>
        <userTask id="directorTak" name="经理审批">
            <extensionElements>
                <flowable:taskListener event="create"
                                       class="com.xxxx.xxxx.ManagerTaskHandler"></flowable:taskListener>
            </extensionElements>
        </userTask>
        <userTask id="bossTask" name="老板审批">
            <extensionElements>
                <flowable:taskListener event="create"
                                       class="com.xxxx.xxxx.BossTaskHandler"></flowable:taskListener>
            </extensionElements>
        </userTask>
        <endEvent id="end" name="结束"></endEvent>
        <sequenceFlow id="directorNotPassFlow" name="驳回" sourceRef="directorTak" targetRef="fillTask">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="bossNotPassFlow" name="驳回" sourceRef="bossTask" targetRef="fillTask">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow1" sourceRef="start" targetRef="fillTask"></sequenceFlow>
        <sequenceFlow id="flow2" sourceRef="fillTask" targetRef="judgeTask"></sequenceFlow>
        <sequenceFlow id="judgeMore" name="大于500元" sourceRef="judgeTask" targetRef="bossTask">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money > 500}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="bossPassFlow" name="通过" sourceRef="bossTask" targetRef="end">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="directorPassFlow" name="通过" sourceRef="directorTak" targetRef="end">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="judgeLess" name="小于500元" sourceRef="judgeTask" targetRef="directorTak">
            <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money <= 500}]]></conditionExpression>
        </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_Expense">
        <bpmndi:BPMNPlane bpmnElement="Expense" id="BPMNPlane_Expense">
            <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
                <omgdc:Bounds height="30.0" width="30.0" x="285.0" y="135.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="fillTask" id="BPMNShape_fillTask">
                <omgdc:Bounds height="80.0" width="100.0" x="405.0" y="110.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="judgeTask" id="BPMNShape_judgeTask">
                <omgdc:Bounds height="40.0" width="40.0" x="585.0" y="130.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="directorTak" id="BPMNShape_directorTak">
                <omgdc:Bounds height="80.0" width="100.0" x="735.0" y="110.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="bossTask" id="BPMNShape_bossTask">
                <omgdc:Bounds height="80.0" width="100.0" x="555.0" y="255.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
                <omgdc:Bounds height="28.0" width="28.0" x="771.0" y="281.0"></omgdc:Bounds>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
                <omgdi:waypoint x="315.0" y="150.0"></omgdi:waypoint>
                <omgdi:waypoint x="405.0" y="150.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
                <omgdi:waypoint x="505.0" y="150.16611295681062"></omgdi:waypoint>
                <omgdi:waypoint x="585.4333333333333" y="150.43333333333334"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="judgeLess" id="BPMNEdge_judgeLess">
                <omgdi:waypoint x="624.5530726256983" y="150.44692737430168"></omgdi:waypoint>
                <omgdi:waypoint x="735.0" y="150.1392757660167"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="directorNotPassFlow" id="BPMNEdge_directorNotPassFlow">
                <omgdi:waypoint x="785.0" y="110.0"></omgdi:waypoint>
                <omgdi:waypoint x="785.0" y="37.0"></omgdi:waypoint>
                <omgdi:waypoint x="455.0" y="37.0"></omgdi:waypoint>
                <omgdi:waypoint x="455.0" y="110.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="bossPassFlow" id="BPMNEdge_bossPassFlow">
                <omgdi:waypoint x="655.0" y="295.0"></omgdi:waypoint>
                <omgdi:waypoint x="771.0" y="295.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="judgeMore" id="BPMNEdge_judgeMore">
                <omgdi:waypoint x="605.4340277777778" y="169.56597222222223"></omgdi:waypoint>
                <omgdi:waypoint x="605.1384083044983" y="255.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="directorPassFlow" id="BPMNEdge_directorPassFlow">
                <omgdi:waypoint x="785.0" y="190.0"></omgdi:waypoint>
                <omgdi:waypoint x="785.0" y="281.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="bossNotPassFlow" id="BPMNEdge_bossNotPassFlow">
                <omgdi:waypoint x="555.0" y="295.0"></omgdi:waypoint>
                <omgdi:waypoint x="455.0" y="295.0"></omgdi:waypoint>
                <omgdi:waypoint x="455.0" y="190.0"></omgdi:waypoint>
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>

RepositoryService提供了在编辑和发布审批流程的 api。主要是模型管理和流程定义的业务 api。

1.提供了带条件的查询模型流程定义的api
repositoryService.createXXXQuery()
例如:
repositoryService.createModelQuery().list() 模型查询 
repositoryService.createProcessDefinitionQuery().list() 流程定义查询

repositoryService.createXXXXQuery().XXXKey(XXX) (查询该key是否存在)

2.提供一大波模型与流程定义的通用方法
模型相关(【本人亲测这里获取模型貌似不行,有知道的联系我】)
repositoryService.getModel()  (获取模型)
repositoryService.saveModel()  (保存模型)
repositoryService.deleteModel() (删除模型)
repositoryService.createDeployment().deploy(); (部署模型)
repositoryService.getModelEditorSource()  (获得模型JSON数据的UTF8字符串)
repositoryService.getModelEditorSourceExtra()  (获取PNG格式图像)

3.流程定义相关
repositoryService.getProcessDefinition(ProcessDefinitionId);  获取流程定义具体信息
repositoryService.activateProcessDefinitionById() 激活流程定义
repositoryService.suspendProcessDefinitionById()  挂起流程定义
repositoryService.deleteDeployment()  删除流程定义
repositoryService.getProcessDiagram()获取流程定义图片流
repositoryService.getResourceAsStream()获取流程定义xml流
repositoryService.getBpmnModel(pde.getId()) 获取bpmn对象(当前进行到的那个节点的流程图使用)

4.流程定义授权相关
repositoryService.getIdentityLinksForProcessDefinition() 流程定义授权列表
repositoryService.addCandidateStarterGroup()新增组流程授权
repositoryService.addCandidateStarterUser()新增用户流程授权
repositoryService.deleteCandidateStarterGroup() 删除组流程授权
repositoryService.deleteCandidateStarterUser()  删除用户流程授权

RuntimeService处理正在运行的流程。

runtimeService.createProcessInstanceBuilder().start() 发起流程
runtimeService.deleteProcessInstance() 删除正在运行的流程
runtimeService.suspendProcessInstanceById() 挂起流程定义
runtimeService.activateProcessInstanceById() 激活流程实例
runtimeService.getVariables(processInstanceId); 获取表单中填写的值
runtimeService.getActiveActivityIds(processInstanceId)获取以进行的流程图节点 (当前进行到的那个节点的流程图使用)

runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); 终止流程

HistoryService在用户发起审批后,会生成流程实例。historyService 为处理流程实例的 api,但是其中包括了已经完成的和未完成的流程实例。

historyService.createHistoricProcessInstanceQuery().list() 查询流程实例列表(历史流程,包括未完成的)
historyService.createHistoricProcessInstanceQuery().list().foreach().getValue() 可以获取历史中表单的信息
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); 根绝id查询流程实例
historyService.deleteHistoricProcessInstance() 删除历史流程
historyService.deleteHistoricTaskInstance(taskid); 删除任务实例
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list()  流程实例节点列表 (当前进行到的那个节点的流程图使用)

TaskService对流程实例的各个节点的审批处理。

流转的节点审批
taskService.createTaskQuery().list() 待办任务列表
taskService.createTaskQuery().taskId(taskId).singleResult();  待办任务详情
taskService.saveTask(task); 修改任务
taskService.setAssignee() 设置审批人
taskService.addComment() 设置审批备注
taskService.complete() 完成当前审批
taskService.getProcessInstanceComments(processInstanceId); 查看任务详情(也就是都经过哪些人的审批,意见是什么)
taskService.delegateTask(taskId, delegater); 委派任务
taskService.claim(taskId, userId);认领任务
taskService.unclaim(taskId); 取消认领
taskService.complete(taskId, completeVariables); 完成任务

任务授权
taskService.addGroupIdentityLink()新增组任务授权
taskService.addUserIdentityLink() 新增人员任务授权
taskService.deleteGroupIdentityLink() 删除组任务授权
taskService.deleteUserIdentityLink() 删除人员任务授权

ManagementService主要是执行自定义命令。

managementService.executeCommand(new classA())  执行classA的内部方法,classA要实现Command,重写execute方法

IdentityService用于身份信息获取和保存,这里主要是获取身份信息。

identityService.createUserQuery().userId(userId).singleResult();  获取审批用户的具体信息
identityService.createGroupQuery().groupId(groupId).singleResult(); 获取审批组的具体信息

主要几张表介绍
ACT_RU_TASK 每次启动的流程都会再这张表中,表示代办项, 流程结束会删除该流程数据
ACT_RU_EXECUTION 流程执行过程表, 会存该流程正在执行的过程数据, 流程结束会删除该流程数据
ACT_RU_VARIABLE 流程变量表, 流程中传的参数都会再该表存储, 流程结束会删除该流程数据
ACT_HI_PROCINST 历史运行流程, 当流程处理完了, 在ACT_RU_* 表中就不会有数据, 可以在该表中查询历史
ACT_HI_TASKINST 历史运行的task信息,
ACT_RE_PROCDEF 流程模板记录,同一个key多次发布version_字段会递增
ACT_RE_DEPLOYMENT 部署的流程模板, 可以启动流程使用的

摘抄自:
https://www.cnblogs.com/xfeiyun/p/16185713.html
https://www.cnblogs.com/codeMedita/p/15972476.html
https://blog.csdn.net/qq_42277412/article/details/121830797
https://blog.csdn.net/qq_42715450/article/details/126634276

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

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

相关文章

【chapter29】【PyTorch】[Regularization】

前言&#xff1a; 前面讲了Overfitted,这里重点讲解一下如何防止 Overfitting ,以及其中的方案之一 Regularization 模型的参数量,模型的表达能力远超模型本身复杂度. 与之对应的是奥卡姆剃刀原理&#xff1a; 如何用最简单的方法得到最好的效果 找到关键的部分&#xff0c;简…

【SWAT水文模型】SWAT水文模型建立及应用第三期:土壤库建立(待更新)

SWAT水文模型建立及应用&#xff1a;土壤库建立 1 简介2 土壤数据下载2.1 数据下载方式2.1.1 世界土壤数据库HWSD数据2.1.2 中国土壤数据库 2.2 数据下载 3 土壤数据的准备3.1 SWAT土壤数据库参数3.2 土壤质地转化3.3 土壤参数的提取3.4 其他变量的提取3.5 土壤类型分布图的处理…

回顾 | Pre VS Code Day - 用 GitHub Codespaces 构建 OpenAI 应用实战

编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0c;将每周三到周六&a…

85.qt qml-炫酷烟花粒子特效(支持多种爆炸模式、爆炸阴影、背景场景)

效果如下所示: 截图如下所示: 实现内容如下所示: 1.实现多个爆炸效果2.爆炸的时候增加光度阴影效果3.由于场景有湖面,所以还需要增加一个倒影粒子组首先我们来学习下,该示例中所需要常用的类型点 1.如何更改粒子生命周期时的颜色变换动画 方法有两种。 1.1通过colorTable和si…

详谈Android进程间的大数据通信机制:LocalSocket

前言 说起Android进行间通信&#xff0c;大家第一时间会想到AIDL&#xff0c;但是由于Binder机制的限制&#xff0c;AIDL无法传输超大数据。 比如我们在之前文章《WebRtc中是如何处理视频数据的&#xff1f;》提到的我们可以得到WebRtc的视频数据&#xff0c;这时候我们如果有…

C++类和对象(4)

C类和对象 1.拷贝构造函数1.1 概念1.2. 特征1.2.1. 拷贝构造函数构造函数的一种重载形式&#xff1b;1.2.2. 拷贝构造函数的参数只能有一个&#xff0c;是对本类类型对象的引用&#xff0c;不能是传值调用&#xff0c;编译会直接报错&#xff0c;或者是直接进入死循环。1.2.3. …

wvp开发环境搭建

代码下载地址 代码下载地址 https://gitee.com/pan648540858/wvp-GB28181-pro.git 开发工具 采用jetbrain idea 利用开发工具下载代码 文件-新建-来自版本控制的项目 url是上面的代码下载链接&#xff0c;点击克隆即可 下图是已经克隆并打开的代码 安装依赖环境 安装redi…

基于html+css的图展示44

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Linux套接字编程

在上一篇博客中我们对网络中一些基本概念进行了简单阐述&#xff0c;这一篇博客我们来对套接字编程的内容进行初步了解。 目录 1.引入 2.UDP协议 2.1通信两端流程 2.1.1服务端流程 2.1.2客户端流程 2.2套接字相关操作接口 2.2.1创建套接字 2.2.2为套接字绑定地址信息 …

SSL证书周期变为90天? 锐成让您轻松应对行业新规

3月3日&#xff0c;谷歌在其“Move Forward, Together”栏目中&#xff0c;称已向CA/B论坛发起了投票提案&#xff0c;建议将公共TLS&#xff08;也称为SSL&#xff09;证书的最长有效期从398天减少到90天。值得注意的是&#xff0c;即便CA/B论坛没有通过这一提议&#xff0c;谷…

【C语言】函数讲解(下)

【C语言】函数讲解&#xff08;下&#xff09; 1.函数的声明和定义1.1函数声明1.2函数定义 2.函数的嵌套调用和链式访问2.1嵌套调用2.2链式访问 3.函数递归3.1什么是递归3.2递归的两个必要条件3.2.1练习13.2.2练习2 3.3递归与迭代3.3.1练习13.3.2练习2 所属专栏&#xff1a;C语…

Android Jetpack—LiveData

1.LiveData LiveData是Android Jetpack包提供的一种可观察的数据存储器类&#xff0c;它可以通过添加观察者被其他组件观察其变更。不同于普通的观察者&#xff0c;LiveData最重要的特征是它具有生命周期感知能力&#xff0c;它遵循其他应用组件&#xff08;如 Activity、Frag…

软件测试—进阶篇

软件测试—进阶篇 &#x1f50e;根据测试对象划分界面测试可靠性测试容错性测试文档测试兼容性测试易用性测试安装卸载测试安全性测试性能测试内存泄漏测试 &#x1f50e;根据是否查看代码划分黑盒测试白盒测试灰盒测试 &#x1f50e;根据开发阶段划分单元测试集成测试系统测试…

mulesoft MCIA 破釜沉舟备考 2023.04.27.25 (易错题)

@[TOC](mulesoft MCIA 破釜沉舟备考 2023.04.27.25 (易错题)) 1. According to MuleSoft, which deployment characteristic applies to a microservices application architecture? A. Services exist as independent deployment artifacts and can be scaled independently…

ABeam Insight | 智能制造系列(6):虚拟/增强现实(VR/AR)×智能制造

虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;的概念早在20世纪60年代就被提出&#xff0c;但由于当时的技术水平无法满足相关应用的需求&#xff0c;这些概念并没有引起广泛关注。直到近年来随着计算机技术的飞速发展&#xff0c;虚拟现实和增强现…

python+nodejs+php+springboot+vue高校教室自习室预约管理系统

建立的自习室预约管理系统用户使用浏览器就可以对其进行访问&#xff0c;管理员在操作上面能够方便管理&#xff0c;因此用户和管理员能够方便对这个系统进行操作。论文全面介绍系统数据库&#xff0c;功能设计和业务流程设计。数据库能够存储自习室预约管理系统需要的数据。 …

Leanback(1)-播放控制栏下添加新的行

我们要在播放控制栏下面加入下面一行。 这个就是标准的row。 leanback的原理 Android Leanback结构源码简析 - 简书 我们知道Row用来提供数据&#xff0c;row可以通过一个ObjectAdapter来管理和提供数据 我们知道presenter是一个负责将数据绑定到视图上的对象&#xff0c;它可以…

基于STM32的智能语音垃圾桶设计

一. 系统设计及框图&#xff1a; 本设计整体功能如下&#xff1a; 1. 超声波感应到有人靠近时语音提示“垃圾放置请分类”。 2. 检测垃圾筒时是否满&#xff0c;当满时语音提示“垃圾桶已满”。 3. 光传感器检测&#xff0c;指示灯指示。 4. 语音识别不同的垃圾类型。 二.…

前端程序员的职业发展规划与路线——ChatGPT的回答

文章目录 一、前端程序员的职业规划是&#xff1f;回答1&#xff1a; 作为一个前端开发程序员&#xff0c;您的职业发展路线可能如下&#xff1a;回答2&#xff1a;作为前端开发程序员&#xff0c;您的职业发展路线可能如下&#xff1a;回答3&#xff1a; 你的职业发展路线可能…

ASEMI代理ADI亚德诺ADM3051CRZ-REEL7车规级芯片

编辑-Z ADM3051CRZ-REEL7芯片参数&#xff1a; 型号&#xff1a;ADM3051CRZ-REEL7 显性状态&#xff1a;78 mA 隐性状态&#xff1a;10 mA 待命状态&#xff1a;275μA CANH输出电压&#xff1a;4.5V CANL输出电压&#xff1a;2V 差动输出电压&#xff1a;3V 输入电压…