【工作流引擎】Activiti的使用02

news2024/9/22 21:36:26

Activiti的使用主要分三步:

1,定义流程

按照bpmn规范定义一个流程,
模板文件

<?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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.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.activiti.org/test">
  <process id="myProcess" name="My process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="创建请假单"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="部门经理审核"></userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask3" name="人事复核"></userTask>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
    <bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="130.0" y="160.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="210.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="360.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="510.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="160.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="165.0" y="177.0"></omgdi:waypoint>
        <omgdi:waypoint x="210.0" y="177.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="315.0" y="177.0"></omgdi:waypoint>
        <omgdi:waypoint x="360.0" y="177.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="465.0" y="177.0"></omgdi:waypoint>
        <omgdi:waypoint x="510.0" y="177.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="615.0" y="177.0"></omgdi:waypoint>
        <omgdi:waypoint x="660.0" y="177.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

BPMN规范中的流程符号

1, 事件Event

  • 开始
  • 中间
  • 结束

2,活动Activity

  • 用户任务
  • 服务任务
  • 任务子流程

一个活动可以是一个任务,还可以是一个当前流程的字处理流程,活动还可以指定不同的类型

3,网关GateWay
网关用来处理决策

  • 排他网关

只有一条径会被选择,流程执行到该网关时,按照输出顺序逐个执行,当条件为true时,继续执行当前网关

如果有多条路径则会执行第一个值为true的线路,如果所有true,则会报异常

排他网关需要和条件顺序流结合使用,default属性指定默认顺序流,当所有条件都不满足时会走default指定的顺序流

  • 并行网关

所有路径会被同时选择

拆分-----并行执行所有输出流,为每一条顺序六创建一个并行执行线路

合并----所有并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行

  • 包容网关

可以同时执行多条线路,也可以在网关设置条件
拆分----计算线路上的表达式,结果为true的,创建一个并行线路执行

合并----所有并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行

  • 综合网关

  • 事件网关

用于捕捉事件设置的,允许多个输出流执行多个不同的中间捕获事件,当流程执行到事件网关后,流程处于等待状态,需要等到抛出事件才能将等待状态转换为活动状态.

创建流程文件

在idea中下载actiBPM插件,在插件库中可能找不到该插件
actiBPMN插件下载

在resource文件夹下创建一个流程文件 **.bmpn文件,然后使用插件绘制业务流程

在这里插入图片描述
在流程中添加每个流程相关的人(申请人,审批人…)
在这里插入图片描述

在这里插入图片描述
之后我们查看evection.bpmn文件

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1696900343930" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process activiti:candidateStarterGroups="employee" activiti:candidateStarterUsers="Gavin" id="MyEvection" isClosed="false" isExecutable="true" name="Travel Application" processType="None">
    <startEvent id="_2" name="StartEvent"/>
    <userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="Travel Application"/>
    <userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" name="Department Manager Approval"/>
    <userTask activiti:assignee="tom" activiti:exclusive="true" id="_5" name="General Manager Approval"/>
    <userTask activiti:assignee="gavin" activiti:exclusive="true" id="_6" name="Financial Approval"/>
    <sequenceFlow id="_7" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_9" sourceRef="_4" targetRef="_5"/>
    <sequenceFlow id="_10" sourceRef="_5" targetRef="_6"/>
    <endEvent id="_11" name="EndEvent"/>
    <sequenceFlow id="_12" sourceRef="_6" targetRef="_11"/>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="MyEvection">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <omgdc:Bounds height="32.0" width="32.0" x="165.0" y="25.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
        <omgdc:Bounds height="55.0" width="85.0" x="150.0" y="135.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <omgdc:Bounds height="55.0" width="100.0" x="155.0" y="255.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="100.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="355.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
        <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="450.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_11" id="Shape-_11">
        <omgdc:Bounds height="32.0" width="32.0" x="190.0" y="585.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_11">
        <omgdi:waypoint x="206.0" y="505.0"/>
        <omgdi:waypoint x="206.0" y="585.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_3">
        <omgdi:waypoint x="181.0" y="57.0"/>
        <omgdi:waypoint x="181.0" y="135.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4">
        <omgdi:waypoint x="195.0" y="190.0"/>
        <omgdi:waypoint x="195.0" y="255.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_4" targetElement="_5">
        <omgdi:waypoint x="202.5" y="310.0"/>
        <omgdi:waypoint x="202.5" y="355.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_6">
        <omgdi:waypoint x="202.5" y="410.0"/>
        <omgdi:waypoint x="202.5" y="450.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

我们可以看到,.bpmn文件其实是一个xml格式的文件,我们尝试改一下后缀名为.xml

由于使用的.xml文件后缀而不是原生的.bpmn文件,那怎么生成流程图呢?
右键该文件—>>
在这里插入图片描述

之后就会生成一个图:这个图就比较美观,可以用于给客户展示(内部使用的话没必要)
在这里插入图片描述

当然你也可以截图巴拉巴拉,反正有很多方法,不用太在意;

如果流程名使用中文,可能会出现乱码问题,别着急,
在这里插入图片描述
还是乱码的话,需要修改下面这两个文件:

参考这篇文章—三步解决IDEA actiBPM插件之.bpmn文件中文乱码问题

中文版流程
在这里插入图片描述

2,部署流程

把流程定义文件,加载到数据库中

   @Test
    public void Test02() {
        //1,创建processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2,获取部署的服务 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3,使用RepositoryService实例进行流程的部署,定义一个流程名然后部署到数据库中
        DeploymentBuilder deployment = repositoryService.createDeployment();
        //4,将部署信息装入数据库表中
        Deployment deploy = deployment.name("出差申请流程").disableSchemaValidation().addClasspathResource("bpmn/evection.bpmn").addClasspathResource("bpmn/evection.png").deploy();

        System.out.println("流程部署id"+ deploy.getId());
        System.out.println("流程部署名称"+ deploy.getName());
        System.out.println("流程部署目录"+ deploy.getCategory());
        System.out.println("流程部署"+ deploy.getTenantId());
        System.out.println("流程部署"+ deploy.getKey());
        System.out.println("流程部署时间"+ deploy.getDeploymentTime());

    }

部署完毕后,我们可以看到re的表中有了数据

在这里插入图片描述
部署时操作的表有:

  • ACT_RE_DEPLOYMENT
    存放部署的流程信息(名称,部署时间等)
DeploymentEntity[id=1, name=出差申请流程]
2023-10-10 11:45:14,089 2510  [           main] DEBUG entEntityImpl.insertDeployment  - ==>  Preparing: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_) values(?, ?, ?, ?, ?, ?, ?) 
2023-10-10 11:45:14,100 2521  [           main] DEBUG entEntityImpl.insertDeployment  - ==> Parameters: 1(String), 出差申请流程(String), null, null, (String), 2023-10-10 11:45:14.01(Timestamp), null
2023-10-10 11:45:14,102 2523  [           main] DEBUG entEntityImpl.insertDeployment  - <==    Updates: 1

在这里插入图片描述

  • ACT_GE_BYTEARRAY
    存放部署文件信息
Preparing: INSERT INTO ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, DEPLOYMENT_ID_, GENERATED_) VALUES (?, 1, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?) 
2023-10-10 11:45:14,121 2542  [           main] DEBUG eEntityImpl.bulkInsertResource  - ==> Parameters: 2(String), bpmn/evection.png(String), java.io.ByteArrayInputStream@7a11c4c7(ByteArrayInputStream), 1(String), false(Boolean), 3(String), bpmn/evection.bpmn(String), java.io.ByteArrayInputStream@4cc547a(ByteArrayInputStream), 1(String), false(Boolean)
2023-10-10 11:45:14,132 2553  [           main] DEBUG eEntityImpl.bulkInsertResource  - <==    Updates: 2

在这里插入图片描述

ACT_RE_PROCDEF
流程定义表
在这里插入图片描述

ACT_GE_PROPERTY
在这里插入图片描述

3,启动流程

启动流程需要使用runtimeService,

 @Test
    public void Test03() {
        //流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获得运行时服务
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //通过key来开启一个实例
        ProcessInstance myEvection = runtimeService.startProcessInstanceByKey("MyEvection");
        System.out.println(myEvection.getProcessDefinitionId());
        System.out.println(myEvection.getId());
        System.out.println(myEvection.getActivityId());
    }

启动时根据act_re_procdef表中的key来启动一个实例;
在这里插入图片描述

创建流程实例时用到/操作的表
主要是下面的几张表
在这里插入图片描述
记录了流程历史表
在这里插入图片描述
记录了当下正在走的流程
在这里插入图片描述
记录了操作的流程用时(开始时间和结束时间)

任务完成得整个流程代码如下

package gavin.test;

import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.util.List;

public class ActTest {


    //创建数据表
    @Test
    public void Test01() {
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(engine);
    }

    /**
     * 部署流程
     * 1,创建processEngine
     * 2,获取部署的服务 RepositoryService
     * 3,使用RepositoryService实例进行流程的部署,定义一个流程名然后部署到数据库中
     * 4,将部署信息(.bpmn文件和.png文件)入数据库表中输出部署信息
     */
    @Test
    public void Test02() {
        //1,创建processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2,获取部署的服务 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3,使用RepositoryService实例进行流程的部署,定义一个流程名然后部署到数据库中
        DeploymentBuilder deployment = repositoryService.createDeployment();
        //4,将部署信息装入数据库表中
        Deployment deploy = deployment.name("出差申请流程").disableSchemaValidation().addClasspathResource("bpmn/evection.bpmn").addClasspathResource("bpmn/evection.png").deploy();

        System.out.println("流程部署id" + deploy.getId());
        System.out.println("流程部署名称" + deploy.getName());
        System.out.println("流程部署目录" + deploy.getCategory());
        System.out.println("流程部署" + deploy.getTenantId());
        System.out.println("流程部署" + deploy.getKey());
        System.out.println("流程部署时间" + deploy.getDeploymentTime());

    }

    /**
     * hi_actinst 流程实例执行历史
     * hi_identitylink 流程参与用户历史
     * hi_procinst 流程实例历史信息
     * hi_taskinst 流程任务历史
     * ru_execution 流程执行信息
     * ru_identitylink 路程参与用户信息
     * ru_task 流程任务
     */
    @Test
    public void Test03() {
        //流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获得运行时服务
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //通过key来开启一个实例
        ProcessInstance myEvection = runtimeService.startProcessInstanceByKey("MyEvection");
        System.out.println(myEvection.getProcessDefinitionId());
        System.out.println(myEvection.getId());
        System.out.println(myEvection.getActivityId());
    }

    /**
     * 查询个人执行的任务
     */
    @Test
    public void Test04() {
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = engine.getTaskService();
        List<Task> list = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("zhangsan").list();

        for (Task task :
                list) {
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getAssignee());
            System.out.println(task.getName());
        }
    }

    /**
     * 完成任务id
     */
    @Test
    public void Test05() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();
        taskService.complete("10005");
    }


    /**
     * 查询个人执行的任务
     */
    @Test
    public void Test06() {
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = engine.getTaskService();
        List<Task> list = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("jerry").list();

        for (Task task :
                list) {
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getAssignee());
            System.out.println(task.getName());
        }
    }
    /**
     * 完成任务id
     */
    @Test
    public void Test07() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();
        taskService.complete("17502");
    }
    /**
     * 查询个人执行的任务
     */
    @Test
    public void Test08() {
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = engine.getTaskService();
        List<Task> list = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("tom").list();

        for (Task task :
                list) {
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getAssignee());
            System.out.println(task.getName());
        }
    }
    /**
     * 完成任务id
     */
    @Test
    public void Test09() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();
        taskService.complete("20002");
    }
        /**
     * 完成任务id
     */
    @Test
    public void Test10() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();
        taskService.complete("22502");
    }

}

小结:
1,获得processengine—以生成数据表

2,部署对应的工作流
通过processengine获得部署服务(部署文件 *.bpmn 与流程图 )repositoryService

3,开启流程实例
获得runtimeservice后获得运行时

4,处理工作流程
获得taskservice完成流程实例,以进行下一步流程

打包部署

  @Test
    public void deployProcessZip() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        //获得流---读取资源
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
        //流传入构造方法中
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        Deployment deploy = repositoryService.createDeployment().disableSchemaValidation().addZipInputStream(zipInputStream).deploy();
        System.out.println(deploy.getId());
        System.out.println(deploy.getName());
    }

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

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

相关文章

基于SpringBoot的大学城水电管理系统

目录 前言 一、技术栈 二、系统功能介绍 管理员模块的实现 领用设备管理 消耗设备管理 设备申请管理 状态汇报管理 用户模块的实现 设备申请 状态汇报 用户反馈 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛…

在windows系统上安装pgAdmin4

pgAdmin4是全球最先进的开源数据库PostgreSQL的领先开源管理工具。它旨在满足新手和经验丰富的PostgreSQL用户的需求&#xff0c;提供了强大的图形界面&#xff0c;可简化数据库对象的创建、维护和使用。 pgAdmin4是Python开发的Web应用程序&#xff0c;既可以部署为Web模式通…

使用eclipce ,将java项目打包成jar包

第一步&#xff1a;右击需要打包的项目&#xff0c;-Run As -> Maven install 第二步&#xff1a;在当前项目的target 目录下&#xff0c;查看生成的项目jar包

Visual Studio 错误CS0006:未能找到元数据文件踩坑记录

前言 在写项目的时候&#xff0c;添加了个新的Nuget包&#xff0c;突然就不行&#xff0c;然后就是报错&#xff0c;找不到文件、 出现的原因是因为项目之间互相引用出现了问题&#xff0c;比如如下情况 先版本回退 如果有Git仓库 第一时间去看Git 文件比较&#xff0c;找到…

高压放大器在纳米材料中的应用有哪些

高压放大器是一种重要的电子设备&#xff0c;可以用于增强输入信号的电压。在纳米材料领域&#xff0c;高压放大器也具有广泛的应用。下面西安安泰将介绍高压放大器在纳米材料中的应用&#xff0c;并探讨其可行性和潜在的研究方向。 纳米材料传感器&#xff1a;高压放大器在纳米…

C语言重点突破(2)指针(二)

本章重点 1. 字符指针 2. 数组指针 3. 指针数组 4. 数组传参和指针传参 1. 字符指针 在我的前一章节&#xff0c;我们提到指针也有类型的区分&#xff0c;有整型指针&#xff0c;浮点型指针&#xff0c;下面我们讲讲字符指针 字符指针的用法通常是将一个字符变量的地址存…

请求和响应的概述

请求&#xff1a;在浏览器地址栏输入地址&#xff0c;点击回车请求服务器&#xff0c;这个过程就是一个请求过程。 响应&#xff1a;服务器根据浏览器发送的请求&#xff0c;返回数据到浏览器在网页上进行显示&#xff0c;这个过程就称之为响应。 针对Servlet的每次请求&…

配资炒股优质平台排名:十大排名和评估!

随着互联网的发展&#xff0c;配资炒股平台已经成为了越来越多投资者的选择&#xff0c;但是市场上的配资炒股平台各不相同&#xff0c;投资者如何选择一家优质的平台呢&#xff1f;这时候&#xff0c;配资炒股优质平台排名就显得尤为重要。 配资炒股优质平台排名的作用&#…

搭载国内首个教育大模型“子曰”,有道虚拟人口语教练Hi Echo今日上线

10月11日&#xff0c;网易有道宣布&#xff0c;搭载子曰教育大模型的全球首个虚拟人口语教练 Hi Echo正式推出独立APP和微信小程序。这名一对一口语教练具备全天候多平台的陪伴能力&#xff0c;将更好地为用户提供随时随地高质量的口语练习&#xff0c;让用户彻底告别哑巴英语。…

OpenGL LUT滤镜算法解析

1. 简介 滤镜&#xff1a;一些图像处理软件针对性地提供了一些对传统滤镜效果的模拟功能&#xff0c;使图像达到一种特殊效果。滤镜通常需要同通道、图层、色阶等联合使用&#xff0c;才能使图像取得最佳艺术效果。在软件界面中也直接以“滤镜”&#xff08;Filter&#xff09…

乐优商城(二)搭建后台前端

1. 搭建后台管理前端 1.1 导入已有资源 找到已经准备好的 leyou-manage-web 压缩文件&#xff0c;这就是后台管理的前端项目 解压 leyou-manage-web 文件到项目中&#xff0c;注意与 leyou 文件同级 1.2 安装依赖 在 IDEA 中打开 leyou-manage-web 工程 2.打开 Teminal&…

LeakCanary(4)面试题系列

序、慢慢来才是最快的方法。 问题1&#xff1a;LeakCanary 支持Android 场景中的那些内存泄漏监测&#xff1f; 已销毁的 Activity 对象&#xff08;进入 DESTROYED 状态&#xff09;&#xff1b;已销毁的 Fragment 对象和 Fragment View 对象&#xff08;进入 DESTROYED 状态…

面试算法25:链表中的数字相加

题目 给定两个表示非负整数的单向链表&#xff0c;请问如何实现这两个整数的相加并且把它们的和仍然用单向链表表示&#xff1f;链表中的每个节点表示整数十进制的一位&#xff0c;并且头节点对应整数的最高位数而尾节点对应整数的个位数。例如&#xff0c;两个分别表示整数98…

css吸顶特效(elementui vue3官网)

效果如图&#xff1a;当浏览器滚轮在最上面的时候 没什么区别。当鼠标滚轮超出最上面高度时会有这种粒子感。吸顶遮盖下面内容 首先要 明确 css 基础属性 position: sticky;的用法。再了解 background-image: radial-gradient(transparent 1px, #fff 1px); background-size: …

Java 8 引进的一个新特性 Optional

Optional 是 Java 8 引进的一个新特性&#xff0c;通常用于缓解常见的空指针异常问题。 Brian Goetz &#xff08;Java语言设计架构师&#xff09;对Optional设计意图的原话如下&#xff1a; Optional is intended to provide a limited mechanism for library method return…

马蹄集matji oj赛(第十二次)

目录 元素共鸣 欧拉函数 欧拉函数2 小码哥的喜欢数 整数的逆 数的自我 阶乘的质因子 分数个数 质数率 数字游戏 元素共鸣 难度&#xff1a;黄金 0时间限制&#xff1a;1秒 巴占用内存&#xff1a;128M 遥远的大陆上存在着元素共鸣的机制。 建立一个一维坐标系&#x…

保护隐私与增强网络安全之网络代理技术

目录 前言 一、网络代理技术原理 二、网络代理技术类型 1. HTTP代理 2. SOCKS代理 3. DNS代理 4. 加密代理 5. 反向代理 三、网络代理技术应用 1. 加速网络访问速度 2. 绕过网络限制 3. 保护个人隐私 4. 节省带宽 5. 改善网络安全 四、网络代理技术优缺点 网络…

APK大小缩小65%,内存减少70%:如何优化Android App

APK大小缩小65&#xff05;&#xff0c;内存减少70&#xff05;&#xff1a;如何优化Android App 我们一直在努力为我们的Android应用程序构建MVP产品。在开发MVP产品后&#xff0c;我们发现需要进行应用程序优化以提高性能。经过分析&#xff0c;我们发现了以下可以改进的应用…

比特币有助减少腐败;微软 Copilot 每月赔 20 美元;AIGC 明年会“洗冷水澡”丨 RTE 开发者日报 Vol.64

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

AMEYA360分享:村田电子搭载了Onsemi公司IoT设备专用IC的新Bluetooth® Low Energy模块开始量产

近年来&#xff0c;所有远程监控、远程控制的用例均要求具备可无线连接的电池驱动IoT设备&#xff0c;而长寿命电池与安全的数据通信功能是其关键。为此&#xff0c;在IoT边缘设备的设计方面&#xff0c;最大的课题是要提高功率效率和安全性。 Type 2EG由于无线与内置微处理器两…