主頁 > 後端開發 > URule規則引擎

URule規則引擎

2023-03-15 07:19:51 後端開發

沒有規則,不成方圓;

一、背景

前段時間,在做專案重構的時候,遇到很多地方需要做很多的條件判斷,當然可以用很多的if-else判斷去解決,但是當時也不清楚怎么回事,就想玩點別的,于是乎,就去調研了規則引擎,

當然,市面上有很多成熟的規則引擎,功能很多,性能很好,但是,就是想玩點不一樣的(大家做技術選型別這樣,這個是反面教材),最終一款URule的規則引擎吸引了我,主要還是采用瀏覽器可直接配置,不需要過多安裝,可視化規則也做的不錯,經過一系列調研,后面就把它接入了專案中,順便記錄下調研的結果,

二、介紹

規則引擎其實是一種組件,它可以嵌入到程式當中,將程式復雜的判斷規則從業務代碼中剝離出來,使得程式只需要關心自己的業務,而不需要去進行復雜的邏輯判斷;簡單的理解是規則接受一組輸入的資料,通過預定好的規則配置,再輸出一組結果,

當然,市面上有很多成熟的規則引擎,如:Drools、Aviator、EasyRules等等,但是URule,它可以運行在Windows、Linux、Unix等各種型別的作業系統之上,采用純瀏覽器的編輯模式,不需要安裝工具,直接在瀏覽器上編輯規則和測驗規則,

當然這款規則引擎有開源和pro版本的區別,至于pro版是啥,懂的都懂,下面放個表格,了解下具體的區別

特性 PRO版 開源版
向導式決策集
腳本式決策集
決策樹
決策流
決策表
交叉決策表
復雜評分卡
檔案名、專案名重構
引數名、變數常量名重構
Excel決策表匯入
規則集模版保存與加載
中文專案名和檔案名支持
服務器推送知識包到客戶端功能的支持
知識包優化與壓縮的支持
客戶端服務器模式下大知識包的推拉支持
規則集中執行組的支持
規則流中所有節點向導式條件與動作配置的支持
回圈規則多回圈單元支持
回圈規則中無條件執行的支持
匯入專案自動重命名功能
規則樹構建優化
物件查找索引支持
規則樹中短路計算的支持
規則條件冗余計算快取支持
基于方案的批量場景測驗功能
知識包呼叫監控
更為完善的檔案讀寫權限控制
知識包版本控制
SpringBean及Java類的熱部署
技術支持

三、安裝使用

實際使用時,有四種使用URule Pro的方式,分別是嵌入式模式、本地模式、分布式計算模式以及獨立服務模式,

但是我們這里不考慮URule Pro,咱自己整個開源版,在開源版集成springboot的基礎上做一個二次開發,搜了一圈,其實就有解決方案,大致的專案模塊如下:

自己創建個空資料庫,只需要在edas-rule-server服務中修改下資料庫的配置,然后啟動服務即可,第一次啟動完成,資料庫中會創建表,

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/urule-data?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=mysql

上面說過,它是純用瀏覽器進行編輯,配置規則的,只需要打開瀏覽器,輸入地址:http://localhost:8090/urule/frame,看到這個界面,就說明啟動成功了,

四、基礎概念

3.1整體介紹

先說下URule它的構成部分,主要是兩部分:1、設計器部分 2、規則執行引擎,設計器部分主要是庫檔案和規則檔案構成,下面看下整體的結構圖

3.2庫檔案

如上圖介紹的,庫檔案有4種,包括變數庫,引數庫,常量庫和動作庫,其實類似于Java開發的系統中的物體物件,列舉,常量以及方法,

上面說過,規則都是可視化配置的,在配置規則的程序中,就需要引入各種已經定義好的庫檔案,再結合業務需求,從而配置出符合業務場景的業務規則,所以哪里都有庫檔案的身影,

3.2.1變數庫檔案

在業務開發中,我們會創建很多Getter和Setter的Java類,比如PO、VO、BO、DTO、POJO等等,其實這些類new物件后主要起到的作用就是資料的載體,用來傳輸資料,

在URule中,變數庫就是用來映射這些物件,然后可以在規則中使用,最終完成業務和規則的互動,最后上一張圖,用來創建變數庫

對了,上面廢話了這么多可視化配置,這才是第一次展示配置界面,慚愧慚愧,

上圖一目了然,在“庫”這個選單底下右鍵,然后點擊添加變數庫即可,最后定義自己喜歡的變數庫名,當然名字只支持中文或者英文,其他字符不可用,

創建完變數庫后,就可以對變數庫進行編輯,可以認為就是給POJO添加屬性

也不彎彎繞繞講什么術語,就個人理解,圖左邊是創建類,其中名稱是它的別名,配置規則用它代替這個類,圖右邊是類的屬性,我這里隨便寫了幾個,估計看了懂得都懂,

最后在業務系統中創建對應的類,注意全限定名和配置變數庫的類路徑一致,

package com.cicada;

import com.bstek.urule.model.Label;
import lombok.Data;

/**
 * @author 往事如風
 * @version 1.0
 * @date 2023/3/3 15:38
 * @description
 */
@Data
public class Stu {

    @Label("姓名")
    private String name;

    @Label("年齡")
    private int age;

    @Label("班級")
    private String classes;
}

最后說下這個@Label注解,這個是由URule提供的注解,主要是描述欄位的屬性,跟變數庫的標題一欄一致就行,聽官方介紹可以通過這個注解,實作POJO屬性和變數庫屬性映射,就是POJO寫好,然后對應規則的變數庫就不需要重新寫,可以直接生成,反正就有這個功能,這里就直接一筆帶過了,

3.2.2常量庫檔案

說到常量庫,這個就可以認為是我們Java系統中的常量,列舉,比如性別,要定義列舉吧;比如對接的機構,也可以定義一個列舉吧,

當然,類似于變數庫,常量庫也可以實作和系統中的列舉相互映射,這樣做的好處可以避免我們手動輸入,防止輸入錯誤,創建常量庫也比較簡單,直接在“庫”這個選單下右鍵,“添加常量庫”,

創建好常量庫檔案后,也會出現如下頁面:

3.2.3引數庫檔案

引數庫,就是URule規則中的臨時變數,變數的型別和數量不固定,可以認為類似于Map,實際上存盤引數庫的也就是個Map,

同樣的套路,直接在“庫”這個選單下右鍵,“添加引數庫”,

可以看到,引數庫已經少了左邊分類這一項,直接添加引數,選擇型別就是干,相對簡單了很多,“名稱”這列我這里用了英文,就是Map中的key,而“標題”這列就是在配置規則時候顯示用的,中文看著比較直觀,

當然還需要注意的點是,定義的名稱要保證唯一,因為Map中的key是唯一的,不然就會存在覆寫的情況,

3.2.4動作庫檔案

動作庫可以對配置在spring中的bean方法進行映射,然后可以在規則中直接呼叫這批方法,
慣用套路,還是在“庫”選單下右鍵,點擊“添加動作庫”,

然后我在系統中添加了一個類Action,然后在類上標記@Component注解,將該類交給spring的bean容器管理,該類中添加一些方法,在方法上標記@ExposeAction注解,該注解是URule定義的,說明被標記的方法都會被動作庫讀取到,

package com.bstek.urule.cicada;

import com.bstek.urule.action.ActionId;
import com.bstek.urule.model.ExposeAction;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author 往事如風
 * @version 1.0
 * @date 2023/3/10 13:59
 * @description
 */
@Component("action")
public class Action {

    @ActionId("Hello")
    public String hello(){
        return "hello";
    }

    @ExposeAction(value="https://www.cnblogs.com/cicada-smile/p/方法1")
    public boolean evalTest(String username){
        if(username==null){
            return false;
        }else if(username.equals("張三")){
            return true;
        }
        return false;
    }

    @ExposeAction(value="https://www.cnblogs.com/cicada-smile/p/測驗Int")
    public int testInt(int a,int b){
        return a+b;
    }

    @ExposeAction(value="https://www.cnblogs.com/cicada-smile/p/列印內容")
    public void printContent(String username, Date birthday){
        SimpleDateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(birthday!=null){
            System.out.println(username+"今年已經"+sd.format(birthday)+"歲了!");
        }else{
            System.out.println("Hello "+username+"");
        }
    }
    
    @ExposeAction(value="https://www.cnblogs.com/cicada-smile/p/列印Stu")
    public void printUser(Stu m){
        System.out.println("Hello "+m.getName()+", is age:"+m.getAge());
    }
}

最后在動作庫頁面上添加bean,“Bean Id”一列輸入對應的spring bean的名稱,這里輸入action,然后點擊操作列中的小手按鈕,就會彈出剛在Action類中標記了ExposeAction注解的方法,選擇一個指定的方法添加進來,最后看到方法對應的引數也會被自動加載進去,

最后,變數庫、引數庫、動作庫、常量庫這些庫檔案定義好后,各種規則檔案配置的時候就可以匯入他們,但是一旦這些庫檔案被某個規則檔案使用,就不要隨意修改庫檔案了,

3.3規則集

說到規則集,顧名思義,就是配置規則了,前面定義的庫檔案就需要匯入到規則集中去配置使用,它是使用頻率最高的一個業務規則實作方式,

規則集說的是規則的集合,由三個部分規則組成:如果、那么、否則,

在規則集的定義的方式上,URule由向導式和腳本式兩種;

  • 向導式規則集:就是在頁面上通過滑鼠點點點,高度的可視化配置,不是開發都能懂,這也是這個規則引擎的亮點所在,
  • 腳本式規則集:聽名字就知道了,這玩意要寫腳本的,拉高配置門檻,需要懂點編碼的人來撰寫,

3.3.1向導式規則集

還是一樣,首先新建,這次是在“決策集”選單上右鍵,點擊“添加向導式決策集”,這樣就創建好一個規則集了,

在配置規則前,可以先匯入前面定義好的庫檔案,我這里匯入變數庫檔案,頁面上點擊“變數庫”,然后選擇指定的變數庫檔案即可,如圖所示;

最后,可以愉快的配置規則了,向導式沒什么好講的,都是可視化界面,點點點即可,下面是我配置的一個簡單的規則集;

可以看到由三部分組成:如果、那么、否則;

  1. 如果:配置規則的條件;
  2. 那么:配置滿足條件后執行的動作,一般配置變數賦值比較多
  3. 否則:配置不滿足條件執行的動作

最后,附上添加完規則后,通過代碼去執行規則;

package com.cicada;

import cn.hutool.core.bean.BeanUtil;
import com.Result;
import com.bstek.urule.Utils;
import com.bstek.urule.runtime.KnowledgePackage;
import com.bstek.urule.runtime.KnowledgeSession;
import com.bstek.urule.runtime.KnowledgeSessionFactory;
import com.bstek.urule.runtime.service.KnowledgeService;
import com.cicada.req.StuReq;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @author 往事如風
 * @version 1.0
 * @date 2023/3/10 16:47
 * @description
 */
@RestController
@RequestMapping("/rule")
public class RuleDataController {

    @PostMapping("/stu")
    public Result rule(@RequestBody StuReq stuReq) throws IOException {
        KnowledgeService knowledgeService = (KnowledgeService) Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
        KnowledgePackage knowledgePackage = knowledgeService.getKnowledge("xxx/xxx");
        KnowledgeSession knowledgeSession = KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);
        Stu stu = BeanUtil.copyProperties(stuReq, Stu.class);
        knowledgeSession.insert(stu);
        knowledgeSession.fireRules();
        return Result.success(stu.getTeacher());
    }
}

請求介面,最終引數符合配置的條件,回傳“那么”中配置的輸出結果,

3.3.2腳本式規則集

腳本式的規則集,各種原理都是和向導式一模一樣,無非就是拉高門檻,用寫腳本的方式去實作配置的規則,這里不做過多的介紹了,

3.4決策表

再聊下決策表,其實它就是規則集的另一種展示形式,比較相對規則集,我更喜歡用決策表去配置規則,應為它呈現的更加直觀,更便于理解,但是本質和規則集沒啥區別,

也不展開過多的贅述,這里我就放一張配置過的決策表;

3.5其他

當然,還有其他的概念和功能,這里也不一一介紹了,因為上面說的已經是最常用的了,想了解的可以自行去了解,其他功能包括:交叉決策表、評分卡、復雜評分卡、決策樹、規則流;當然,其中有些是Pro版的功能,

四、運用場景

最近在開發一期大版本的需求,其中就有個場景,具體如下;
參與購買訂單的用戶都會有自己的一個職級,也可以說是角色,每個用戶都會有三個職位:普通用戶、會員、精英會員,

然后,每個月初都會對用戶進行一次晉升處理,普通用戶達到要求,就會晉升為會員,會員達到要求就會晉升為精英會員,

當然,普通用戶晉升會員,會員晉升精英會員,都會有不同的規則;

  1. 普通用戶->會員:3個月內幫注冊人數達到3人;3個月內自己和底下團隊的人,下單金額超過1萬;個人的訂單繼續率超過80%,
  2. 會員->精英會員:3個月內幫注冊人數達到6人;3個月內自己和底下團隊的人,下單金額超過5萬;個人的訂單繼續率超過90%,
  3. 不能跨級晉升,普通用戶最多只能到會員,達到會員了才能晉升到精英會員,

當然,這只是做過簡化的一部分需求,我做過稍許的改動,真實的需求場景并沒有這么簡單,

下面,我對這個需求做一個規則的配置,這里用一個決策表進行配置;在配置規則前,我添加一個變數庫檔案和常量庫;

最后,添加一個決策表,并進行規則配置;

可以看到,表格一共五列,其中前四列是規則,最后一列是滿足規則后輸出的資訊,這樣看著就很清晰,即使并不是技術人員,也可以輕松看懂其中的規則,

五、總結

規則引擎對于我們的系統而言可用可不用,它可以錦上添花,幫助我們剝離出業務中需要進行大量判斷的場景,但是,這種規則的剝離,需要我們開發人員對需求進行理解,在理解的基礎上進行抽象概念的具化,這,也是整個編程的必經之路

六、參考原始碼

編程檔案:
https://gitee.com/cicadasmile/butte-java-note

應用倉庫:
https://gitee.com/cicadasmile/butte-flyer-parent
Gitee主頁: https://gitee.com/cicadasmile/butte-java-note

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546777.html

標籤:Java

上一篇:面試官:怎么洗掉 HashMap 中的重復元素?第 3 種實作思路,99% 的人不會!

下一篇:劍指 Offer 68 - II. 二叉樹的最近公共祖先(java解題)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more