主頁 > 後端開發 > 第2-4-3章 規則引擎Drools基礎語法-業務規則管理系統-組件化-中臺

第2-4-3章 規則引擎Drools基礎語法-業務規則管理系統-組件化-中臺

2022-11-25 08:00:29 後端開發

目錄
  • 4. Drools基礎語法
    • 4.1 規則檔案構成
    • 4.2 規則體語法結構
    • 4.3 注釋
    • 4.4 Pattern模式匹配
    • 4.5 比較運算子
      • 4.5.1 語法
      • 4.5.2 操作步驟
    • 4.6 執行指定規則
    • 4.7 關鍵字
    • 4.8 Drools內置方法
      • 4.8.1 update方法
      • 4.8.2 insert方法
      • 4.8.3 retract方法

4. Drools基礎語法

全套代碼及資料全部完整提供,點此處下載

4.1 規則檔案構成

在使用Drools時非常重要的一個作業就是撰寫規則檔案,通常規則檔案的后綴為.drl,

drl是Drools Rule Language的縮寫,在規則檔案中撰寫具體的規則內容,

一套完整的規則檔案內容構成如下:

關鍵字 描述
package 包名,只限于邏輯上的管理,同一個包名下的查詢或者函式可以直接呼叫
import 用于匯入類或者靜態方法
global 全域變數
function 自定義函式
query 查詢
rule end 規則體

Drools支持的規則檔案,除了drl形式,還有Excel檔案型別的,

4.2 規則體語法結構

規則體是規則檔案內容中的重要組成部分,是進行業務規則判斷、處理業務結果的部分,

規則體語法結構如下:

rule "ruleName"
    attributes
    when
        LHS
    then
        RHS
end

rule:關鍵字,表示規則開始,引數為規則的唯一名稱,

attributes:規則屬性,是rule與when之間的引數,為可選項,

when:關鍵字,后面跟規則的條件部分,

LHS(Left Hand Side):是規則的條件部分的通用名稱,它由零個或多個條件元素組成,如果LHS為空,則它將被視為始終為true的條件元素,

then:關鍵字,后面跟規則的結果部分,

RHS(Right Hand Side):是規則的后果或行動部分的通用名稱,

end:關鍵字,表示一個規則結束,

4.3 注釋

在drl形式的規則檔案中使用注釋和Java類中使用注釋一致,分為單行注釋和多行注釋,

單行注釋用"//"進行標記,多行注釋以"/*"開始,以"*/"結束,如下示例:

//規則rule1的注釋,這是一個單行注釋
rule "rule1"
    when
    then
    	System.out.println("rule1觸發");
end

/*
規則rule2的注釋,
這是一個多行注釋
*/
rule "rule2"
    when
    then
    	System.out.println("rule2觸發");
end

4.4 Pattern模式匹配

前面我們已經知道了Drools中的匹配器可以將Rule Base中的所有規則與Working Memory中的Fact物件進行模式匹配,那么我們就需要在規則體的LHS部分定義規則并進行模式匹配,LHS部分由一個或者多個條件組成,條件又稱為pattern,

pattern的語法結構為:系結變數名:Object(Field約束)

其中系結變數名可以省略,通常系結變數名的命名一般建議以$開始,如果定義了系結變數名,就可以在規則體的RHS部分使用此系結變數名來操作相應的Fact物件,Field約束部分是需要回傳true或者false的0個或多個運算式,

例如我們的入門案例中:

//規則二:所購圖書總價在100到200元的優惠20元
rule "book_discount_2"
    when
    	//Order為型別約束,originalPrice為屬性約束
        $order:Order(originalPrice < 200 && originalPrice >= 100)
    then
        $order.setRealPrice($order.getOriginalPrice() - 20);
        System.out.println("成功匹配到規則二:所購圖書總價在100到200元的優惠20元");
end

通過上面的例子我們可以知道,匹配的條件為:

1、作業記憶體中必須存在Order這種型別的Fact物件-----型別約束

2、Fact物件的originalPrice屬性值必須小于200------屬性約束

3、Fact物件的originalPrice屬性值必須大于等于100------屬性約束

以上條件必須同時滿足當前規則才有可能被激活,

系結變數既可以用在物件上,也可以用在物件的屬性上,例如上面的例子可以改為:

//規則二:所購圖書總價在100到200元的優惠20元
rule "book_discount_2"
    when
        $order:Order($op:originalPrice < 200 && originalPrice >= 100)
    then
        System.out.println("$op=" + $op);
        $order.setRealPrice($order.getOriginalPrice() - 20);
        System.out.println("成功匹配到規則二:所購圖書總價在100到200元的優惠20元");
end

LHS部分還可以定義多個pattern,多個pattern之間可以使用and或者or進行連接,也可以不寫,默認連接為and,

//規則二:所購圖書總價在100到200元的優惠20元
rule "book_discount_2"
    when
        $order:Order($op:originalPrice < 200 && originalPrice >= 100) and
        $customer:Customer(age > 20 && gender=='male')
    then
        System.out.println("$op=" + $op);
        $order.setRealPrice($order.getOriginalPrice() - 20);
        System.out.println("成功匹配到規則二:所購圖書總價在100到200元的優惠20元");
end

4.5 比較運算子

Drools提供的比較運算子,如下表:

符號 說明
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于
!= 不等于
contains 檢查一個Fact物件的某個屬性值是否包含一個指定的物件值
not contains 檢查一個Fact物件的某個屬性值是否不包含一個指定的物件值
memberOf 判斷一個Fact物件的某個屬性是否在一個或多個集合中
not memberOf 判斷一個Fact物件的某個屬性是否不在一個或多個集合中
matches 判斷一個Fact物件的屬性是否與提供的標準的Java正則運算式進行匹配
not matches 判斷一個Fact物件的屬性是否不與提供的標準的Java正則運算式進行匹配

前6個比較運算子和Java中的完全相同,下面我們重點學習后6個比較運算子,

4.5.1 語法

  • contains | not contains語法結構

    Object(Field[Collection/Array] contains value)

    Object(Field[Collection/Array] not contains value)

  • memberOf | not memberOf語法結構

    Object(field memberOf value[Collection/Array])

    Object(field not memberOf value[Collection/Array])

  • matches | not matches語法結構

    Object(field matches "正則運算式")

    Object(field not matches "正則運算式")

4.5.2 操作步驟

第一步:創建物體類,用于測驗比較運算子

package com.itheima.drools.entity;
import java.util.List;

/**
 * 物體類
 * 用于測驗比較運算子
 */
public class ComparisonOperatorEntity {
    private String names;
    private List<String> list;

    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}

第二步:在/resources/rules下創建規則檔案comparisonOperator.drl

package comparisonOperator
import com.itheima.drools.entity.ComparisonOperatorEntity
/*
 當前規則檔案用于測驗Drools提供的比較運算子
*/

//測驗比較運算子contains
rule "rule_comparison_contains"
    when
        ComparisonOperatorEntity(names contains "張三")
        ComparisonOperatorEntity(list contains names)
    then
        System.out.println("規則rule_comparison_contains觸發");
end

//測驗比較運算子not contains
rule "rule_comparison_notContains"
    when
        ComparisonOperatorEntity(names not contains "張三")
        ComparisonOperatorEntity(list not contains names)
    then
        System.out.println("規則rule_comparison_notContains觸發");
end

//測驗比較運算子memberOf
rule "rule_comparison_memberOf"
    when
        ComparisonOperatorEntity(names memberOf list)
    then
        System.out.println("規則rule_comparison_memberOf觸發");
end

//測驗比較運算子not memberOf
rule "rule_comparison_notMemberOf"
    when
        ComparisonOperatorEntity(names not memberOf list)
    then
        System.out.println("規則rule_comparison_notMemberOf觸發");
end

//測驗比較運算子matches
rule "rule_comparison_matches"
    when
        ComparisonOperatorEntity(names matches "張.*")
    then
        System.out.println("規則rule_comparison_matches觸發");
end

//測驗比較運算子not matches
rule "rule_comparison_notMatches"
    when
        ComparisonOperatorEntity(names not matches "張.*")
    then
        System.out.println("規則rule_comparison_notMatches觸發");
end

第三步:撰寫單元測驗

//測驗比較運算子
@Test
public void test2(){
    KieServices kieServices = KieServices.Factory.get();
    KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
    KieSession kieSession = kieClasspathContainer.newKieSession();

    ComparisonOperatorEntity comparisonOperatorEntity = new ComparisonOperatorEntity();
    comparisonOperatorEntity.setNames("張三");
    List<String> list = new ArrayList<String>();
    list.add("張三");
    list.add("李四");
    comparisonOperatorEntity.setList(list);

    //將資料提供給規則引擎,規則引擎會根據提供的資料進行規則匹配,如果規則匹配成功則執行規則
    kieSession.insert(comparisonOperatorEntity);

    kieSession.fireAllRules();
    kieSession.dispose();
}

4.6 執行指定規則

通過前面的案例可以看到,我們在呼叫規則代碼時,滿足條件的規則都會被執行,那么如果我們只想執行其中的某個規則如何實作呢?

Drools給我們提供的方式是通過規則過濾器來實作執行指定規則,對于規則檔案不用做任何修改,只需要修改Java代碼即可,如下:

//測驗執行指定規則
    @Test
    public void test3(){
        KieServices kieServices = KieServices.Factory.get();
        //獲得Kie容器物件
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        //從Kie容器物件中獲取會話物件
        KieSession session = kieContainer.newKieSession();

        //Fact物件,事實物件
        ComparisonOperatorEntity fact = new ComparisonOperatorEntity();
        fact.setNames("李四");

        List<String> list = new ArrayList<String>();
        list.add("張三2");
        //list.add("李四");

        fact.setList(list);

        session.insert(fact);

        //激活規則,由Drools框架自動進行規則匹配,如果規則匹配成功,則執行當前規則
        //使用框架提供的規則過濾器執行指定規則
        session.fireAllRules(new RuleNameEqualsAgendaFilter("rule_comparison_notcontains"));
        //session.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_"));
        //關倍訓話
        session.dispose();
    }

4.7 關鍵字

Drools的關鍵字分為:硬關鍵字(Hard keywords)和軟關鍵字(Soft keywords),

硬關鍵字是我們在規則檔案中定義包名或者規則名時明確不能使用的,否則程式會報錯,軟關鍵字雖然可以使用,但是不建議使用,

硬關鍵字包括:true false null

軟關鍵字包括:lock-on-active date-effective date-expires no-loop auto-focus activation-group agenda-group ruleflow-group entry-point duration package import dialect salience enabled attributes rule extend when then template query declare function global eval not in or and exists forall accumulate collect from action reverse result end over init

4.8 Drools內置方法

規則檔案的RHS部分的主要作用是通過插入,洗掉或修改作業記憶體中的Fact資料,來達到控制規則引擎執行的目的,Drools提供了一些方法可以用來操作作業記憶體中的資料,操作完成后規則引擎會重新進行相關規則的匹配,原來沒有匹配成功的規則在我們修改資料完成后有可能就會匹配成功了,

創建如下物體類:

package com.itheima.drools.entity;

import java.util.List;

/**
 * 學生
 */
public class Student {
    private int id;
    private String name;
    private int age;
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

4.8.1 update方法

update方法的作用是更新作業記憶體中的資料,并讓相關的規則重新匹配,

第一步:撰寫規則檔案/resources/rules/student.drl,檔案內容如下

package student
import com.itheima.drools.entity.Student

/*
 當前規則檔案用于測驗Drools提供的內置方法
*/

rule "rule_student_age小于10歲"
    when
        $s:Student(age < 10)
    then
        $s.setAge(15);
        update($s);//更新資料,導致相關的規則會重新匹配
        System.out.println("規則rule_student_age小于10歲觸發");
end

rule "rule_student_age小于20歲同時大于10歲"
    when
        $s:Student(age < 20 && age > 10)
    then
        $s.setAge(25);
        update($s);//更新資料,導致相關的規則會重新匹配
        System.out.println("規則rule_student_age小于20歲同時大于10歲觸發");
end

rule "rule_student_age大于20歲"
    when
        $s:Student(age > 20)
    then
        System.out.println("規則rule_student_age大于20歲觸發");
end

第二步:撰寫單元測驗

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();

Student student = new Student();
student.setAge(5);

//將資料提供給規則引擎,規則引擎會根據提供的資料進行規則匹配,如果規則匹配成功則執行規則
kieSession.insert(student);

kieSession.fireAllRules();
kieSession.dispose();

通過控制臺的輸出可以看到規則檔案中定義的三個規則都觸發了,

在更新資料時需要注意防止發生死回圈,

4.8.2 insert方法

insert方法的作用是向作業記憶體中插入資料,并讓相關的規則重新匹配,

第一步:修改student.drl檔案內容如下

package student
import com.itheima.drools.entity.Student

/*
 當前規則檔案用于測驗Drools提供的內置方法
*/

rule "rule_student_age等于10歲"
    when
        $s:Student(age == 10)
    then
        Student student = new Student();
        student.setAge(5);
        insert(student);//插入資料,導致相關的規則會重新匹配
        System.out.println("規則rule_student_age等于10歲觸發");
end

rule "rule_student_age小于10歲"
    when
        $s:Student(age < 10)
    then
        $s.setAge(15);
        update($s);
        System.out.println("規則rule_student_age小于10歲觸發");
end

rule "rule_student_age小于20歲同時大于10歲"
    when
        $s:Student(age < 20 && age > 10)
    then
        $s.setAge(25);
        update($s);
        System.out.println("規則rule_student_age小于20歲同時大于10歲觸發");
end

rule "rule_student_age大于20歲"
    when
        $s:Student(age > 20)
    then
        System.out.println("規則rule_student_age大于20歲觸發");
end

第二步:撰寫單元測驗

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();

Student student = new Student();
student.setAge(10);

//將資料提供給規則引擎,規則引擎會根據提供的資料進行規則匹配,如果規則匹配成功則執行規則
kieSession.insert(student);

kieSession.fireAllRules();
kieSession.dispose();

通過控制臺輸出可以發現,四個規則都觸發了,這是因為首先進行規則匹配時只有第一個規則可以匹配成功,但是在第一個規則中向作業記憶體中插入了一個資料導致重新進行規則匹配,此時第二個規則可以匹配成功,在第二個規則中進行了資料修改導致第三個規則也可以匹配成功,以此類推最終四個規則都匹配成功并執行了,

4.8.3 retract方法

retract方法的作用是洗掉作業記憶體中的資料,并讓相關的規則重新匹配,

第一步:修改student.drl檔案內容如下

package student
import com.itheima.drools.entity.Student

/*
 當前規則檔案用于測驗Drools提供的內置方法
*/

rule "rule_student_age等于10歲時洗掉資料"
    /*
    salience:設定當前規則的執行優先級,數值越大越優先執行,默認值為0.
    因為當前規則的匹配條件和下面規則的匹配條件相同,為了保證先執行當前規則,需要設定優先級
    */
    salience 100 
    when
        $s:Student(age == 10)
    then
        retract($s);//retract方法的作用是洗掉作業記憶體中的資料,并讓相關的規則重新匹配,
        System.out.println("規則rule_student_age等于10歲時洗掉資料觸發");
end

rule "rule_student_age等于10歲"
    when
        $s:Student(age == 10)
    then
        Student student = new Student();
        student.setAge(5);
        insert(student);
        System.out.println("規則rule_student_age等于10歲觸發");
end

rule "rule_student_age小于10歲"
    when
        $s:Student(age < 10)
    then
        $s.setAge(15);
        update($s);
        System.out.println("規則rule_student_age小于10歲觸發");
end

rule "rule_student_age小于20歲同時大于10歲"
    when
        $s:Student(age < 20 && age > 10)
    then
        $s.setAge(25);
        update($s);
        System.out.println("規則rule_student_age小于20歲同時大于10歲觸發");
end

rule "rule_student_age大于20歲"
    when
        $s:Student(age > 20)
    then
        System.out.println("規則rule_student_age大于20歲觸發");
end

第二步:撰寫單元測驗

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();

Student student = new Student();
student.setAge(10);

//將資料提供給規則引擎,規則引擎會根據提供的資料進行規則匹配,如果規則匹配成功則執行規則
kieSession.insert(student);

kieSession.fireAllRules();
kieSession.dispose();

通過控制臺輸出可以發現,只有第一個規則觸發了,因為在第一個規則中將作業記憶體中的資料洗掉了導致第二個規則并沒有匹配成功,

全套代碼及資料全部完整提供,點此處下載

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

標籤:Java

上一篇:Spring Security(4)

下一篇: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