Typescript入門-interface講解

  • 對象成員語法形式
    • 1)對象屬性
    • 2)對象的屬性索引
    • 3)對象的方法
    • 4)函數
    • 5)構造函數
  • interface 的繼承
    • interface 繼承 interface
    • interface 繼承 type
    • interface 繼承 class
  • 接口合并
  • interface 與 type 的異同

interface 是對象的模板,可以看作是一種類型約定,中文譯為“接口”。使用了某個模板的對象,就擁有了指定的類型結構。

interface Person {firstName: string;lastName: string;age: number;
}

上面示例中,定義了一個接口Person,它指定一個對象模板,擁有三個屬性firstName、lastName和age。任何實現這個接口的對象,都必須部署這三個屬性,并且必須符合規定的類型。

實現該接口很簡單,只要指定它作為對象的類型即可。

const p: Person = {firstName: "John",lastName: "Smith",age: 25,
};

上面示例中,變量p的類型就是接口Person,所以必須符合Person指定的結構。

方括號運算符可以取出 interface 某個屬性的類型。

interface Foo {a: string;
}type A = Foo["a"]; // string

上面示例中,Foo[‘a’] 返回屬性a的類型,所以類型A就是string。

對象成員語法形式

interface 可以表示對象的各種語法,它的成員有 5 種形式。

  • 對象屬性
  • 對象的屬性索引
  • 對象方法
  • 函數
  • 構造函數

1)對象屬性

interface Point {x: number;y: number;
}

上面示例中,x和y都是對象的屬性,分別使用冒號指定每個屬性的類型。

屬性之間使用分號或逗號分隔,最后一個屬性結尾的分號或逗號可以省略。

如果屬性是可選的,就在屬性名后面加一個問號。

interface Foo {x?: string;
}

如果屬性是只讀的,需要加上 readonly 修飾符。

interface A {readonly a: string;
}

2)對象的屬性索引

interface A {[prop: string]: number;
}

上面示例中,[prop: string] 就是屬性的字符串索引,表示屬性名只要是字符串,都符合類型要求。

屬性索引共有stringnumbersymbol三種類型。

一個接口中,最多只能定義一個字符串索引。字符串索引會約束該類型中所有名字為字符串的屬性。

interface MyObj {[prop: string]: number;a: boolean; // 編譯錯誤
}

上面示例中,屬性索引指定所有名稱為字符串的屬性,它們的屬性值必須是數值(number)。屬性a的值為布爾值就報錯了。

屬性的數值索引,其實是指定數組的類型。

interface A {[prop: number]: string;
}const obj: A = ["a", "b", "c"];

上面示例中,[prop: number] 表示屬性名的類型是數值,所以可以用數組對變量obj賦值。

同樣的,一個接口中最多只能定義一個數值索引。數值索引會約束所有名稱為數值的屬性。

如果一個 interface 同時定義了字符串索引和數值索引,那么數值索性必須服從于字符串索引。因為在 JavaScript 中,數值屬性名最終是自動轉換成字符串屬性名。

interface A {[prop: string]: number;[prop: number]: string; // 報錯
}interface B {[prop: string]: number;[prop: number]: number; // 正確
}

上面示例中,數值索引的屬性值類型與字符串索引不一致,就會報錯。數值索引必須兼容字符串索引的類型聲明。

3)對象的方法

對象的方法共有三種寫法。

// 寫法一
interface A {f(x: boolean): string;
}// 寫法二
interface B {f: (x: boolean) => string;
}// 寫法三
interface C {f: { (x: boolean): string };
}

屬性名可以采用表達式,所以下面的寫法也是可以的。

const f = "f";interface A {[f](x: boolean): string;
}

重載(Overloading)是指在同一個作用域中,允許多個同名的方法或函數根據參數的數量或類型不同而有不同的實現。在 TypeScript 的接口(interface)中,方法可以聲明多種參數和返回值類型的組合,這就是方法重載。例如:

interface A {f(): number;f(x: boolean): boolean;f(x: string, y: string): string;
}

上面例子中,接口 A 的方法 f 有三種不同的參數簽名,這就是方法的重載。實現時,可以根據傳入參數的不同,執行不同的邏輯。

interface 里面的函數重載,不需要給出實現。但是,由于對象內部定義方法時,無法使用函數重載的語法,所以需要額外在對象外部給出函數方法的實現。

interface A {f(): number;f(x: boolean): boolean;f(x: string, y: string): string;
}function MyFunc(): number;
function MyFunc(x: boolean): boolean;
function MyFunc(x: string, y: string): string;
function MyFunc(x?: boolean | string, y?: string): number | boolean | string {if (x === undefined && y === undefined) return 1;if (typeof x === "boolean" && y === undefined) return true;if (typeof x === "string" && typeof y === "string") return "hello";throw new Error("wrong parameters");
}const a: A = {f: MyFunc,
};

上面示例中,接口A的方法f()有函數重載,需要額外定義一個函數MyFunc()實現這個重載,然后部署接口A的對象a的屬性f等于函數MyFunc()就可以了。

4)函數

interface 也可以用來聲明獨立的函數。

interface Add {(x: number, y: number): number;
}const myAdd: Add = (x, y) => x + y;

上面示例中,接口Add聲明了一個函數類型。

5)構造函數

interface 內部可以使用 new 關鍵字,表示構造函數。

interface ErrorConstructor {new (message?: string): Error;
}

上面示例中,接口 ErrorConstructor 內部有 new 命令,表示它是一個構造函數。TypeScript 里面,構造函數特指具有 constructor 屬性的類。

interface 的繼承

interface 可以繼承其他類型,主要有下面幾種情況。

interface 繼承 interface

interface 可以使用 extends 關鍵字,繼承其他 interface

interface Shape {name: string;
}interface Circle extends Shape {radius: number;
}

上面示例中,Circle 繼承了 Shape,所以Circle其實有兩個屬性name和radius。這時,Circle是子接口,Shape是父接口。

extends 關鍵字會從繼承的接口里面拷貝屬性類型,這樣就不必書寫重復的屬性。

interface 允許多重繼承。

interface Style {color: string;
}interface Shape {name: string;
}interface Circle extends Style, Shape {radius: number;
}

上面示例中,Circle 同時繼承了 Style 和 Shape,所以擁有三個屬性color、name和radius。

多重接口繼承,實際上相當于多個父接口的合并。

如果子接口與父接口存在同名屬性,那么子接口的屬性會覆蓋父接口的屬性。注意,子接口與父接口的同名屬性必須是類型兼容的,不能有沖突,否則會報錯。

interface Foo {id: string;
}interface Bar extends Foo {id: number; // 報錯
}

上面示例中,Bar繼承了Foo,但是兩者的同名屬性id的類型不兼容,導致報錯。

多重繼承時,如果多個父接口存在同名屬性,那么這些同名屬性不能有類型沖突,否則會報錯。

interface Foo {id: string;
}interface Bar {id: number;
}// 報錯
interface Baz extends Foo, Bar {type: string;
}

上面示例中,Baz同時繼承了Foo和Bar,但是后兩者的同名屬性id有類型沖突,導致報錯。

interface 繼承 type

interface 可以繼承 type 命令定義的對象類型。

type Country = {name: string;capital: string;
};interface CountryWithPop extends Country {population: number;
}

上面示例中,CountryWithPop 繼承了 type 命令定義的 Country 對象,并且新增了一個population 屬性。

注意,如果 type 命令定義的類型不是對象,interface 就無法繼承。

interface 繼承 class

interface 還可以繼承 class,即繼承該類的所有成員。

class A {x: string = "";y(): boolean {return true;}
}interface B extends A {z: number;
}

上面示例中,B 繼承了 A,因此 B 就具有屬性x、y()和z。

實現B接口的對象就需要實現這些屬性。

const b: B = {x: "",y: function () {return true;},z: 123,
};

上面示例中,對象 b 就實現了接口 B,而接口 B 又繼承了類 A。

某些類擁有私有成員和保護成員,interface 可以繼承這樣的類,但是意義不大。

class A {private x: string = "";protected y: string = "";
}interface B extends A {z: number;
}// 報錯
const b: B = {/* ... */
};// 報錯
class C implements B {// ...
}

上面示例中,A 有私有成員和保護成員,B 繼承了 A,但無法用于對象,因為對象不能實現這些成員。這導致 B 只能用于其他 class,而這時其他 class 與 A 之間不構成父類和子類的關系,使得 x 與 y 無法部署。

接口合并

多個同名接口會合并成一個接口。

interface Box {height: number;width: number;
}interface Box {length: number;
}

上面示例中,兩個Box接口會合并成一個接口,同時有height、width和length三個屬性。

這樣的設計主要是為了兼容 JavaScript 的行為。JavaScript 開發者常常對全局對象或者外部庫,添加自己的屬性和方法。那么,只要使用 interface 給出這些自定義屬性和方法的類型,就能自動跟原始的 interface 合并,使得擴展外部類型非常方便。

舉例來說,Web 網頁開發經常會對 windows 對象和 document 對象添加自定義屬性,但是 TypeScript 會報錯,因為原始定義沒有這些屬性。解決方法就是把自定義屬性寫成 interface,合并進原始定義。

interface Document {foo: string;
}document.foo = "hello";

上面示例中,接口 Document 增加了一個自定義屬性 foo,從而就可以在 document 對象上使用自定義屬性。

同名接口合并時,同一個屬性如果有多個類型聲明,彼此不能有類型沖突。

interface A {a: number;
}interface A {a: string; // 報錯
}

上面示例中,接口 A 的屬性 a 有兩個類型聲明,彼此是沖突的,導致報錯。

同名接口合并時,如果同名方法有不同的類型聲明,那么會發生函數重載。而且,后面的定義比前面的定義具有更高的優先級。

interface Cloner {clone(animal: Animal): Animal;
}interface Cloner {clone(animal: Sheep): Sheep;
}interface Cloner {clone(animal: Dog): Dog;clone(animal: Cat): Cat;
}// 等同于
interface Cloner {clone(animal: Dog): Dog;clone(animal: Cat): Cat;clone(animal: Sheep): Sheep;clone(animal: Animal): Animal;
}

上面示例中,clone()方法有不同的類型聲明,會發生函數重載。這時,越靠后的定義,優先級越高,排在函數重載的越前面。比如,clone(animal: Animal)是最先出現的類型聲明,就排在函數重載的最后,屬于clone()函數最后匹配的類型。

這個規則有一個例外。同名方法之中,如果有一個參數是字面量類型字面量類型有更高的優先級

interface A {f(x: "foo"): boolean;
}interface A {f(x: any): void;
}// 等同于
interface A {f(x: "foo"): boolean;f(x: any): void;
}

上面示例中,f()方法有一個類型聲明參數x是字面量類型,這個類型聲明的優先級最高,會排在函數重載的最前面。

一個實際的例子是 Document 對象的createElement()方法,它會根據參數的不同,而生成不同的 HTML 節點對象。

interface Document {createElement(tagName: any): Element;
}
interface Document {createElement(tagName: "div"): HTMLDivElement;createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {createElement(tagName: string): HTMLElement;createElement(tagName: "canvas"): HTMLCanvasElement;
}// 等同于
interface Document {createElement(tagName: "canvas"): HTMLCanvasElement;createElement(tagName: "div"): HTMLDivElement;createElement(tagName: "span"): HTMLSpanElement;createElement(tagName: string): HTMLElement;createElement(tagName: any): Element;
}

上面示例中,createElement()方法的函數重載,參數為字面量的類型聲明會排到最前面,返回具體的 HTML 節點對象。類型越不具體的參數,排在越后面,返回通用的 HTML 節點對象。

如果兩個 interface 組成的聯合類型存在同名屬性,那么該屬性的類型也是聯合類型。

interface Circle {area: bigint;
}interface Rectangle {area: number;
}declare const s: Circle | Rectangle;s.area; // bigint | number

上面示例中,接口 Circle 和 Rectangle 組成一個聯合類型Circle | Rectangle。因此,這個聯合類型的同名屬性area,也是一個聯合類型。本例中的 declare 命令表示變量 s 的具體定義,由其他腳本文件給出。

interface 與 type 的異同

interface 命令與 type 命令作用類似,都可以表示對象類型。

很多對象類型即可以用 interface 表示,也可以用 type 表示。而且,兩者往往可以換用,幾乎所有的 interface 命令都可以改寫為 type 命令。

它們的相似之處,首先表現在都能為對象類型起名。

type Country = {name: string;capital: string;
};interface Coutry {name: string;capital: string;
}

上面示例是 type 命令和 interface 命令,分別定義同一個類型。

class 命令也有類似作用,通過定義一個類,同時定義一個對象類型。但是,它會創造一個值,編譯后依然存在。如果只是單純想要一個類型,應該使用 typeinterface

interfacetype 的區別有下面幾點。

(1)type 能夠表示非對象類型,而 interface 只能表示對象類型(包括數組函數等)。

(2)interface 可以繼承其他類型,type 不支持繼承。

繼承的主要作用是添加屬性,type 定義的對象類型如果想要添加屬性,只能使用&運算符,重新定義一個類型。

type Animal = {name: string;
};type Bear = Animal & {honey: boolean;
};

上面示例中,類型 Bear 在 Animal 的基礎上添加了一個屬性 honey。

上例的 & 運算符,表示同時具備兩個類型的特征,因此可以起到兩個對象類型合并的作用。

作為比較,interface 添加屬性,采用的是繼承的寫法。

interface Animal {name: string;
}interface Bear extends Animal {honey: boolean;
}

繼承時,typeinterface 是可以換用的。interface 可以繼承 type

type Foo = { x: number };interface Bar extends Foo {y: number;
}

type 也可以繼承 interface。

interface Foo {x: number;
}type Bar = Foo & { y: number };

(3)同名 interface 會自動合并,同名 type 則會報錯。也就是說,TypeScript 不允許使用 type 多次定義同一個類型。

type A = { foo: number }; // 報錯
type A = { bar: number }; // 報錯

上面示例中,type兩次定義了類型A,導致兩行都會報錯。

作為比較,interface 則會自動合并。

interface A {foo: number;
}
interface A {bar: number;
}const obj: A = {foo: 1,bar: 1,
};

上面示例中,interface 把類型A的兩個定義合并在一起。

這表明,interface 是開放的,可以添加屬性,type 是封閉的,不能添加屬性,只能定義新的 type。

(4)interface 不能包含屬性映射(mapping),type 可以

interface Point {x: number;y: number;
}// 正確
type PointCopy1 = {[Key in keyof Point]: Point[Key];
};// 報錯
interface PointCopy2 {[Key in keyof Point]: Point[Key];
};

(5)this 關鍵字只能用于 interface

// 正確
interface Foo {add(num: number): this;
}// 報錯
type Foo = {add(num: number): this;
};

上面示例中,type 命令聲明的方法add(),返回this就報錯了。interface 命令沒有這個問題。

下面是返回 this 的實際對象的例子。

interface GetInfo {(x:number): this
}const getInfo:GetInfo = function (x: number) {return this;
}

(6)interface 可以直接擴展原始數據類型,type只能間接實現

  • interface

    我們可以通過擴展全局接口(Global Interfaces)來為原始數據類型添加新的方法或屬性。這是因為 TypeScript 的原始類型(如stringnumberboolean等)都有對應的全局接口定義。

    // 擴展Number接口
    interface Number {isEven(): boolean;toPercentage(): string;
    }// 實現擴展的方法
    Number.prototype.isEven = function() {return this % 2 === 0;
    };Number.prototype.toPercentage = function() {return `${this * 100}%`;
    };// 使用示例
    const num1 = 10;
    console.log(num1.isEven()); // 輸出: trueconst num2 = 0.75;
    console.log(num2.toPercentage()); // 輸出: "75%"
    

    注意事項:在模塊化項目中,需要使用declare global包裹接口擴展:

    declare global {interface Number {// 擴展方法定義}
    }
    

    但需要避免過度擴展原始類型,以免造成代碼維護困難和潛在沖突。那有沒有更好的方式來規避這個問題,我們接著看。

  • type

    在 TypeScript 中,無法直接用 type 擴充原生 Number 類型,這是由 TypeScript 的類型系統設計決定的:原生類型(如Number)的擴展只能通過 interface 的聲明合并實現,而 type 不支持聲明合并。

    不過,可以通過type創建一個 “增強版數字類型”,并關聯擴展方法,間接實現類似效果:

    // 1. 用type定義增強型數字類型(本質仍是number,但帶有擴展語義)
    type EnhancedNumber = number;// 2. 定義擴展方法的類型(約束方法參數和返回值)
    type NumberExtensions = {isEven: (num: EnhancedNumber) => boolean;toPercent: (num: EnhancedNumber) => string;
    };// 3. 實現擴展方法
    const enhance: NumberExtensions = {isEven: (num) => num % 2 === 0,toPercent: (num) => `${(num * 100)}%`
    };// 4. 使用示例
    const num: EnhancedNumber = 0.25;// 調用擴展方法(通過工具對象關聯)
    console.log(enhance.isEven(4)); // 輸出: true
    console.log(enhance.toPercent(num)); // 輸出: "25.0%"// 仍可使用原生Number方法
    console.log(num.toFixed(2)); // 輸出: "0.25"
    

    核心區別說明:

    • type的局限性:type 是類型別名,無法像 interface 那樣通過聲明合并擴展原生類型的方法集,只能通過工具函數 / 對象間接關聯擴展功能。
    • 實現思路:通過type EnhancedNumber = number創建語義化類型,再用type約束擴展方法的類型,最后通過工具對象實現功能。
    • 類型安全:這種方式仍能保證類型一致性,同時保留原生數字的所有特性。

    如果需要直接在數字實例上調用擴展方法(如 num.isEven()),必須使用 interface 的聲明合并,這是 TypeScript 規范中擴展原生類型的唯一方式。type 更適合創建語義化類型或組合類型,而非直接擴展原生類型的方法。

(7)interface 無法表達某些復雜類型(比如交叉類型聯合類型),但是 type 可以。

type A = {/* ... */
};
type B = {/* ... */
};type AorB = A | B;
type AorBwithName = AorB & {name: string;
};

上面示例中,類型 AorB 是一個聯合類型,AorBwithName則是為AorB添加一個屬性。這兩種運算,interface 都沒法表達。

綜上所述,如果有復雜的類型運算,那么沒有其他選擇只能使用 type;一般情況下,interface靈活性比較高,便于擴充類型或自動合并,建議優先使用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94653.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94653.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94653.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構青銅到王者第五話---LinkedList與鏈表(2)

目錄 一、常見的鏈表題目練習(續) 1、鏈表的回文結構。 2、輸入兩個鏈表,找出它們的第一個公共結點。 3、給定一個鏈表,判斷鏈表中是否有環。 4、給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環&#…

Kafa面試經典題--Kafka為什么吞吐量大,速度快

這是一個非常核心的面試題和技術問題。Kafka 的高吞吐量和速度并非來自某一項“銀彈”技術,而是其架構設計中一系列精巧決策共同作用的結果。 一、核心思想:最大化利用底層硬件資源 Kafka 速度快的根本原因是,它的設計哲學是 “盡可能地避免不必要的開銷,并將硬件(尤其是…

Stream API 新玩法:從 teeing()到 mapMulti()

1. 背景:Stream API 的演進 自 Java 8 引入 Stream API 以來,Java 的集合處理方式發生了質變。開發者可以用聲明式風格實現復雜的數據轉換與聚合。然而,隨著應用場景多樣化,社區逐漸發現一些“尷尬空缺”: 聚合時&…

STM32G4 SVPWM VF開環強拖電機

目錄一、STM32G4 SVPWM VF開環強拖電機1 SVPWM1.1 SVPWM技術簡介1.2 基于零序分量注入的SVPWM算法的實現2. VF開環強拖電機3. VF啟動電機實驗現象附學習參考網址歡迎大家有問題評論交流 (* ^ ω ^)一、STM32G4 SVPWM VF開環強拖電機 1 SVPWM 1.1 SVPWM技術簡介 SVPWM控制策略…

產品運營必備職場通用能力及提升攻略,一文說明白

在互聯網行業蓬勃發展的當下,產品運營崗位成為了連接產品、用戶與商業目標的關鍵紐帶。從用戶增長到活動策劃,從數據分析到跨部門協作,產品運營人員需具備多元化技能,才能在激烈競爭中嶄露頭角。隨著企業對精細化運營與數據驅動決…

面試 總結(1)

面試總結 一、spring相關 1. Spring Security角色管理實現 在智慧種植蟲害識別系統中,我實現了農戶端和企業端的雙角色權限控制,這一部分是這樣實現的: MySQL 表時設計區分農戶和企業的角色表與權限表。登錄時,JWT 令牌包含用戶 I…

串與數組:從字符處理到多維存儲的數據結構詳解

串(字符串)和數組是數據結構中的兩個重要分支,它們在程序設計中承擔著不同但互補的角色。串專門處理字符數據,而數組則提供了多維數據的存儲和訪問機制。本文將深入探討這兩種數據結構的理論基礎、實現方法和核心算法。 文章目錄1…

面試之JVM

類的生命周期 加載、鏈接、初始化(是類的初始化)、使用(對象的初始化)、卸載(GC) 鏈接:驗證、準備、解析 類加載 JDK9的升級點:擴展類加載器改成了平臺類加載器。 java中很多的包分…

webpack開發模式與生產模式(webpack --mode=development/production“, )

webpack開發模式與生產模式的區別webpack的development(開發模式)和production(生產模式)是兩種常見的構建環境配置,主要區別體現在構建速度、代碼優化和調試支持等方面。開發模式 (development)目標:注重開…

當自然語言遇上數據庫:Text2Sql.Net的MCP革命如何重新定義開發者與數據的交互方式

想象一下,在IDE中對AI助手說"幫我找出本月銷售額最高的前10個產品",然后它不僅能理解你的意圖,還能直接生成并執行SQL查詢,返回準確結果——這不是科幻,而是Text2Sql.Net的MCP集成帶來的現實。 &#x1f3af…

2025流程圖模板和工具深度評測:AI如何提升繪圖效率80%?

引言:流程圖模板的價值革命 在數字化辦公的浪潮中,流程圖已從單純的"業務說明工具"進化為跨部門協作的"視覺語言"。據智研咨詢2025年報告顯示,規范使用流程圖模板可使團隊溝通效率提升40%,錯誤率降低58%。無…

WebSocket實時通信系統——js技能提升

2. WebSocket實時通信系統 功能概述 實現完整的WebSocket通信系統,支持實時消息推送、連接管理、心跳檢測和自動重連。 技術難點 WebSocket連接生命周期管理消息序列化和反序列化心跳機制和連接保活錯誤處理和重連策略多組件狀態同步 實現思路 2.1 WebSocket管理器 …

Spring AI 入門指南:三步將AI集成到Spring Boot應用

無需深入AI底層實現,Java開發者也能快速構建智能應用本文將介紹如何使用 Spring AI 在 Spring Boot 項目中快速集成 AI 能力。通過三步操作——添加依賴、配置 API 憑證和編寫調用代碼,Java 開發者可以輕松構建 AI 應用。一、Spring AI 簡介Spring AI 是…

OOM問題排查思路及解決方案

OOM問題原因: 根本原因是創建的對象數量超過JVM堆內存容量,且這些對象無法被GC回收場景: 1.本地緩存了用戶態,用戶量急劇上升導致內存溢出,如使用HashMap本地緩存10萬用戶數據,每 個用戶對象約2KB&#xf…

梨花教育暖心鵬城:深圳市養老護理院里“時光綻放”,用聲音點亮銀發精神之光

2025年8月24日,在深圳這座充滿活力與夢想的城市,一場溫暖人心的公益活動在深圳市養老護理院溫情上演。梨花教育策劃并組織了“梨花?時光綻放”公益活動,旨在通過聲音的魅力,為市養老護理院的老人們送去關懷與歡樂,豐富…

力扣100+補充大完結

力扣100分類一、Java基礎代碼模板1. 基礎輸入輸出模板import java.util.Scanner;class Solution {public static int linkedListOperation() {// 鏈表操作實現return 0;}public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.next…

SSM從入門到實戰:3.3 SpringMVC數據綁定與驗證

👋 大家好,我是 阿問學長!專注于分享優質開源項目解析、畢業設計項目指導支持、幼小初高的教輔資料推薦等,歡迎關注交流!🚀 📖 本文概述 本文是SSM框架系列SpringMVC基礎篇的第三篇&#xff0…

ctfshow_萌新web16-web20-----文件包含日志注入

_萌新web16解開md5?c36d_萌新web17-----文件包含禁用了php關鍵字&#xff0c;這個題禁了遠程文件包含,進行日志注入發現日志中有user-agent信息&#xff0c;因此我們可以在user-agent中寫入木馬抓包burpsuitUser-agent:<?php eval($_POST[cmd])?>抓包然后連接蟻劍_萌新…

Flink的CheckPoint與SavePoint

Flink的Checkpoint&#xff08;檢查點&#xff09;和Savepoint&#xff08;保存點&#xff09;是兩種不同的狀態快照機制&#xff0c;主要區別如下&#xff1a;1. ?Checkpoint??核心功能?&#xff1a;周期性觸發的容錯機制&#xff0c;用于故障恢復時保證狀態一致性57。?觸…

Ansible 自動化運維工具:介紹與完整部署(RHEL 9)

Ansible 自動化運維工具&#xff1a;介紹與完整部署&#xff08;RHEL 9&#xff09;Ansible 的介紹與安裝 一、自動化運維的必要性 傳統手動運維依賴圖形/命令行界面、檢查清單或記憶執行任務&#xff0c;存在以下核心問題&#xff1a; 易出錯&#xff1a;易跳過步驟或執行錯誤…