独辟蹊径:我是如何用Java自创一套工作流引擎的(上)

news2024/10/6 14:36:32

作者:后端小肥肠

创作不易,未经允许严谨转载。

目录

1. 前言

2. 我为什么要自创一套工作流引擎

3. 表结构设计及关系讲解

3.1. 流程类别business_approval_workflow

3.1.1. 表结构

3.1.2. 表关系说明

3.2. 流程定义business_approval_workflow_detail

3.2.1. 表结构

3.2.2. 表关系说明

3.3. 流程任务记录approval_detail

3.3.1. 表结构

3.3.2. 表关系说明

3.4. 流程审批历史 approval_history

3.4.1. 表结构

3.4.2. 表关系说明

3.5. 申请表(流程实例)request

3.5.1. 表结构

4. 核心代码讲解

4.1. 设计用户表

4.2. 集成权限框架SpringSecurity

4.3. 工作流基础代码

4.4. 提交申请

4.5. 查看待我审批

4.6. 执行审批操作

4.7. 查看我已审批

5. 结语


1. 前言

在当前的技术生态中,工作流引擎如Activiti7和Flowable已经成为企业自动化的重要组成部分。然而,使用这些流行解决方案往往伴随着不小的学习成本,特别是Activiti7与Spring Security深度集成,使得不采用Security作为权限框架的系统面临集成上的挑战。此外,许多业务场景并不需要如此复杂的工作流框架。因此,出于对更灵活、更轻量级工作流解决方案的追求,我决定自主开发一套工作流引擎,以更好地满足特定的业务需求,同时减少对外部库的依赖。这不仅是一次技术上的挑战,也是对现有工作流理念的一次实践探索。

2. 我为什么要自创一套工作流引擎

熟悉我的博客读者都知道,我曾经基于Activiti7开发了一套成熟的工作流管理框架。然而,为何我还要自己动手创造一套新的工作流引擎呢?答案很简单:追求轻量化和更精准的边界。我长期专注于数据中台项目,涉及数据的汇集、管理与分发,其中审批流程即为其中一环。除了一个复杂的自定义流程设计和动态指定审批人的项目外,绝大多数系统仅需简单的审批流程,通常仅需1至2级审批,不涉及复杂的流程设计工具。

因此,我开发了一套轻量级工作流引擎,仅需要5张表就能完全满足简单审批流程的需求。这种定制化的设计不仅极大地简化了系统架构,还充分体现了对于业务需求精准匹配的追求。

这一决定不仅是技术上的挑战,更是对传统工作流理念的一次革新实践。

3. 表结构设计及关系讲解

3.1. 流程类别business_approval_workflow

3.1.1. 表结构
CREATE TABLE "public"."business_approval_workflow" (
  "id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "name" varchar(50) COLLATE "pg_catalog"."default" NOT NULL,
  CONSTRAINT "business_approval_workflow_pkey" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."business_approval_workflow" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."business_approval_workflow"."name" IS '业务流程名称';

 business_approval_workflow为流程类别表,定义系统中所需流程,id为业务流程id,name为业务流程名称。

3.1.2. 表关系说明

该表为流程类别表,系统中涉及的所有流程都记录在该表中。

3.2. 流程定义business_approval_workflow_detail

3.2.1. 表结构
CREATE TABLE "public"."business_approval_workflow_detail" (
  "id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "workflow_id" varchar(20) COLLATE "pg_catalog"."default" NOT NULL,
  "serial_number" int4 NOT NULL,
  "node_name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
  "node_username" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
  "is_final" varchar(1) COLLATE "pg_catalog"."default" NOT NULL,
  CONSTRAINT "business_approval_workflow_detail_pkey" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."business_approval_workflow_detail" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."business_approval_workflow_detail"."workflow_id" IS '业务流程id';

COMMENT ON COLUMN "public"."business_approval_workflow_detail"."serial_number" IS '流程序号';

COMMENT ON COLUMN "public"."business_approval_workflow_detail"."node_name" IS '任务节点名称';

COMMENT ON COLUMN "public"."business_approval_workflow_detail"."node_username" IS '处理任务节点的username';

COMMENT ON COLUMN "public"."business_approval_workflow_detail"."is_final" IS '是否最后一道审批;,1表示是,0表示不是';
3.2.2. 表关系说明

business_approval_workflow_detail为流程定义表,定义流程表中的workflow_id对应business_approval_workflow中的id(逻辑外键)。

该表主要用于定义已知流程中有哪些任务节点(node_name),节点是顺序(serial_number),任务节点的审批人(node_username)。

3.3. 流程任务记录approval_detail

3.3.1. 表结构

approval_detail表记录流程审批过程中任务节点的状态。

CREATE TABLE "public"."approval_detail" (
  "id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "request_id" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
  "approver_username" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "approval_time" timestamp(6),
  "next_approver_username" varchar(32) COLLATE "pg_catalog"."default",
  "status" varchar(6) COLLATE "pg_catalog"."default" NOT NULL,
  "remark" varchar(900) COLLATE "pg_catalog"."default",
  "workflow_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "version" int4 NOT NULL DEFAULT 1,
  "is_deleted" int4 NOT NULL DEFAULT 0,
  "create_time" timestamp(6),
  "update_time" timestamp(6),
  "node_name" varchar(255) COLLATE "pg_catalog"."default",
  "next_node_name" varchar(255) COLLATE "pg_catalog"."default",
  CONSTRAINT "approval_detail_pkey" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."approval_detail" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."approval_detail"."id" IS '主键';

COMMENT ON COLUMN "public"."approval_detail"."request_id" IS 'request表id';

COMMENT ON COLUMN "public"."approval_detail"."approver_username" IS '审批人username';

COMMENT ON COLUMN "public"."approval_detail"."approval_time" IS '审批时间';

COMMENT ON COLUMN "public"."approval_detail"."next_approver_username" IS '下一个审批人的username';

COMMENT ON COLUMN "public"."approval_detail"."status" IS '审批状态;1.待我审批;2.通过;3.驳回; ';

COMMENT ON COLUMN "public"."approval_detail"."remark" IS '审批意见';

COMMENT ON COLUMN "public"."approval_detail"."workflow_id" IS '业务流程id';

COMMENT ON COLUMN "public"."approval_detail"."node_name" IS '当前任务节点名称';

COMMENT ON COLUMN "public"."approval_detail"."next_node_name" IS '下一任务节点名称';
3.3.2. 表关系说明

approval_detail表记录流程运行中的任务节点信息。request_id对应request表中的id(逻辑外键);workflow_id对应business_approval_workflow表中的id(逻辑外键),此表可以类比理解为Activiti7中的act_ru_task

3.4. 流程审批历史 approval_history

3.4.1. 表结构

approval_history表记录流程运行时或运转后每个任务节点的历史信息。

CREATE TABLE "public"."approval_history" (
  "id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "request_id" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
  "approver_name" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "approval_time" timestamp(6),
  "status" varchar(1) COLLATE "pg_catalog"."default",
  "remark" varchar(900) COLLATE "pg_catalog"."default",
   "workflow_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "version" int4 NOT NULL DEFAULT 1,
  "is_deleted" int4 NOT NULL DEFAULT 0,
  "applicant_phone" varchar(11) COLLATE "pg_catalog"."default",
  "purpose" varchar(255) COLLATE "pg_catalog"."default",
  "applicant_name" varchar(255) COLLATE "pg_catalog"."default",
  "approver_username" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "create_time" timestamp(6),
  "update_time" timestamp(6),
  CONSTRAINT "approval_history_pkey" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."approval_history" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."approval_history"."request_id" IS '申请id';

COMMENT ON COLUMN "public"."approval_history"."approver_name" IS '审批人姓名';

COMMENT ON COLUMN "public"."approval_history"."approval_time" IS '审批时间';

COMMENT ON COLUMN "public"."approval_history"."status" IS '审批状态1.待我审批;2.通过;3.驳回';

COMMENT ON COLUMN "public"."approval_history"."remark" IS '审批意见';

COMMENT ON COLUMN "public"."approval_history"."workflow_id" IS '业务流程id';

COMMENT ON COLUMN "public"."approval_history"."applicant_phone" IS '申请人电话';

COMMENT ON COLUMN "public"."approval_history"."purpose" IS '申请理由';

COMMENT ON COLUMN "public"."approval_history"."applicant_name" IS '申请人姓名';

COMMENT ON COLUMN "public"."approval_history"."approver_username" IS '审批人username';
3.4.2. 表关系说明

approval_history表中,request_id对应request表中的id(逻辑外键);workflow_id对应business_approval_workflow表中的id(逻辑外键)。

3.5. 申请表(流程实例)request

3.5.1. 表结构

request表为申请表,同时也记录着整个流程的审批状态,当用户提交申请时在该表中填充数据,当审批状态发生改变时需要同步更新request表中status的状态,与approval_detail中的status不同,request表中status记录的是整个流程的审批状态。

CREATE TABLE "public"."request" (
  "id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "workflow_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "create_time" timestamp(6) NOT NULL,
  "purpose" varchar(900) COLLATE "pg_catalog"."default" NOT NULL,
  "status" varchar(1) COLLATE "pg_catalog"."default" NOT NULL,
  "version" int4 DEFAULT 1,
  "applicant_name" varchar(255) COLLATE "pg_catalog"."default",
  "applicant_phone" varchar(11) COLLATE "pg_catalog"."default",
  "is_deleted" int4 DEFAULT 0,
  "update_time" timestamp(6),
  "applicat_username" varchar(50) COLLATE "pg_catalog"."default",
  "applicat_unit" varchar(50) COLLATE "pg_catalog"."default",
  "resource_id" varchar(255) COLLATE "pg_catalog"."default" DEFAULT ''::character varying
)
;

ALTER TABLE "public"."request" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."request"."workflow_id" IS '业务类型id';

COMMENT ON COLUMN "public"."request"."create_time" IS '申请时间;数据库自动填充';

COMMENT ON COLUMN "public"."request"."purpose" IS '使用目的';

COMMENT ON COLUMN "public"."request"."status" IS '审批状态;1.正在审核;2.通过;3.驳回';

COMMENT ON COLUMN "public"."request"."applicant_name" IS '申请人姓名';

COMMENT ON COLUMN "public"."request"."applicant_phone" IS '申请人电话';

COMMENT ON COLUMN "public"."request"."update_time" IS '更新时间';

COMMENT ON COLUMN "public"."request"."applicat_username" IS '申请用户名';

COMMENT ON COLUMN "public"."request"."applicat_unit" IS '申请单位';

COMMENT ON COLUMN "public"."request"."resource_id" IS '申请资源id';

4. 核心代码讲解

4.1. 设计用户表

CREATE TABLE "public"."sys_user" (
  "id" varchar(40) COLLATE "pg_catalog"."default" NOT NULL,
  "username" varchar(60) COLLATE "pg_catalog"."default",
  "password" varchar(60) COLLATE "pg_catalog"."default",
  "nick_name" varchar(60) COLLATE "pg_catalog"."default",
  CONSTRAINT "sys_user_pkey" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."sys_user" 
  OWNER TO "postgres";

CREATE INDEX "username" ON "public"."sys_user" USING btree (
  "username" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);

COMMENT ON COLUMN "public"."sys_user"."id" IS '用户 ID';

COMMENT ON COLUMN "public"."sys_user"."username" IS '用户名';

COMMENT ON COLUMN "public"."sys_user"."password" IS '密码,加密存储';

COMMENT ON COLUMN "public"."sys_user"."nick_name" IS '昵称';

COMMENT ON TABLE "public"."sys_user" IS '用户信息表';

在表中写死几个用户,设定好他们的角色。

4.2. 集成权限框架SpringSecurity

工作流一般都需要跟权限框架联动,这里假设整合的是SpringSecurity(实际上我没整合权限框架,哈哈,我把用户都写死在代码里面了),整合步骤就略过了,我之出过SpringSecurity系列,包含了用户登录、权限和菜单分配,都有很详细的代码,链接如下:

【Spring Security系列】Spring Security+JWT+Redis实现用户认证登录及登出_spring security jwt 退出登录-CSDN博客

【Spring Security系列】基于Spring Security实现权限动态分配之用户-角色分配_springsecurity新增角色分配权限-CSDN博客

【Spring Security系列】基于Spring Security实现权限动态分配之菜单-角色分配及动态鉴权实践_springsecurity 角色关联菜单-CSDN博客

4.3. 工作流基础代码

本章将详细解说工作流基础代码,包含提交申请查看待我审批执行审批操作查看我已审批接口。

4.4. 提交申请

controller层

    @GetMapping("")
    public Boolean addRequest(@RequestBody RequestDTO requestDTO){
      return requestService.addRequest(requestDTO);
    }

 RequestDTO编写

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestDTO {
    private String workflowId;
    private String purpose;
    private String applicantName;
    private String applicantPhone;
    private String applicatUsername;
    private String applicatUnit;
    private String resourceId;

}

servic层

    public Boolean addRequest(RequestDTO requestDTO) {
        Request request= BeanCopyUtils.copyBean(requestDTO,Request.class);
        request.setStatus("1");//设置整个流程状态为正在审核
        // 1. 插入数据到 request 表
        baseMapper.insert(request);


        // 2. 根据 workflow_id 查询业务流程的节点信息,找到 serial_number 为 1 的节点,即流程开始时的第一个节点
        BusinessApprovalWorkflowDetail firstNode = workflowDetailService.findFirstNodeByWorkflowId(request.getWorkflowId());
        //获取下一级节点 填充下级节点审批人
        BusinessApprovalWorkflowDetail nextNode=workflowDetailService.getNextNodeByPreNode(firstNode);

        if (firstNode != null) {
            // 创建一个 approval_detail 记录示例,需要根据具体情况设置字段值
            ApprovalDetail approvalDetail = new ApprovalDetail();
            approvalDetail.setRequestId(request.getId()); // 假设设置关联的 request_id
            approvalDetail.setApproverUsername(firstNode.getNodeUsername()); // 设置首次节点的审批人用户名
            approvalDetail.setApprovalTime(new Date());
            approvalDetail.setNextApproverUsername(nextNode.getNodeUsername());//设置下游节点的审批人用户名
            approvalDetail.setStatus("1"); // 设置初始状态为待审批
            approvalDetail.setWorkflowId(request.getWorkflowId());
            approvalDetail.setNodeName(firstNode.getNodeName());
            approvalDetail.setNextNodeName(nextNode.getNodeName());

            // 插入数据到 approval_detail 表
            approvalDetailService.save(approvalDetail);
        } else {
            // 如果未找到对应的节点,根据实际需求进行错误处理或日志记录
            throw new RuntimeException("Unable to find the first node for workflow id: " + request.getWorkflowId());
        }
        return true;
    }

上述代码实现了一个方法 addRequest,它接收一个 RequestDTO 对象作为参数,首先将其转换为 Request 对象并插入到数据库的 request 表中,设置流程状态为正在审核。然后根据流程定义查询首个审批节点和下一个审批节点的信息,并将这些信息作为审批详情记录插入到 approval_detail 表中,确保申请与审批流程的正确关联和处理。 

4.5. 查看待我审批

controller层

    @GetMapping("/pending-approval")
    public List<ApprovalDetail> getPendingAppprovalList() {
        return approvalDetailService.getPendingAppprovalList();
    }

servic层

    public List<ApprovalDetail> getPendingAppprovalList() {
        //这里我写死了,实际获取应该走权限框架获取当前在线用户username
        String username="xfc";
        LambdaQueryWrapper<ApprovalDetail> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(ApprovalDetail::getApproverUsername,username);
        List<ApprovalDetail> approvalDetails = baseMapper.selectList(queryWrapper);
        return approvalDetails;
    }

4.6. 执行审批操作

controller层

    @PostMapping("/approval")
    public Boolean approvalApplication(@Validated @RequestBody ApprovalDTO approvalDTO) {
        return approvalDetailService.approvalApplication(approvalDTO);
    }

servic层

    @Transactional
    @Override
    public Boolean approvalApplication(ApprovalDTO approvalDTO) {
        // 这里我写死了,实际获取应该走权限框架获取当前在线用户 username
        String username = "xfc";
//        审批人姓名,从用户表中获取
        String name="小肥肠";
        //查询出当前任务节点
        ApprovalDetail approvalDetail = baseMapper.selectById(approvalDTO.getId());
        //获取当前审批的申请信息
        Request request = requestMapper.selectById(approvalDetail.getRequestId());
        if(request==null){
            throw new RuntimeException("申请id有误");
        }

        // 审批通过
        if (approvalDTO.getStatus().equals("2")) {
            // 根据 workflow_id 和 node_name 联查 business_approval_workflow_detail 表,获取当前流程是否为最后节点即 is_final=1
            BusinessApprovalWorkflowDetail currentWorkflowDetail = businessApprovalWorkflowDetailService.findByWorkflowIdAndNodeName(approvalDTO.getWorkflowId(), approvalDetail.getNodeName());

            if (currentWorkflowDetail != null && currentWorkflowDetail.getIsFinal().equals("1")) {
                // 如果是最后节点,则删除该条数据,填充 approval_history 表,根据 request 表修改 request 数据的 status 为 2
                baseMapper.deleteById(approvalDetail.getId()); // 删除当前审批记录
                // 填充 approval_history 表
                ApprovalHistory approvalHistory = new ApprovalHistory();
                approvalHistory.setRequestId(request.getId());
                approvalHistory.setApproverName(name); // 设置审批人姓名,或者从用户表中获取
                approvalHistory.setApprovalTime(new Date());
                approvalHistory.setStatus("2"); // 通过
                approvalHistory.setRemark(approvalDTO.getRemark());
                approvalHistory.setWorkflowId(approvalDTO.getWorkflowId());
                approvalHistory.setApplicantPhone(request.getApplicantPhone());
                approvalHistory.setPurpose(request.getPurpose());
                approvalHistory.setApplicantName(request.getApplicantName());
                approvalHistory.setApproverUsername(username); // 设置审批人用户名,或者从用户表中获取
                approvalHistoryMapper.insert(approvalHistory); // 插入审批历史记录

                // 更新 request 表中的状态为 2(通过)
                    request.setStatus("2");
                    requestMapper.updateById(request);

            } else {
                // 如果不是最后节点,则更新 business_approval_workflow_detail 为下一个节点审批信息
                BusinessApprovalWorkflowDetail nextNode = businessApprovalWorkflowDetailService.getNextNodeByPreNode(currentWorkflowDetail);
//                获取下一级节点的更下一级
                BusinessApprovalWorkflowDetail nextNextNode=businessApprovalWorkflowDetailService.getNextNodeByPreNode(nextNode);
                    // 更新当前 approval_detail 表中的审批人和下一个审批人信息
                    approvalDetail.setApproverUsername(nextNode.getNodeUsername());
                    approvalDetail.setNextApproverUsername(nextNextNode!=null?nextNextNode.getNodeUsername():null);
                    approvalDetail.setApprovalTime(new Date());
                    approvalDetail.setStatus("1"); // 设置为待审批状态
                    baseMapper.updateById(approvalDetail);
            }
        } else if (approvalDTO.getStatus().equals("3")) {
            // 审批驳回
            baseMapper.deleteById(approvalDetail.getId()); // 删除当前审批记录

            // 填充 approval_history 表
            ApprovalHistory approvalHistory = new ApprovalHistory();
            approvalHistory.setRequestId(request.getId());
            approvalHistory.setApproverName(name); // 设置审批人姓名,或者从用户表中获取
            approvalHistory.setApprovalTime(new Date());
            approvalHistory.setStatus("3"); // 驳回
            approvalHistory.setRemark(approvalDTO.getRemark());
            approvalHistory.setWorkflowId(approvalDTO.getWorkflowId());
            approvalHistory.setApplicantPhone(request.getApplicantPhone());
            approvalHistory.setPurpose(request.getPurpose());
            approvalHistory.setApplicantName(request.getApplicantName());
            approvalHistory.setApproverUsername(username); // 设置审批人用户名,或者从用户表中获取
            approvalHistoryMapper.insert(approvalHistory); // 插入审批历史记录

            // 更新 request 表中的状态为 3(驳回)
                request.setStatus("3");
            requestMapper.updateById(request);

        }
        return true; // 或者根据实际需求返回其他业务逻辑
    }

上述方法实现了审批申请的功能。首先,根据审批人的用户名查询当前需要审批的详细信息,并根据审批状态(通过或驳回)进行不同的处理逻辑。如果是审批通过并且当前节点为流程的最后一个节点,则删除当前审批记录并更新申请状态为通过;否则,更新到下一个审批节点的信息。如果是审批驳回,则直接删除当前审批记录,并更新申请状态为驳回。通过事务管理,保证了数据库操作的原子性和一致性。 

4.7. 查看我已审批

controller层

    @GetMapping("/approved")
    public List<ApprovalHistory> getApprovedList() {
        return approvalHistoryService.getApprovedList();
    }

servic层

    public List<ApprovalHistory> getApprovedList() {
        //这里我写死了,实际获取应该走权限框架获取当前在线用户username
        String username="xfc";
        LambdaQueryWrapper<ApprovalHistory>queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(ApprovalHistory::getApproverUsername,username);
        List<ApprovalHistory> approvalHistories = baseMapper.selectList(queryWrapper);
        return approvalHistories;
    }

5. 结语

在本文中,我们系统地介绍了如何用Java语言自创一套工作流引擎。通过设计核心表结构和实现基础代码框架,我们打下了坚实的理论基础。在下篇文章中,我们将结合实际项目,展示工作流引擎的实际应用和效果。我们将深入探讨工作流引擎在复杂业务流程中的应用。如本文对您有帮助,请动动小手点点关注哦~

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

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

相关文章

Oracle--存储结构

总览 一、逻辑存储结构 二、物理存储结构 1.数据文件 2.控制文件 3.日志文件 4.服务器参数文件 5.密码文件 总览 一、逻辑存储结构 数据块是Oracle逻辑存储结构中的最小的逻辑单位&#xff0c;一个数据库块对应一个或者多个物理块&#xff0c;大小由参数DB_BLOCK_SIZE决…

【详细介绍下PostgreSQL】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

matlab-1-函数图像的绘制

常识 如何建一个新文件 创建新文件&#xff0c;点击新建&#xff0c;我们就可以开始写代码了 为什么要在代码开头加入clear 假如我们有2个文件&#xff0c;第一个文件里面给x赋值100&#xff0c;第二个文件为输出x 依次运行&#xff1a; 结果输出100&#xff0c;这是因为它们…

WPF/C#:异常处理

什么是异常&#xff1f; 在C#中&#xff0c;异常是在程序执行过程中发生的特殊情况&#xff0c;例如尝试除以零、访问不存在的文件、网络连接中断等。这些情况会中断程序的正常流程。 当C#程序中发生这种特殊情况时&#xff0c;会创建一个异常对象并将其抛出。这个异常对象包…

Floyd-Warshall

应用场景 要求出每两点之间的最短路。或判断两点之间的连通性&#xff08;两点之间是否有路径&#xff09;。 板子 代码&#xff08;必背!!!&#xff09; for(int k 1; k < n; k)for(int i 1; i < n; i)for(int j 1; j < n; j)d[i][j] min(d[i][j], d[i][k] …

堆的基本概念

堆 堆是一个完全二叉树 完全二叉树的要求&#xff0c;除了最后一层&#xff0c;其他层的节点个数都是满的&#xff0c;最后一层的节点都靠左排列 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值 堆中每个节点的值都大于等于(或者小于等于)其左右子节点的值…

C#(C Sharp)学习笔记_封装【十八】

什么是封装&#xff1f; 封装是面向对象思维的三大特性之一。封装是将数据和对数据进行操作的函数绑定到一起的机制。它隐藏了对象的内部状态和实现细节&#xff0c;只对外提供必要的接口&#xff0c;从而确保对象内部状态的完整性和安全性。封装的主要目的是增强安全性和简化…

登录MySQL方式

登录MySQL方式 方式一&#xff1a;通过MySQL自带的客户端 MySQL 客户端输入命令即可 方式二&#xff1a;通过window自带的客户端 从命令端&#xff08;cmd&#xff09;进入 mysql -h localhost -P 3306 -u root -p Enter password:密码登录方式&#xff1a; mysql -h 主…

【LeetCode最详尽解答】11-盛最多水的容器 Container-With-Most-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; 链接&#xff1a; 11-盛最多水的容器 直觉 这个问题可以通过可视化图表来理解和解决。 通过图形化这个…

基于51单片机万年历设计—显示温度农历

基于51单片机万年历设计 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本系统采用单片机DS1302时钟芯片LCD1602液晶18b20温度传感器按键蜂鸣器设计而成。 1.可以显示年月日、时分秒、星期、温度值。…

mySql的事务(操作一下)

目录 1. 简介2. 事务操作3. 四大特性4. 并发事务问题5. 脏读6. 不可重复读7. 幻读事务隔离级别参考链接 1. 简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作…

机器学习(V)--无监督学习(二)主成分分析

当数据的维度很高时&#xff0c;很多机器学习问题变得相当困难&#xff0c;这种现象被称为维度灾难&#xff08;curse of dimensionality&#xff09;。 在很多实际的问题中&#xff0c;虽然训练数据是高维的&#xff0c;但是与学习任务相关也许仅仅是其中的一个低维子空间&am…

【Java】Object、Objects、包装类、StringBuilder、StringJoiner

目录 1.API2.Object类3.Objects类4.包装类4.1包装类概述4.2包装类的其他常见操作 5.StringBuilder 可变字符串5.1概述5.2StringBuilder案例 6.StringJoiner 1.API API&#xff1a;应用程序编程接口&#xff0c;全称application programing interface&#xff0c;即Java已经写好…

分享一个 .NET Core 使用选项方式读取配置内容的详细例子

前言 在 .NET Core 中&#xff0c;可以使用选项模式&#xff08;Options Pattern&#xff09;来读取和管理应用程序的配置内容。 选项模式通过创建一个 POCO&#xff08;Plain Old CLR Object&#xff09;来表示配置选项&#xff0c;并将其注册到依赖注入容器中&#xff0c;方…

Spring AI探索

Spring AI概述 该Spring AI项目旨在简化包含人工智能功能的应用程序的开发&#xff0c;避免不必要的复杂性。 该项目从著名的 Python 项目&#xff08;例如 LangChain 和 LlamaIndex&#xff09;中汲取灵感&#xff0c;但 Spring AI 并非这些项目的直接移植。该项目的成立基于…

Linux内核编程(五)ioctl驱动编写

本文目录 一、系统层和内核层接口1. ioctl系统层接口2. ioctl内核层接口 二、标准 unlocked_ioctl 接口的命令合成三、代码编程 ioctl 主要用于实现对硬件设备控制类操作&#xff0c;实现 write 和 read 不太好实现的功能。 ioctl 是一个强大的工具&#xff0c;可以用于实现复杂…

​单级高频谐振小放

目录 高频交流等效电路 质量指标 增益 通频带 选择性 高频交流等效电路 质量指标 增益 YL撇是怎么来的。 通频带 选择性

Spark常见的可以优化的点

Shuffle 复用 # 1.以下操作会复用的shuffle结果&#xff0c;只会读一遍数据源 val rdd1 sc.textFile("hdfs://zjyprc-hadoop/tmp/hive-site.xml").flatMap(_.split(" ")).map(x > (x,1)).reduceByKey(_ _).filter(_._2 > 1) rdd1.count() rdd1.fil…

基于dagger平台实现资源位的接口自动化

文章目录 什么是dagger平台&#xff1f;什么是资源位&#xff1f;什么是接口自动化&#xff1f;如何实现接口自动化&#xff1f;内部调用关系基本概念互相引用关系 目录结构具体实现任务&#xff1a;Task用例&#xff1a;Case场景&#xff1a;Scene接口&#xff1a;Api 监控与数…

基于Itô扩散过程的交易策略偏微分方程matlab求解与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于It扩散过程的交易策略偏微分方程,提出了一种确定It扩散过程。通过根据的第一次通过时间来确定问题在这个过程中&#xff0c;我们推导出交易长度的分布函数和密…