精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

工作中最常用的五種工作流引擎

開發(fā) 前端
有些小伙伴在工作中,一提到工作流引擎就頭疼,不知道如何選型,更不清楚它們底層的原理。其實(shí),工作流引擎就像我們生活中的交通信號(hào)系統(tǒng),它負(fù)責(zé)協(xié)調(diào)各個(gè)"路口"(業(yè)務(wù)節(jié)點(diǎn))的通行順序,確保整個(gè)"交通"(業(yè)務(wù)流程)有序進(jìn)行。今天我想和大家聊聊工作中最常用的5種工作流引擎,希望對(duì)你會(huì)有所幫助。

前言

有些小伙伴在工作中,一提到工作流引擎就頭疼,不知道如何選型,更不清楚它們底層的原理。

其實(shí),工作流引擎就像我們生活中的交通信號(hào)系統(tǒng),它負(fù)責(zé)協(xié)調(diào)各個(gè)"路口"(業(yè)務(wù)節(jié)點(diǎn))的通行順序,確保整個(gè)"交通"(業(yè)務(wù)流程)有序進(jìn)行。

今天我想和大家聊聊工作中最常用的5種工作流引擎,希望對(duì)你會(huì)有所幫助。

一、工作流引擎是什么?

在深入具體引擎之前,我們先明確一個(gè)基本概念:工作流引擎本質(zhì)上是業(yè)務(wù)流程自動(dòng)化的核心支撐系統(tǒng)

它負(fù)責(zé)將復(fù)雜的業(yè)務(wù)邏輯分解為多個(gè)任務(wù)節(jié)點(diǎn),并控制這些節(jié)點(diǎn)之間的流轉(zhuǎn)邏輯。

舉個(gè)例子,比如一個(gè)請(qǐng)假審批流程:?jiǎn)T工提交申請(qǐng) → 直接主管審批 → 部門經(jīng)理審批 → HR備案 → 結(jié)束。

如果每個(gè)環(huán)節(jié)都用if-else硬編碼,代碼會(huì)變得極其臃腫且難以維護(hù)。

而工作流引擎通過可視化的方式定義流程,讓業(yè)務(wù)邏輯和流程控制徹底解耦。

為了讓大家更直觀地理解工作流引擎的架構(gòu),我畫了一個(gè)整體架構(gòu)圖:

圖片圖片

這張圖展示了工作流引擎的核心組件。接下來,我們看看為什么要用工作流引擎:

  1. 降低復(fù)雜度:將業(yè)務(wù)流程從業(yè)務(wù)代碼中解耦
  2. 提高可維護(hù)性:流程變更只需修改配置,無需改代碼
  3. 增強(qiáng)可視化:大多數(shù)引擎提供流程設(shè)計(jì)器和監(jiān)控界面
  4. 保證一致性:通過狀態(tài)機(jī)保證業(yè)務(wù)流程的標(biāo)準(zhǔn)執(zhí)行

有些小伙伴在工作中可能會(huì)問:"我們系統(tǒng)業(yè)務(wù)邏輯不復(fù)雜,需要用工作流引擎嗎?"

我的經(jīng)驗(yàn)是:當(dāng)你的業(yè)務(wù)有狀態(tài)流轉(zhuǎn)、多人協(xié)作、需要長(zhǎng)時(shí)間運(yùn)行的特征時(shí),就應(yīng)該考慮使用工作流引擎了。

二、Activiti:企業(yè)級(jí)標(biāo)準(zhǔn)工作流引擎

Activiti可以說是Java領(lǐng)域最老牌、最知名的工作流引擎之一,它最初是jBPM的原作者離開JBoss后創(chuàng)建的。

核心原理

Activiti基于BPMN 2.0標(biāo)準(zhǔn),采用狀態(tài)機(jī)+命令模式的設(shè)計(jì)。

它的核心思想是將業(yè)務(wù)流程抽象為一系列的活動(dòng)節(jié)點(diǎn),通過令牌(Token)在節(jié)點(diǎn)間的流動(dòng)來驅(qū)動(dòng)流程執(zhí)行。

架構(gòu)特點(diǎn)

  • 支持完整的BPMN 2.0元素
  • 采用命令模式,所有操作都封裝為命令
  • 基于狀態(tài)機(jī)管理流程實(shí)例狀態(tài)
  • 支持事務(wù)性流程執(zhí)行

開源地址

GitHub: https://github.com/Activiti/Activiti

示例:請(qǐng)假審批流程

首先在Spring Boot項(xiàng)目中引入依賴:

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M6</version>
</dependency>

定義BPMN 2.0流程文件(leave-approval.bpmn20.xml):

<?xml versinotallow="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
    <process id="leaveApproval" name="請(qǐng)假審批流程" isExecutable="true">
        <!-- 開始事件 -->
        <startEvent id="startEvent" />
        
        <!-- 用戶提交申請(qǐng) -->
        <userTask id="submitLeave" name="提交請(qǐng)假申請(qǐng)" 
                 activiti:assignee="#{employee}"/>
        
        <!-- 主管審批 -->
        <userTask id="leaderApproval" name="直接主管審批"
                 activiti:assignee="#{leader}"/>
        
        <!-- 排他網(wǎng)關(guān):根據(jù)審批結(jié)果決定流向 -->
        <exclusiveGateway id="decisionGateway"/>
        
        <!-- 條件序列流:審批通過 -->
        <sequenceFlow id="flowApproved" sourceRef="decisionGateway" targetRef="hrRecord">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[${approved == true}]]>
            </conditionExpression>
        </sequenceFlow>
        
        <!-- 條件序列流:審批駁回 -->
        <sequenceFlow id="flowRejected" sourceRef="decisionGateway" targetRef="rejectEnd">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[${approved == false}]]>
            </conditionExpression>
        </sequenceFlow>
        
        <!-- HR備案 -->
        <userTask id="hrRecord" name="HR備案" 
                 activiti:assignee="#{hr}"/>
        
        <!-- 結(jié)束事件 -->
        <endEvent id="endEvent" />
    </process>
</definitions>

Java代碼中啟動(dòng)和執(zhí)行流程:

@Service
@Transactional
publicclass LeaveProcessService {
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    @Autowired
    private RepositoryService repositoryService;
    
    // 部署流程定義
    public void deployProcess() {
        repositoryService.createDeployment()
            .addClasspathResource("processes/leave-approval.bpmn20.xml")
            .name("請(qǐng)假審批流程")
            .deploy();
    }
    
    // 啟動(dòng)請(qǐng)假流程
    public void startLeaveProcess(String employee, String leader, int leaveDays) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee", employee);
        variables.put("leader", leader);
        variables.put("hr", "hr_department");
        variables.put("leaveDays", leaveDays);
        // 啟動(dòng)時(shí)尚未有審批結(jié)果,approved變量稍后設(shè)置
        variables.put("approved", null);
        
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
            "leaveApproval", variables);
        
        System.out.println("流程啟動(dòng)成功,實(shí)例ID:" + processInstance.getId());
    }
    
    // 查詢用戶待辦任務(wù)
    public List<Task> getPendingTasks(String assignee) {
        return taskService.createTaskQuery()
            .taskAssignee(assignee)
            .orderByTaskCreateTime().desc()
            .list();
    }
    
    // 完成任務(wù)并傳遞審批結(jié)果
    public void completeTask(String taskId, boolean approved, String comment) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("approved", approved);
        
        // 添加審批意見
        if (comment != null && !comment.trim().isEmpty()) {
            taskService.addComment(taskId, null, comment);
        }
        
        taskService.complete(taskId, variables);
        System.out.println("任務(wù)完成,審批結(jié)果:" + (approved ? "通過" : "駁回"));
    }
}

代碼邏輯深度解析

  1. 流程定義:BPMN文件定義了節(jié)點(diǎn)拓?fù)浣Y(jié)構(gòu),userTask表示人工任務(wù),exclusiveGateway是決策點(diǎn)
  2. 變量傳遞:通過variables映射表在流程實(shí)例中傳遞業(yè)務(wù)數(shù)據(jù)
  3. 任務(wù)查詢:Activiti自動(dòng)維護(hù)任務(wù)狀態(tài),通過TaskQueryAPI查詢待辦
  4. 狀態(tài)持久化:所有流程狀態(tài)自動(dòng)持久化到數(shù)據(jù)庫(kù),保證一致性

有些小伙伴在工作中可能會(huì)遇到Activiti表太多的問題,其實(shí)這是因?yàn)樗捎?/span>分表設(shè)計(jì)ACT_RE_*存儲(chǔ)靜態(tài)定義,ACT_RU_*存儲(chǔ)運(yùn)行時(shí)數(shù)據(jù),ACT_HI_*存儲(chǔ)歷史數(shù)據(jù)。

這種設(shè)計(jì)既保證了運(yùn)行時(shí)性能,又支持歷史追溯。

三、Flowable:Activiti的性能優(yōu)化版

Flowable是Activiti的原班人馬創(chuàng)建的分支項(xiàng)目,在性能和云原生支持方面有顯著改進(jìn)。

它完全兼容Activiti的API,但內(nèi)部進(jìn)行了大量?jī)?yōu)化。

核心原理

Flowable在Activiti的基礎(chǔ)上引入了異步執(zhí)行器執(zhí)行樹優(yōu)化。

它通過更精細(xì)的鎖管理和批量處理來提升高并發(fā)下的性能。

架構(gòu)改進(jìn)

  • 增強(qiáng)的異步執(zhí)行器,支持批量操作
  • 優(yōu)化的執(zhí)行樹結(jié)構(gòu),減少數(shù)據(jù)庫(kù)訪問
  • 更好的緩存管理和懶加載策略
  • 原生支持Spring Boot Starter

開源地址

GitHub: https://github.com/flowable/flowable-engine

示例:訂單處理流程(含服務(wù)任務(wù))

Flowable特別擅長(zhǎng)處理自動(dòng)化業(yè)務(wù)流程,下面是一個(gè)訂單處理示例:

@Service
publicclass OrderProcessService {
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private RepositoryService repositoryService;
    
    // 部署訂單流程
    public void deployOrderProcess() {
        repositoryService.createDeployment()
            .addClasspathResource("processes/order-process.bpmn20.xml")
            .addClasspathResource("processes/order-discount.dmn") // DMN決策表
            .deploy();
    }
    
    // 啟動(dòng)訂單流程
    public void startOrderProcess(Order order) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("order", order);
        variables.put("customerService", "cs_team");
        variables.put("warehouse", "wh_team");
        
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
            "orderProcess", order.getOrderNo(), variables);
        
        logger.info("訂單流程啟動(dòng): {}", processInstance.getId());
    }
}

// 服務(wù)任務(wù)處理器 - 庫(kù)存檢查
@Component
publicclass InventoryCheckDelegate implements JavaDelegate {
    
    @Autowired
    private InventoryService inventoryService;
    
    @Override
    public void execute(DelegateExecution execution) {
        Order order = (Order) execution.getVariable("order");
        
        // 調(diào)用庫(kù)存服務(wù)檢查庫(kù)存
        boolean inStock = inventoryService.checkInventory(
            order.getProductId(), order.getQuantity());
        
        execution.setVariable("inStock", inStock);
        
        if (!inStock) {
            execution.setVariable("needBackorder", true);
            logger.warn("產(chǎn)品{}庫(kù)存不足,需要備貨", order.getProductId());
        }
    }
}

// 服務(wù)任務(wù)處理器 - 支付處理
@Component
publicclass PaymentProcessDelegate implements JavaDelegate {
    
    @Autowired
    private PaymentService paymentService;
    
    @Override
    public void execute(DelegateExecution execution) {
        Order order = (Order) execution.getVariable("order");
        
        try {
            // 調(diào)用支付網(wǎng)關(guān)
            PaymentResult result = paymentService.processPayment(order);
            execution.setVariable("paymentSuccess", result.isSuccess());
            execution.setVariable("paymentId", result.getPaymentId());
            
        } catch (Exception e) {
            execution.setVariable("paymentSuccess", false);
            execution.setVariable("paymentError", e.getMessage());
            thrownew RuntimeException("支付處理失敗", e);
        }
    }
}

對(duì)應(yīng)的BPMN流程包含服務(wù)任務(wù):

<process id="orderProcess" name="訂單處理流程">
    <startEvent id="start" />
    
    <!-- 庫(kù)存檢查服務(wù)任務(wù) -->
    <serviceTask id="inventoryCheck" name="庫(kù)存檢查"
                 activiti:class="com.example.InventoryCheckDelegate"/>
    
    <!-- 庫(kù)存決策網(wǎng)關(guān) -->
    <exclusiveGateway id="inventoryDecision" />
    
    <!-- 有庫(kù)存流程 -->
    <sequenceFlow id="inStockFlow" sourceRef="inventoryDecision" targetRef="paymentProcess">
        <conditionExpression>${inStock == true}</conditionExpression>
    </sequenceFlow>
    
    <!-- 無庫(kù)存流程 -->
    <sequenceFlow id="outOfStockFlow" sourceRef="inventoryDecision" targetRef="backorderTask">
        <conditionExpression>${inStock == false}</conditionExpression>
    </sequenceFlow>
    
    <!-- 支付處理 -->
    <serviceTask id="paymentProcess" name="支付處理"
                 activiti:class="com.example.PaymentProcessDelegate"/>
    
    <!-- 備貨任務(wù) -->
    <userTask id="backorderTask" name="備貨處理" 
              activiti:assignee="#{warehouse}"/>
    
    <endEvent id="end" />
</process>

深度原理剖析

  1. 服務(wù)任務(wù)異步執(zhí)行:Flowable的JavaDelegate默認(rèn)支持異步執(zhí)行,避免阻塞主線程
  2. 執(zhí)行樹優(yōu)化:Flowable將流程執(zhí)行建模為執(zhí)行樹,減少狀態(tài)同步開銷
  3. 批量事件處理:多個(gè)流程實(shí)例的事件可以批量處理,提升吞吐量
  4. DMN集成:內(nèi)置DMN決策引擎,支持復(fù)雜業(yè)務(wù)規(guī)則

有些小伙伴在工作中處理高并發(fā)場(chǎng)景時(shí),F(xiàn)lowable的異步執(zhí)行器特別有用。

它能夠?qū)⒑臅r(shí)的服務(wù)任務(wù)放入消息隊(duì)列異步處理,避免數(shù)據(jù)庫(kù)長(zhǎng)事務(wù)。

四、Camunda:微服務(wù)架構(gòu)的首選

Camunda是另一個(gè)流行的Activiti分支,特別強(qiáng)調(diào)運(yùn)維監(jiān)控微服務(wù)集成能力。

它提供了完整的操作工具鏈。

核心原理

Camunda采用外部任務(wù)模式樂觀鎖并發(fā)控制。它的核心思想是將工作流引擎與業(yè)務(wù)服務(wù)解耦,通過外部任務(wù)隊(duì)列實(shí)現(xiàn)松耦合集成。

架構(gòu)特色

  • 外部任務(wù)模式,支持多語(yǔ)言客戶端
  • 完整的監(jiān)控工具Cockpit和Tasklist
  • 基于樂觀鎖的高并發(fā)控制
  • 原生支持微服務(wù)架構(gòu)模式

開源地址

GitHub: https://github.com/camunda/camunda-bpm-platform

示例:貸款審批流程(外部任務(wù)模式)

Camunda的外部任務(wù)模式特別適合微服務(wù)架構(gòu):

// 貸款申請(qǐng)DTO
@Data
publicclass LoanApplication {
    private String applicationId;
    private String applicantName;
    privatedouble amount;
    privateint duration;
    privatedouble income;
    privateint creditScore;
}

// 貸款流程啟動(dòng)服務(wù)
@Service
@Transactional
publicclass LoanProcessService {
    
    @Autowired
    private RuntimeService runtimeService;
    
    public void startLoanProcess(LoanApplication application) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("application", application);
        variables.put("creditCheckRequired", application.getAmount() > 100000);
        variables.put("autoApprovalLimit", 50000.0);
        
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
            "loanApprovalProcess", application.getApplicationId(), variables);
        
        logger.info("貸款流程啟動(dòng): {}", processInstance.getId());
    }
}

// 征信檢查外部任務(wù)工作者
@Component
publicclass CreditCheckWorker {
    
    @Autowired
    private ExternalTaskService externalTaskService;
    
    @Autowired
    private CreditService creditService;
    
    @PostConstruct
    public void startCreditCheckWorker() {
        new Thread(() -> {
            while (true) {
                try {
                    // 獲取外部任務(wù)
                    List<LockedExternalTask> tasks = externalTaskService
                        .fetchAndLock(10, "credit-check-worker")
                        .topic("credit-check", 60000L)
                        .execute();
                    
                    for (LockedExternalTask task : tasks) {
                        processCreditCheck(task);
                    }
                    
                    Thread.sleep(5000); // 5秒輪詢
                    
                } catch (Exception e) {
                    logger.error("征信檢查工作者異常", e);
                }
            }
        }).start();
    }
    
    private void processCreditCheck(LockedExternalTask task) {
        try {
            LoanApplication application = (LoanApplication) 
                task.getVariable("application");
            
            // 調(diào)用外部征信系統(tǒng)
            CreditReport report = creditService.getCreditReport(
                application.getApplicantName(), application.getApplicantId());
            
            Map<String, Object> variables = new HashMap<>();
            variables.put("creditReport", report);
            variables.put("creditScore", report.getScore());
            variables.put("creditCheckPassed", report.getScore() > 600);
            
            // 完成任務(wù)
            externalTaskService.complete(task.getId(), "credit-check-worker", variables);
            
            logger.info("征信檢查完成: {}", application.getApplicationId());
            
        } catch (Exception e) {
            // 處理失敗,解鎖任務(wù)以便重試
            externalTaskService.handleFailure(task.getId(), "credit-check-worker", 
                e.getMessage(), 3, 30000L);
        }
    }
}

// 風(fēng)險(xiǎn)評(píng)估外部任務(wù)工作者
@Component
publicclass RiskAssessmentWorker {
    
    @Autowired
    private RiskService riskService;
    
    public void startRiskAssessmentWorker() {
        // 類似的實(shí)現(xiàn)模式
        // 訂閱"risk-assessment"主題
    }
}

Camunda還提供強(qiáng)大的運(yùn)維監(jiān)控能力:

// 流程實(shí)例監(jiān)控
@Service
publicclass ProcessMonitorService {
    
    @Autowired
    private HistoryService historyService;
    
    @Autowired
    private ManagementService managementService;
    
    // 獲取流程實(shí)例統(tǒng)計(jì)
    public Map<String, Object> getProcessStats(String processDefinitionKey) {
        Map<String, Object> stats = new HashMap<>();
        
        // 運(yùn)行中實(shí)例數(shù)量
        long runningInstances = historyService.createHistoricProcessInstanceQuery()
            .processDefinitionKey(processDefinitionKey)
            .unfinished()
            .count();
        
        // 今日完成數(shù)量
        long todayCompleted = historyService.createHistoricProcessInstanceQuery()
            .processDefinitionKey(processDefinitionKey)
            .finishedAfter(TemporalUtil.todayStart())
            .count();
        
        // 平均處理時(shí)間
        HistoricProcessInstanceQuery query = historyService
            .createHistoricProcessInstanceQuery()
            .processDefinitionKey(processDefinitionKey)
            .finished();
        
        stats.put("runningInstances", runningInstances);
        stats.put("todayCompleted", todayCompleted);
        stats.put("avgDuration", calculateAverageDuration(query));
        
        return stats;
    }
}

架構(gòu)深度解析

  1. 外部任務(wù)模式:業(yè)務(wù)邏輯在引擎外部執(zhí)行,支持多語(yǔ)言和技術(shù)棧
  2. 主題訂閱機(jī)制:工作者訂閱特定主題的任務(wù),實(shí)現(xiàn)關(guān)注點(diǎn)分離
  3. 樂觀鎖控制:通過版本號(hào)避免并發(fā)沖突,提高吞吐量
  4. 完整的運(yùn)維體系:Cockpit提供實(shí)時(shí)監(jiān)控,Optimize提供流程分析

Camunda的這種設(shè)計(jì)特別適合微服務(wù)架構(gòu),每個(gè)微服務(wù)可以獨(dú)立開發(fā)部署,通過外部任務(wù)與工作流引擎交互。

五、jBPM:規(guī)則集成的最佳選擇

jBPM是紅帽旗下的開源BPM套件,基于KIE(Knowledge Is Everything)平臺(tái),與Drools規(guī)則引擎深度集成。

核心原理

jBPM采用知識(shí)會(huì)話模式,將流程引擎和規(guī)則引擎統(tǒng)一在同一個(gè)會(huì)話中。

這種設(shè)計(jì)使得業(yè)務(wù)流程和業(yè)務(wù)規(guī)則能夠無縫協(xié)作。

架構(gòu)特色

  • 與Drools規(guī)則引擎深度集成
  • 基于知識(shí)會(huì)話的統(tǒng)一執(zhí)行環(huán)境
  • 支持BPMN 2.0和CMN(案例管理)
  • 完整的生命周期管理

開源地址

GitHub: https://github.com/kiegroup/jbpm

示例:保險(xiǎn)理賠流程(規(guī)則集成)

jBPM最大的優(yōu)勢(shì)在于規(guī)則和流程的集成:

// 保險(xiǎn)理賠DTO
@Data
publicclass InsuranceClaim {
    private String claimId;
    private String policyNumber;
    private String claimType; // AUTO, HEALTH, PROPERTY
    privatedouble claimAmount;
    private Date incidentDate;
    private String description;
    privateboolean fraudulent = false;
    privatedouble approvedAmount = 0.0;
}

// 理賠流程服務(wù)
@Service
publicclass ClaimProcessService {
    
    @Autowired
    private RuntimeEngine runtimeEngine;
    
    @Autowired
    private KieContainer kieContainer;
    
    public void startClaimProcess(InsuranceClaim claim) {
        // 創(chuàng)建KIE會(huì)話
        KieSession kieSession = kieContainer.newKieSession();
        
        try {
            // 插入事實(shí)對(duì)象到規(guī)則引擎
            kieSession.insert(claim);
            kieSession.insert(new Date());
            
            // 啟動(dòng)流程實(shí)例
            ProcessInstance processInstance = runtimeEngine.getKieSession()
                .startProcess("claimApprovalProcess", 
                    createProcessVariables(claim));
            
            logger.info("理賠流程啟動(dòng): {}", processInstance.getId());
            
        } finally {
            kieSession.dispose();
        }
    }
    
    private Map<String, Object> createProcessVariables(InsuranceClaim claim) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("claim", claim);
        variables.put("claimAmount", claim.getClaimAmount());
        variables.put("claimType", claim.getClaimType());
        variables.put("autoApprovalLimit", 5000.0);
        variables.put("requiresManagerApproval", claim.getClaimAmount() > 10000);
        return variables;
    }
}

// 欺詐檢測(cè)規(guī)則(DRL文件)
rule "High Amount Fraud Detection"
    when
        $claim : InsuranceClaim(claimAmount > 50000)
        Date() // 當(dāng)前日期
    then
        $claim.setFraudulent(true);
        modify($claim);
        System.out.println("檢測(cè)到大額理賠,標(biāo)記為可疑欺詐: " + $claim.getClaimId());
end

rule "Quick Claim Fraud Detection"
    when
        $claim : InsuranceClaim(incidentDate after [30d] )
        // 事故日期在30天內(nèi)的快速理賠
    then
        $claim.setFraudulent(true);
        modify($claim);
        System.out.println("快速理賠標(biāo)記為可疑: " + $claim.getClaimId());
end

rule "Auto Approval for Small Claims"
    when
        $claim : InsuranceClaim(claimAmount <= 5000, fraudulent == false)
    then
        $claim.setApprovedAmount($claim.getClaimAmount());
        modify($claim);
        System.out.println("小額理賠自動(dòng)批準(zhǔn): " + $claim.getClaimId());
end

流程定義中集成規(guī)則任務(wù):

<process id="claimApprovalProcess" name="保險(xiǎn)理賠審批流程">
    
    <startEvent id="start" />
    
    <!-- 規(guī)則任務(wù):欺詐檢測(cè) -->
    <businessRuleTask id="fraudDetection" name="欺詐檢測(cè)"
                      g:ruleFlowGroup="fraud-detection" />
    
    <!-- 網(wǎng)關(guān):基于欺詐檢測(cè)結(jié)果路由 -->
    <exclusiveGateway id="fraudDecision" />
    
    <!-- 檢測(cè)到欺詐 -->
    <sequenceFlow id="fraudDetected" sourceRef="fraudDecision" targetRef="investigateFraud">
        <conditionExpression>${claim.fraudulent == true}</conditionExpression>
    </sequenceFlow>
    
    <!-- 無欺詐 -->
    <sequenceFlow id="noFraud" sourceRef="fraudDecision" targetRef="approvalDecision">
        <conditionExpression>${claim.fraudulent == false}</conditionExpression>
    </sequenceFlow>
    
    <!-- 規(guī)則任務(wù):自動(dòng)理賠決策 -->
    <businessRuleTask id="approvalDecision" name="理賠決策"
                      g:ruleFlowGroup="claim-approval" />
    
    <!-- 欺詐調(diào)查人工任務(wù) -->
    <userTask id="investigateFraud" name="欺詐調(diào)查"
              g:assignee="fraud_investigator" />
    
    <endEvent id="end" />
</process>

深度集成原理

  1. 統(tǒng)一知識(shí)會(huì)話:流程實(shí)例和規(guī)則引擎共享同一個(gè)KIE會(huì)話
  2. 事實(shí)對(duì)象同步:流程變量自動(dòng)作為事實(shí)插入規(guī)則引擎
  3. 規(guī)則流組:通過規(guī)則流組控制規(guī)則執(zhí)行順序
  4. 動(dòng)態(tài)規(guī)則更新:支持運(yùn)行時(shí)更新業(yè)務(wù)規(guī)則而不影響流程實(shí)例

有些小伙伴在處理復(fù)雜業(yè)務(wù)規(guī)則時(shí),jBPM的這種集成模式特別有價(jià)值。

比如在風(fēng)控場(chǎng)景中,反欺詐規(guī)則經(jīng)常變化,使用jBPM可以獨(dú)立更新規(guī)則而不需要修改流程定義。

六、JDEasyFlow:輕量級(jí)流程編排新星

JDEasyFlow是京東自研的輕量級(jí)流程編排組件,特點(diǎn)是簡(jiǎn)單、靈活、易擴(kuò)展。

它適用于不需要完整BPMN功能的簡(jiǎn)單場(chǎng)景。

核心原理

JDEasyFlow采用基于JSON的流程定義狀態(tài)機(jī)引擎。

它的設(shè)計(jì)理念是"約定優(yōu)于配置",通過簡(jiǎn)單的節(jié)點(diǎn)定義實(shí)現(xiàn)靈活的流程編排。

架構(gòu)特色

  • 基于JSON的聲明式流程定義
  • 無數(shù)據(jù)庫(kù)依賴,純內(nèi)存執(zhí)行
  • 支持BPMN元素子集
  • 極低的學(xué)習(xí)成本

開源地址

GitHub: https://github.com/JDEasyFlow/jd-easyflow

示例:簡(jiǎn)單訂單狀態(tài)流轉(zhuǎn)

JDEasyFlow特別適合簡(jiǎn)單的狀態(tài)機(jī)場(chǎng)景:

首先引入依賴:

<dependency>
    <groupId>com.jd.easyflow</groupId>
    <artifactId>easyflow-flow</artifactId>
    <version>1.2.0</version>
</dependency>

定義訂單狀態(tài)流程JSON:

{
  "id": "order_flow",
"name": "訂單狀態(tài)流程",
"nodes": [
    {
      "id": "created",
      "name": "訂單創(chuàng)建",
      "start": true,
      "post": {
        "to": "paid"
      }
    },
    {
      "id": "paid",
      "name": "已支付",
      "action": {
        "createExp": "new com.example.order.PaymentAction()"
      },
      "post": {
        "to": "shipped"
      }
    },
    {
      "id": "shipped",
      "name": "已發(fā)貨",
      "action": {
        "createExp": "new com.example.order.ShipmentAction()"
      },
      "post": {
        "to": "received"
      }
    },
    {
      "id": "received",
      "name": "已收貨",
      "action": {
        "createExp": "new com.example.order.ReceiveAction()"
      },
      "post": {
        "to": "completed"
      }
    },
    {
      "id": "completed",
      "name": "已完成"
    },
    {
      "id": "cancelled",
      "name": "已取消"
    }
  ]
}

Java節(jié)點(diǎn)動(dòng)作實(shí)現(xiàn):

// 支付節(jié)點(diǎn)動(dòng)作
@Component
publicclass PaymentAction implements FlowNodeAction {
    
    @Autowired
    private PaymentService paymentService;
    
    @Override
    public Object execute(FlowRequest request, FlowContext context) {
        String orderId = (String) request.getParam("orderId");
        
        // 執(zhí)行支付邏輯
        PaymentResult result = paymentService.confirmPayment(orderId);
        
        // 設(shè)置節(jié)點(diǎn)輸出
        Map<String, Object> resultData = new HashMap<>();
        resultData.put("paymentId", result.getPaymentId());
        resultData.put("paymentTime", result.getPaymentTime());
        resultData.put("success", result.isSuccess());
        
        logger.info("訂單{}支付處理完成", orderId);
        
        return resultData;
    }
}

// 發(fā)貨節(jié)點(diǎn)動(dòng)作
@Component
publicclass ShipmentAction implements FlowNodeAction {
    
    @Autowired
    private LogisticsService logisticsService;
    
    @Override
    public Object execute(FlowRequest request, FlowContext context) {
        String orderId = (String) request.getParam("orderId");
        
        // 調(diào)用物流服務(wù)發(fā)貨
        ShipmentInfo shipment = logisticsService.createShipment(orderId);
        
        Map<String, Object> resultData = new HashMap<>();
        resultData.put("shipmentId", shipment.getShipmentId());
        resultData.put("shipmentTime", shipment.getShipmentTime());
        resultData.put("logisticsCompany", shipment.getCompany());
        
        logger.info("訂單{}發(fā)貨完成,物流單號(hào): {}", orderId, shipment.getShipmentId());
        
        return resultData;
    }
}

流程引擎配置和使用:

@Configuration
publicclass EasyFlowConfig {
    
    @Bean
    public FlowEngine flowEngine() {
        FlowEngineImpl flowEngine = new FlowEngineImpl();
        flowEngine.setFlowPath("classpath:flows/order_flow.json");
        flowEngine.init();
        return flowEngine;
    }
}

@Service
publicclass OrderFlowService {
    
    @Autowired
    private FlowEngine flowEngine;
    
    // 執(zhí)行訂單流程
    public void processOrder(String orderId, String action) {
        Map<String, Object> params = new HashMap<>();
        params.put("orderId", orderId);
        params.put("action", action);
        
        FlowParam flowParam = new FlowParam("order_flow", params);
        
        // 執(zhí)行流程
        FlowResult result = flowEngine.execute(flowParam);
        
        if (result.isSuccess()) {
            logger.info("訂單流程執(zhí)行成功: {}", result.getNodeIds());
        } else {
            logger.error("訂單流程執(zhí)行失敗: {}", result.getMessage());
            thrownew RuntimeException("流程執(zhí)行失敗: " + result.getMessage());
        }
    }
    
    // 獲取下一個(gè)可用節(jié)點(diǎn)
    public List<String> getNextNodes(String orderId, String currentNode) {
        Map<String, Object> params = new HashMap<>();
        params.put("orderId", orderId);
        
        FlowParam flowParam = new FlowParam("order_flow", params);
        
        // 解析流程定義,獲取后續(xù)節(jié)點(diǎn)
        return flowEngine.getNextNodes(flowParam, currentNode);
    }
}

輕量級(jí)架構(gòu)解析

  1. JSON定義:通過簡(jiǎn)單的JSON結(jié)構(gòu)定義節(jié)點(diǎn)和流轉(zhuǎn)
  2. 無持久化:純內(nèi)存執(zhí)行,性能極高
  3. 插件化動(dòng)作:通過接口實(shí)現(xiàn)業(yè)務(wù)邏輯
  4. 條件支持:支持簡(jiǎn)單的條件表達(dá)式路由

JDEasyFlow的這種設(shè)計(jì)特別適合服務(wù)編排簡(jiǎn)單狀態(tài)機(jī)場(chǎng)景。

有些小伙伴在微服務(wù)架構(gòu)中需要編排多個(gè)服務(wù)調(diào)用,但又不想引入沉重的BPMN引擎,JDEasyFlow是完美選擇。

七、五種工作流引擎全面對(duì)比

為了幫助大家更好地進(jìn)行技術(shù)選型,我整理了這五種工作流引擎的詳細(xì)對(duì)比:

特性維度

Activiti

Flowable

Camunda

jBPM

JDEasyFlow

學(xué)習(xí)曲線

中等

中等

較陡

較陡

簡(jiǎn)單

性能

良好

優(yōu)秀

優(yōu)秀

良好

極佳

功能完備性

很高

中等

監(jiān)控運(yùn)維

基礎(chǔ)

良好

優(yōu)秀

良好

簡(jiǎn)單

社區(qū)生態(tài)

活躍

活躍

活躍

活躍

一般

云原生支持

基礎(chǔ)

良好

優(yōu)秀

良好

良好

規(guī)則集成

基礎(chǔ)

基礎(chǔ)

良好

優(yōu)秀

適用場(chǎng)景

傳統(tǒng)企業(yè)應(yīng)用

高性能業(yè)務(wù)

微服務(wù)架構(gòu)

規(guī)則密集型

輕量級(jí)編排

為了更直觀地展示選型邏輯,我畫了一個(gè)決策流程圖:

圖片圖片

八、總結(jié)

下面我們來總結(jié)一下工作流引擎選型的一些建議:

  1. 傳統(tǒng)企業(yè)級(jí)應(yīng)用:選擇Activiti,生態(tài)成熟,文檔豐富,遇到問題容易找到解決方案
  2. 高性能高并發(fā)場(chǎng)景:選擇Flowable,它在Activiti基礎(chǔ)上做了大量性能優(yōu)化
  3. 微服務(wù)架構(gòu):選擇Camunda,外部任務(wù)模式完美契合微服務(wù)理念,運(yùn)維監(jiān)控工具完善
  4. 規(guī)則密集型業(yè)務(wù):選擇jBPM,與Drools規(guī)則引擎深度集成,適合風(fēng)控、保險(xiǎn)等場(chǎng)景
  5. 輕量級(jí)服務(wù)編排:選擇JDEasyFlow,簡(jiǎn)單靈活,學(xué)習(xí)成本低,無外部依賴

有些小伙伴在工作中可能會(huì)想:"能不能一個(gè)項(xiàng)目用多種工作流引擎?"

我的經(jīng)驗(yàn)是:可以,但要明確邊界。

比如用Camunda管理核心業(yè)務(wù)流程,用JDEasyFlow做微服務(wù)內(nèi)部編排。

最后記?。?/span>沒有最好的工作流引擎,只有最合適的。

選型時(shí)要綜合考慮團(tuán)隊(duì)技術(shù)棧、業(yè)務(wù)場(chǎng)景、性能要求和運(yùn)維能力。

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2025-11-10 02:11:00

2024-12-11 08:20:57

設(shè)計(jì)模式源碼

2025-11-18 08:22:56

2025-08-12 08:22:29

2024-03-18 08:22:15

OOM問題java線上問題

2021-10-14 11:34:05

技術(shù)工作流引擎

2024-04-28 11:22:18

2024-05-09 08:19:09

OOMJVM內(nèi)存

2015-07-14 09:26:28

微型工作流引擎設(shè)計(jì)

2023-01-04 08:02:16

工作流架構(gòu)設(shè)計(jì)

2023-07-05 09:48:44

Activiti部署

2011-12-14 09:58:58

JavajBPM

2023-08-02 18:48:23

Flowable工作流引擎

2009-06-11 14:43:34

jbpm工作流引擎jBPM搭建

2009-09-01 18:26:23

C#工作流引擎

2024-10-17 08:39:32

2021-09-16 11:02:49

Python線程

2021-03-12 06:44:09

Argo Workfl開源項(xiàng)目

2022-10-26 08:00:43

Activiti工作流BPM

2021-12-17 08:39:39

SpringbootActiviti網(wǎng)關(guān)路由
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

丝袜美腿中文字幕| 国产精品夜夜夜一区二区三区尤| 人妻丰满熟妇av无码久久洗澡| 91cn在线观看| 国产成人8x视频一区二区| 美日韩在线视频| 国产大学生av| 人狥杂交一区欧美二区| 91香蕉视频污| 国产精品人成电影| 日韩在线观看视频一区二区| aaa国产精品| 黄色精品一区二区| 日本一区不卡| 国产999久久久| 中文亚洲字幕| 中文字幕精品一区久久久久| 色综合五月婷婷| 超碰91在线观看| 久久色视频免费观看| 国产日韩av在线播放| 免费一级肉体全黄毛片| 亚洲系列另类av| 91精品国产欧美一区二区成人| 一区二区三区av在线| 不卡的日韩av| 日本美女视频一区二区| 欧美成人精品不卡视频在线观看| free性中国hd国语露脸| 亚洲免费资源| 日韩欧美精品免费在线| 国产精品h视频| 亚洲人视频在线观看| 精品在线亚洲视频| 欧美人交a欧美精品| 亚洲国产av一区| 狂野欧美xxxx韩国少妇| 色综合婷婷久久| 熟女视频一区二区三区| www.污视频| 日本在线不卡一区| 性色av一区二区咪爱| 美国一级片在线观看| 99ri日韩精品视频| 欧美日韩高清在线| 人妻内射一区二区在线视频| 超碰在线观看免费| 国产精品午夜春色av| 91免费观看| 亚洲天堂视频网| 乱码第一页成人| 久久久久国色av免费观看性色| 污污视频网站在线免费观看| 8x国产一区二区三区精品推荐| 欧美日韩一区二区三区四区| 人妻精品无码一区二区三区| 玖玖精品在线视频| 国产又黄又爽又色| 在线观看视频免费一区二区三区| 亚洲深夜福利视频| 中文字幕在线播放视频| 99国产精品免费网站| 日韩一区二区免费高清| 天堂av8在线| 激情小说亚洲| 欧美少妇性性性| 国产a级片免费观看| 筱崎爱全乳无删减在线观看| 亚洲福利一区二区| 野外做受又硬又粗又大视频√| 国产在线高清视频| 中文字幕一区二区三区不卡| 亚洲精品人成| av午夜在线| 国产人久久人人人人爽| 欧美一区激情视频在线观看| 男女污污视频在线观看| 久久女同精品一区二区| 欧美日韩亚洲在线| 你懂的视频在线播放| 成人在线一区二区三区| 国产精品一区二区三区在线观| 国产香蕉在线观看| 麻豆91在线播放免费| 国产日本欧美一区| a天堂视频在线| 国产成人免费视频精品含羞草妖精| 国产精品免费小视频| 中文字幕福利视频| 国产原创一区二区| 成人欧美一区二区三区视频xxx| 精品人妻久久久久一区二区三区| 国产精品一区二区三区四区| 国产高清在线精品一区二区三区| 99在线观看免费| 国产精品一区二区久久精品爱涩| 99一区二区| 天天操天天射天天舔| 91在线国产福利| 日韩精品另类天天更新| 国产鲁鲁视频在线观看特色| 亚洲综合色网站| 欧美国产激情视频| 欧美亚洲综合视频| 欧美成人vr18sexvr| 国内自拍偷拍视频| 亚州国产精品| 日韩视频在线免费| 国产无遮挡aaa片爽爽| 老司机午夜精品视频| 成人av番号网| 欧美一级淫片免费视频魅影视频| 久久综合久久综合亚洲| 黄色高清视频网站| 2001个疯子在线观看| 欧美亚洲综合网| 韩国三级在线播放| 久久99国内| 欧美精品在线极品| 一级片免费在线播放| 国产综合色在线视频区| 国产一区二区在线网站| av中文资源在线| 亚洲国产精品一区二区www| 日日摸天天爽天天爽视频| 国产精品视频一区视频二区 | 捆绑调教美女网站视频一区| av色综合网| 国产黄色在线| 亚洲国产三级在线| 亚欧美在线观看| 香蕉精品久久| 欧美国产日本高清在线| 亚洲天堂男人网| 91麻豆免费观看| 亚洲一区三区电影在线观看| 黄页在线观看免费| 欧美日本一区二区| 欧美做受xxxxxⅹ性视频| 久久久精品久久久久久96| 欧美中文字幕在线视频| www.香蕉视频| 国产精品久久久久桃色tv| 超碰超碰超碰超碰超碰| 成人黄色在线| 日韩精品免费视频| 国产亚洲精品成人| 国产伦精品一区二区三区在线观看| 免费看国产精品一二区视频| 超黄网站在线观看| 日韩欧美中文一区| 疯狂试爱三2浴室激情视频| 日本成人在线电影网| 精品国产乱码久久久久久蜜柚| 最新av在线播放| 91精品国产综合久久久久久久久久| 日韩丰满少妇无码内射| 午夜亚洲性色视频| 91精品国产99久久久久久红楼 | 高清国语自产拍免费一区二区三区| 伊人免费在线| 一道本成人在线| 人妻熟女aⅴ一区二区三区汇编| 亚洲裸体俱乐部裸体舞表演av| 99re在线播放| 在线免费观看a视频| 777欧美精品| 欧美大片xxxx| 九色porny丨国产精品| 在线免费一区| 国产精品久久久久久久久久辛辛 | 亚洲精品xxx| 久久精品性爱视频| 丁香婷婷综合网| 2019日韩中文字幕mv| 国产成人福利av| 777午夜精品福利在线观看| 亚洲欧美日韩精品永久在线| 欧美性少妇18aaaa视频| 欧洲女同同性吃奶| 日韩国产精品91| 午夜精品一区二区在线观看| 欧美日韩亚洲国产| 少妇高潮久久77777| 中文字幕第315页| 日韩毛片高清在线播放| 人妻巨大乳一二三区| 雨宫琴音一区二区在线| 九九久久99| 日本综合视频| 伊人久久免费视频| 91精品视频免费在线观看| 亚洲美女屁股眼交| 99九九99九九九99九他书对| 国产精品99一区二区| 国产欧美日韩视频一区二区三区| 午夜久久中文| 日韩一区二区三区国产| 性欧美8khd高清极品| 亚洲精品日日夜夜| 最新在线黄色网址| 美女国产一区二区三区| 青青草原国产免费| 91精品尤物| 日本高清+成人网在线观看| 欧美a在线看| 亚洲第一区在线| 自拍偷拍色综合| 一区二区三区四区在线免费观看 | 久草视频精品在线| 久久精品一区二区三区四区| 国产精品久久久久久久av福利| 亚洲黄色天堂| 亚洲一区二区在| 欧美性生活一级片| 成人性教育视频在线观看| 国产中文在线播放| 久久精品人人爽| 色就是色亚洲色图| 91精品国产综合久久蜜臀| 日日摸天天添天天添破| 亚洲日本在线天堂| 尤物视频最新网址| 懂色av一区二区三区免费看| 国产主播中文字幕| 亚洲毛片av| 亚洲v国产v| 精品精品国产毛片在线看| 成人黄色生活片| 中文字幕影音在线| 欧美成人一二三| 99青草视频在线播放视| 欧美一级片在线观看| 波多野结衣小视频| 亚洲成在人线在线播放| 97**国产露脸精品国产| 神马精品久久| 亚洲激情视频在线播放| 成人高潮片免费视频| 91超碰这里只有精品国产| 亚洲怡红院av| 欧美日韩在线播放三区| 久草视频在线免费| 欧美一a一片一级一片| 国产情侣小视频| 在线一区二区三区四区五区| 国产综合精品视频| 欧美午夜丰满在线18影院| 可以免费看的av毛片| 亚洲一线二线三线视频| 欧美日韩激情在线观看| 一二三四社区欧美黄| 国产一级在线观看视频| 午夜视频在线观看一区二区| 日产电影一区二区三区| 午夜精品成人在线视频| 欧美亚洲精品天堂| 一本色道久久综合狠狠躁的推荐| 中文字幕精品无码一区二区| 欧美性高潮床叫视频| 加勒比在线一区| 在线观看视频一区二区欧美日韩| 中文字幕 亚洲视频| 欧美日韩国产a| 亚洲精品中文字幕成人片| 亚洲第一av网| 欧美色图另类| 深夜福利一区二区| av网站大全在线| 高清在线视频日韩欧美| 色婷婷综合久久久中字幕精品久久 | 91精品在线观看国产| 免费网站在线观看视频| 99在线精品免费视频九九视| 国产裸体舞一区二区三区| 蓝色福利精品导航| 中文字幕人妻熟女在线| 久久亚洲影视婷婷| 久久99久久99精品免费看小说| 亚洲久本草在线中文字幕| 日韩av片在线播放| 欧美日韩综合不卡| 午夜精品久久久久久久99热黄桃 | 成人激情视频免费在线| 亚洲视频国产精品| 欧美不卡1区2区3区| 久久国产亚洲| 国产精品裸体瑜伽视频| 日韩二区三区在线观看| 国产黄色一区二区三区| 久久久久久麻豆| 欧美色图亚洲视频| 色88888久久久久久影院按摩| 国产女人高潮时对白| 精品视频在线导航| 成人日韩欧美| 国产xxx69麻豆国语对白| 日韩精品中文字幕吗一区二区| 蜜桃免费一区二区三区| 欧美99久久| 9久久婷婷国产综合精品性色| 国产精品99久久久久久久vr| av黄色在线免费观看| 亚洲一区二区三区自拍| 中文字幕在线播出| 亚洲精品99久久久久| 黄色大片在线播放| 日本中文字幕不卡免费| www.成人网| 艳母动漫在线免费观看| 久久久777| 性色av蜜臀av浪潮av老女人| 中文字幕在线一区免费| 无码人妻精品一区二区50| 欧美www视频| 免费日本一区二区三区视频| 青草成人免费视频| 国产区精品视频在线观看豆花| 一本—道久久a久久精品蜜桃| 久久精品免费| 在线观看国产免费视频| 依依成人精品视频| 一区二区国产欧美| 在线午夜精品自拍| 中老年在线免费视频| 国产精品裸体一区二区三区| 五月开心六月丁香综合色啪| 中文字幕第36页| 久久精子c满五个校花| av黄色在线看| 亚洲成人久久久| 丁香花在线观看完整版电影| 1卡2卡3卡精品视频| 国产高清一区二区| 日韩不卡一二三| 日本一区二区三级电影在线观看| 久久国产视频精品| 亚洲免费视频网站| 在线天堂资源| 久久久影院一区二区三区| 99热在线精品观看| 你懂得在线视频| 欧美日韩国产在线看| 五月婷婷伊人网| 98精品国产自产在线观看| 欧美三级午夜理伦三级小说| 少妇无码av无码专区在线观看| 99久久伊人久久99| 欧美在线观看不卡| 亚洲欧美中文日韩在线v日本| 极品美女一区| 亚洲国产另类久久久精品极度| 日本中文在线一区| 国产探花在线视频| 欧美一区二区在线播放| 成人看片免费| 国产99视频精品免费视频36| 国产精品www994| bl动漫在线观看| 欧美日韩亚洲一区二| 黄色电影免费在线看| 国产精品久久久久久一区二区 | 日韩精品综合在线| 成人动漫在线一区| 精品免费囯产一区二区三区| 国产一区二区精品丝袜| 亚洲ww精品| 成人毛片100部免费看| 99久久精品情趣| 啪啪小视频网站| 久久九九亚洲综合| 成人18夜夜网深夜福利网| 欧美日韩一道本| 中文字幕精品综合| 99精品免费观看| 97在线视频一区| 久久大综合网| 香蕉视频在线观看黄| 偷拍日韩校园综合在线| jizzjizz在线观看| 5566av亚洲| 国产精品亚洲综合久久| 99精品中文字幕| 亚洲白拍色综合图区| 青青热久免费精品视频在线18| 永久久久久久| 成人18视频日本| 中文字幕激情视频| 久久久久久久久久婷婷| 国产欧美日韩在线观看视频| 亚洲国产欧美91| 欧美性xxxx18| 天堂av资源在线观看| 日本不卡免费新一二三区| 国产一区二区福利视频| 国产精品男女视频| 久久亚洲春色中文字幕| 同性恋视频一区| 天天操夜夜操很很操| 91福利小视频|