国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

手把手教你落地DDD

這篇具有很好參考價(jià)值的文章主要介紹了手把手教你落地DDD。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

手把手教你落地DDD

一、前言
常見(jiàn)的DDD實(shí)現(xiàn)架構(gòu)有很多種,如經(jīng)典四層架構(gòu)、六邊形(適配器端口)架構(gòu)、整潔架構(gòu)(Clean Architecture)、CQRS架構(gòu)等。架構(gòu)無(wú)優(yōu)劣高下之分,只要熟練掌握就都是合適的架構(gòu)。本文不會(huì)逐個(gè)去講解這些架構(gòu),感興趣的讀者可以自行去了解。
本文將帶領(lǐng)大家從日常的三層架構(gòu)出發(fā),精煉推導(dǎo)出我們自己的應(yīng)用架構(gòu),并且將這個(gè)應(yīng)用架構(gòu)實(shí)現(xiàn)為Maven Archetype,最后使用我們Archetype創(chuàng)建一個(gè)簡(jiǎn)單的CMS項(xiàng)目作為本文的落地案例。
需要明確的是,本文只是給讀者介紹了DDD應(yīng)用架構(gòu),還有許多概念沒(méi)有涉及,例如實(shí)體、值對(duì)象、聚合、領(lǐng)域事件等,如果讀者對(duì)完整落地DDD感興趣,可以到本文最后了解更多。
二、應(yīng)用架構(gòu)演化
我們很多項(xiàng)目是基于三層架構(gòu)的,其結(jié)構(gòu)如圖:
手把手教你落地DDD
我們說(shuō)三層架構(gòu),為什么還畫(huà)了一層 Model 呢?因?yàn)?Model 只是簡(jiǎn)單的 Java Bean,里面只有數(shù)據(jù)庫(kù)表對(duì)應(yīng)的屬性,有的應(yīng)用會(huì)將其單獨(dú)拎出來(lái)作為一個(gè)
Maven Module,但實(shí)際上可以合并到 DAO 層。
接下來(lái)我們開(kāi)始對(duì)這個(gè)三層架構(gòu)進(jìn)行抽象精煉。

2.1 第一步、數(shù)據(jù)模型與DAO層合并

為什么數(shù)據(jù)模型要與DAO層合并呢?
首先,數(shù)據(jù)模型是貧血模型,數(shù)據(jù)模型中不包含業(yè)務(wù)邏輯,只作為裝載模型屬性的容器;
其次,數(shù)據(jù)模型與數(shù)據(jù)庫(kù)表結(jié)構(gòu)的字段是一一對(duì)應(yīng)的,數(shù)據(jù)模型最主要的應(yīng)用場(chǎng)景就是DAO層用來(lái)進(jìn)行 ORM,給 Service 層返回封裝好的數(shù)據(jù)模型,供Service 獲取模型屬性以執(zhí)行業(yè)務(wù);
最后,數(shù)據(jù)模型的 Class 或者屬性字段上,通常帶有 ORM 框架的一些注解,跟DAO層聯(lián)系非常緊密,可以認(rèn)為數(shù)據(jù)模型就是DAO層拿來(lái)查詢(xún)或者持久化數(shù)據(jù)的,數(shù)據(jù)模型脫離了DAO層,意義不大。

2.2 第二步、Service層抽取業(yè)務(wù)邏輯

下面是一個(gè)常見(jiàn)的 Service 方法的偽代碼,既有緩存、數(shù)據(jù)庫(kù)的調(diào)用,也有實(shí)際的業(yè)務(wù)邏輯,整體過(guò)于臃腫,要進(jìn)行單元測(cè)試更是無(wú)從下手。
public class Service {

    @Transactional
    public void bizLogic(Param param) {

        checkParam(param);//校驗(yàn)不通過(guò)則拋出自定義的運(yùn)行時(shí)異常

        Data data = new Data();//或者是mapper.queryOne(param);

        data.setId(param.getId());

        if (condition1 == true) {
            biz1 = biz1(param.getProperty1());
            data.setProperty1(biz1);
        } else {
            biz1 = biz11(param.getProperty1());
            data.setProperty1(biz1);
        }

        if (condition2 == true) {
            biz2 = biz2(param.getProperty2());
            data.setProperty2(biz2);
        } else {
            biz2 = biz22(param.getProperty2());
            data.setProperty2(biz2);
        }

        //省略一堆set方法
        mapper.updateXXXById(data);
    }
}
這是典型的事務(wù)腳本的代碼:先做參數(shù)校驗(yàn),然后通過(guò) biz1、biz2 等子方法做業(yè)務(wù),并將其結(jié)果通過(guò)一堆 Set 方法設(shè)置到數(shù)據(jù)模型中,再將數(shù)據(jù)模型更新到數(shù)據(jù)庫(kù)。
由于所有的業(yè)務(wù)邏輯都在 Service 方法中,造成 Service 方法非常臃腫,Service 需要了解所有的業(yè)務(wù)規(guī)則,并且要清楚如何將基礎(chǔ)設(shè)施串起來(lái)。同樣的一條規(guī)則,例如if(condition1=true),很有可能在每個(gè)方法里面都出現(xiàn)。
專(zhuān)業(yè)的事情就該讓專(zhuān)業(yè)的人干,既然業(yè)務(wù)邏輯是跟具體的業(yè)務(wù)場(chǎng)景相關(guān)的,我們想辦法把業(yè)務(wù)邏輯提取出來(lái),形成一個(gè)模型,讓這個(gè)模型的對(duì)象去執(zhí)行具體的業(yè)務(wù)邏輯。這樣Service方法就不用再關(guān)心里面的 if/else 業(yè)務(wù)規(guī)則,只需要通過(guò)業(yè)務(wù)模型執(zhí)行業(yè)務(wù)邏輯,并提供基礎(chǔ)設(shè)施完成用例即可。
將業(yè)務(wù)邏輯抽象成模型,這樣的模型就是領(lǐng)域模型。
要操作領(lǐng)域模型,必須先獲得領(lǐng)域模型,但此時(shí)我們先不管領(lǐng)域模型怎么得到,假設(shè)是通過(guò)loadDomain方法獲得的。通過(guò) Service方法的入?yún)?,我們調(diào)用loadDomain方法得到一個(gè)模型,我們讓這個(gè)模型去做業(yè)務(wù)邏輯,最后執(zhí)行的結(jié)果也都在模型里,我們?cè)賹⒛P突貙?xiě)數(shù)據(jù)庫(kù)。當(dāng)然,怎么寫(xiě)數(shù)據(jù)庫(kù)的我們也先不管,假設(shè)是通過(guò)saveDomain方法。
Service層的方法經(jīng)過(guò)抽取之后,將得到如下的偽代碼:
public class Service {

    public void bizLogic(Param param) {

        //如果校驗(yàn)不通過(guò),則拋一個(gè)運(yùn)行時(shí)異常
        checkParam(param);
        //加載模型
        Domain domain = loadDomain(param);
        //調(diào)用外部服務(wù)取值
      SomeValue someValue=this.getSomeValueFromOtherService(param.getProperty2());
        //模型自己去做業(yè)務(wù)邏輯,Service不關(guān)心模型內(nèi)部的業(yè)務(wù)規(guī)則
        domain.doBusinessLogic(param.getProperty1(), someValue);
        //保存模型
        saveDomain(domain);
    }
}
根據(jù)代碼,我們已經(jīng)將業(yè)務(wù)邏輯抽取出來(lái)了,領(lǐng)域相關(guān)的業(yè)務(wù)規(guī)則封閉在領(lǐng)域模型內(nèi)部。此時(shí) Service方法非常直觀(guān),就是獲取模型、執(zhí)行業(yè)務(wù)邏輯、保存模型,再協(xié)調(diào)基礎(chǔ)設(shè)施完成其余的操作。
抽取完領(lǐng)域模型后,我們工程的結(jié)構(gòu)如下圖:
手把手教你落地DDD

2.3 第三步、維護(hù)領(lǐng)域?qū)ο笊芷?/h2>
在上一步中,loadDomain、saveDomain 這兩個(gè)方法還沒(méi)有得到討論,這兩個(gè)方法跟領(lǐng)域?qū)ο蟮纳芷谙⑾⑾嚓P(guān)。
關(guān)于領(lǐng)域?qū)ο蟮纳芷诘脑敿?xì)知識(shí),讀者可以自行學(xué)習(xí)了解。
不管是 loadDomain 還是 saveDomain,我們一般都要依賴(lài)于數(shù)據(jù)庫(kù),所以這兩個(gè)方法對(duì)應(yīng)的邏輯,肯定是要跟 DAO 產(chǎn)生聯(lián)系的。
保存或者加載領(lǐng)域模型,我們可以抽象成一種組件,通過(guò)這種組件進(jìn)行封裝模型加載、保存的操作,這種組件就是Repository。
注意,Repository 是對(duì)加載或者保存領(lǐng)域模型(這里指的是聚合根,因?yàn)橹挥芯酆细艜?huì)有Repository)的抽象,必須對(duì)上層屏蔽領(lǐng)域模型持久化的細(xì)節(jié),因此其方法的入?yún)⒒蛘叱鰠?,一定是基本?shù)據(jù)類(lèi)型或者領(lǐng)域模型,不能是數(shù)據(jù)庫(kù)表對(duì)應(yīng)的數(shù)據(jù)模型。
以下是 Repository 的偽代碼:

public interface DomainRepository {

    void save(AggregateRoot root);

    AggregateRoot load(EntityId id);
}
接下來(lái)我們要考慮在哪里實(shí)現(xiàn)DomainRepository。既然 DomainRepository 與底層數(shù)據(jù)庫(kù)有關(guān)聯(lián),但是我們現(xiàn)在 DAO 層并沒(méi)有引入 Domain 這個(gè)包,DAO 層自然無(wú)法提供 DomainRepository的實(shí)現(xiàn),我們初步考慮是不是可以將 DomainRepository 實(shí)現(xiàn)在 Service 層。
但是,如果我們?cè)?Service 中實(shí)現(xiàn)DomainRepository,勢(shì)必需要在 Service 層操作數(shù)據(jù)模型:查詢(xún)出來(lái)數(shù)據(jù)模型再封裝為領(lǐng)域模型、或者將領(lǐng)域模型轉(zhuǎn)為數(shù)據(jù)模型再通過(guò)ORM 保存,這個(gè)過(guò)程不該是 Service 層關(guān)心的。
因此,我們決定在 DAO 層直接引入 Domain 包,并在 DAO 層提供 DomainRepository 接口的實(shí)現(xiàn),DAO 層查詢(xún)出數(shù)據(jù)模型之后,封裝成領(lǐng)域模型供DomainRepository 返回。
這樣調(diào)整之后, DAO 層不再向 Service 返回?cái)?shù)據(jù)模型,而是返回領(lǐng)域模型,這就隱藏了數(shù)據(jù)庫(kù)交互的細(xì)節(jié),我們也把DAO層換個(gè)名字稱(chēng)之為Repository。
現(xiàn)在,我們項(xiàng)目的架構(gòu)圖是這樣的了:
手把手教你落地DDD

由于數(shù)據(jù)模型屬于貧血模型,自身沒(méi)有業(yè)務(wù)邏輯,并且只有Repository這個(gè)包會(huì)用到,因此我們將之合并到Repository中,接下來(lái)不再單獨(dú)列舉。

2.4 第四步、泛化抽象

在第三步中,我們的架構(gòu)圖已經(jīng)跟經(jīng)典四層架構(gòu)非常相似了,我們?cè)賹?duì)某些層進(jìn)行泛化抽象。
  • Infrastructure
Repository 倉(cāng)儲(chǔ)層其實(shí)屬于基礎(chǔ)設(shè)施層,只不過(guò)其職責(zé)是持久化和加載聚合,所以,我們將 Repository層改名為 infrastructure-persistence,可以理解為基礎(chǔ)設(shè)施層持久化包。
之所以采取這種 infrastructure-XXX 的格式進(jìn)行命名,是由于 Infrastructure 可能會(huì)有很多的包,分別提供不同的基礎(chǔ)設(shè)施支持。
例如:一般的項(xiàng)目,還有可能需要引入緩存,我們就可以再加一個(gè)包,名字叫infrastructure-cache。
對(duì)于外部的調(diào)用,DDD中有防腐層的概念,將外部模型通過(guò)防腐層進(jìn)行隔離,避免污染本地上下文的領(lǐng)域模型。我們使用入口(Gateway)來(lái)封裝對(duì)外部系統(tǒng)或資源的訪(fǎng)問(wèn)(詳細(xì)見(jiàn)《企業(yè)應(yīng)用架構(gòu)模式》,18.1入口(Gateway)),因此將對(duì)外調(diào)用這一層稱(chēng)之為infrastructure-gateway。

注意:Infrastructure 層的門(mén)面接口都應(yīng)先在Domain 層定義,其方法的入?yún)?、出參,都?yīng)該是領(lǐng)域模型(實(shí)體、值對(duì)象)或者基本類(lèi)型。

  • User Interface
Controller 層其實(shí)就是用戶(hù)接口層,即 User Interface 層,我們?cè)陧?xiàng)目簡(jiǎn)稱(chēng) ui。當(dāng)然了可能很多開(kāi)發(fā)者會(huì)覺(jué)得叫UI好像很別扭,認(rèn)為 UI就是 UI 設(shè)計(jì)師設(shè)計(jì)的圖形界面。
Controller 層的名字有很多,有的叫 Rest,有的叫 Resource,考慮到我們這一層不只是有 Rest 接口,還可能還有一系列 Web相關(guān)的攔截器,所以我一般稱(chēng)之為 Web。因此,我們將其改名為 ui-web,即用戶(hù)接口層的 Web 包。
同樣,我們可能會(huì)有很多的用戶(hù)接口,但是他們通過(guò)不同的協(xié)議對(duì)外提供服務(wù),因而被劃分到不同的包中。
我們?nèi)绻袑?duì)外提供的 RPC服務(wù),那么其服務(wù)實(shí)現(xiàn)類(lèi)所在的包就可以命名為 ui-provider。
有時(shí)候引入某個(gè)中間件會(huì)同時(shí)增加 Infrastructure 和 User Interface。
例如,如果引入 Kafka 就需要考慮一下,如果是給 Service 層提供調(diào)用的,例如邏輯執(zhí)行完發(fā)送消息通知下游,那么我們?cè)偌右粋€(gè)包infrastructure-publisher;如果是消費(fèi) Kafka 的消息,然后調(diào)用 Service 層執(zhí)行業(yè)務(wù)邏輯的,那么就可以命名為 ui-subscriber。
  • Application
至此,Service 層目前已經(jīng)沒(méi)有業(yè)務(wù)邏輯了,業(yè)務(wù)邏輯都在 Domain 層去執(zhí)行了,Service 只是協(xié)調(diào)領(lǐng)域模型、基礎(chǔ)設(shè)施層完成業(yè)務(wù)邏輯。
所以,我們把 Service 層改名為 Application Service 層。
經(jīng)過(guò)第四步的抽象,其架構(gòu)圖為:
手把手教你落地DDD

2.5 第五步、完整的包結(jié)構(gòu)

我們繼續(xù)對(duì)第四步中出現(xiàn)的包進(jìn)行整理,此時(shí)還需要考慮一個(gè)問(wèn)題,我們的啟動(dòng)類(lèi)應(yīng)該放在哪里?
由于有很多的 User Interface,所以啟動(dòng)類(lèi)放在任意一個(gè)User Interface中都不合適,放置在A(yíng)pplication Service中也不合適,因此,啟動(dòng)類(lèi)應(yīng)該存放在單獨(dú)的模塊中。又因?yàn)?application這個(gè)名字被應(yīng)用層占用了,所以將啟動(dòng)類(lèi)所在的模塊命名為 launcher,一個(gè)項(xiàng)目可以存在多個(gè)launcher,按需引用User Interface。
加入啟動(dòng)包,我們就得到了完整的 maven 包結(jié)構(gòu)。
包結(jié)構(gòu)如圖所示:
手把手教你落地DDD
至此,DDD 項(xiàng)目的整體結(jié)構(gòu)基本講完了。

2.6 精煉后的思考

在經(jīng)過(guò)前面五步精煉得到這個(gè)架構(gòu)圖中,經(jīng)典四層架構(gòu)的四層都出現(xiàn)了,而且長(zhǎng)得跟六邊形架構(gòu)也很像。這是為什么呢?
其實(shí),不管是經(jīng)典四層架構(gòu)、還是六邊形架構(gòu),亦或者整潔架構(gòu),都是對(duì)系統(tǒng)應(yīng)用的描述,也許描述的側(cè)重點(diǎn)不一樣,但是描述的是同一個(gè)事物。既然描述的是同一個(gè)事物,長(zhǎng)得像才是理所當(dāng)然的,不可能只是換一個(gè)描述方式,系統(tǒng)就從根本上發(fā)生了改變。
對(duì)于任何一個(gè)應(yīng)用,都可以看成“輸入-處理-輸出”的過(guò)程。
“輸入”環(huán)節(jié):通過(guò)某種協(xié)議對(duì)外暴露領(lǐng)域的能力,這些協(xié)議可能是 REST、可能是 RPC、可能是 MQ 的訂閱者,也可能是WebSocket,也可能是一些任務(wù)調(diào)度的 Task;
”處理“環(huán)節(jié):處理環(huán)節(jié)是整個(gè)應(yīng)用的核心,代表了應(yīng)用具備的核心能力,是應(yīng)用的價(jià)值所在,應(yīng)用在這個(gè)環(huán)節(jié)執(zhí)行業(yè)務(wù)邏輯,貧血模型由Service執(zhí)行業(yè)務(wù)處理,充血模型則是由模型進(jìn)行業(yè)務(wù)處理。
“輸出”環(huán)節(jié),業(yè)務(wù)邏輯執(zhí)行完成之后將結(jié)果輸出到外部。
不管我們采用的什么架構(gòu),其描述的應(yīng)用的核心都是這個(gè)過(guò)程,不必生搬硬套非得用什么應(yīng)用架構(gòu)。
正如《金剛經(jīng)》所言:一切有為法,如夢(mèng)幻泡影,如露亦如電,應(yīng)作如是觀(guān);凡所有相,皆是虛妄;若見(jiàn)諸相非相,即見(jiàn)如來(lái)。
三、ddd-archetype

3.1 Maven Archetype介紹

Maven Archetype是一個(gè)Maven插件,可以幫助開(kāi)發(fā)人員快速創(chuàng)建項(xiàng)目的基礎(chǔ)結(jié)構(gòu),大大減少開(kāi)發(fā)人員在創(chuàng)建項(xiàng)目時(shí)所需的時(shí)間和精力,并且可以確保項(xiàng)目結(jié)構(gòu)的一致性和可重用性,從而提高代碼質(zhì)量和可維護(hù)性。
我們?cè)诮榻BDDD應(yīng)用架構(gòu)時(shí),對(duì)項(xiàng)目的結(jié)構(gòu)進(jìn)行了介紹。我們將項(xiàng)目分為多個(gè)Maven Module,如果每個(gè)項(xiàng)目都手工創(chuàng)建一次,是比較繁瑣的工作,也不利項(xiàng)目結(jié)構(gòu)的統(tǒng)一。
我們使用Maven Archetype創(chuàng)建DDD項(xiàng)目初始化的腳手架,使其在初始化時(shí)完整實(shí)現(xiàn)上文第五步的應(yīng)用架構(gòu)。

3.2 ddd-archetype的使用

3.2.1 項(xiàng)目介紹

ddd-archetype是一個(gè)Maven Archetype的原型工程,我們將其克隆到本地之后,可以安裝為Maven Archetype,幫助我們快速創(chuàng)建DDD項(xiàng)目腳手架。
項(xiàng)目鏈接:https://github.com/feiniaojin/ddd-archetype

3.2.2 安裝過(guò)程

以下將以IDEA為例展示ddd-archetype的安裝使用過(guò)程,主要過(guò)程是:
克隆項(xiàng)目-->archetype:create-from-project-->install-->archetype:crawl

3.2.3 克隆項(xiàng)目

將項(xiàng)目克隆到本地:
git clone https://github.com/feiniaojin/ddd-archetype.git
直接使用主分支即可,然后使用IDEA打開(kāi)該項(xiàng)目
手把手教你落地DDD

3.2.4 archetype:create-from-project

配置打開(kāi)IDEA的run/debug configurations窗口,如下:

手把手教你落地DDD

選擇add new configurations,彈出以下窗口:
其中,上圖中1~4各個(gè)標(biāo)識(shí)的值為:
標(biāo)識(shí)1 - 選擇"+"號(hào);
標(biāo)識(shí)2?- 選擇"Maven";
標(biāo)識(shí)3 - 命令為:
archetype:create-from-project -Darchetype.properties=archetype.properties

注意,在IDEA中添加的命令默認(rèn)不需要加mvn

標(biāo)識(shí)4?- 選擇ddd-archetype的根目錄
以上配置完成后,點(diǎn)擊執(zhí)行該命令。

3.2.5 install

上一步執(zhí)行完成且無(wú)報(bào)錯(cuò)之后,配置install命令。
手把手教你落地DDD
其中,上圖中1~2各個(gè)標(biāo)識(shí)的值為:
標(biāo)識(shí)1 - 值為install;
標(biāo)識(shí)2 - 值為上一步運(yùn)行的結(jié)果,路徑為:
ddd-archetype/target/generated-sources/archetype
install配置完成之后,點(diǎn)擊執(zhí)行。

3.2.6 archetype:crawl

install執(zhí)行完成且無(wú)報(bào)錯(cuò),接著配置archetype:crawl命令。
手把手教你落地DDD
其中,標(biāo)識(shí)1中的值為:
archetype:crawl
配置完成,點(diǎn)擊執(zhí)行即可。

3.3 使用ddd-archetype初始化項(xiàng)目

  • 創(chuàng)建項(xiàng)目時(shí),點(diǎn)擊manage catalogs:
    手把手教你落地DDD
  • 將本地的maven私服中的archetype-catalog.xml加入到catalogs中:
手把手教你落地DDD
添加成功,如下:
創(chuàng)建項(xiàng)目時(shí),選擇本地archetype-catalog,并且選擇ddd-archetype,填入項(xiàng)目信息并創(chuàng)建項(xiàng)目:
手把手教你落地DDD
項(xiàng)目創(chuàng)建完成后:
手把手教你落地DDD
四、代碼案例
本文提供了配套的代碼案例,該案例使用DDD和本文的應(yīng)用架構(gòu)實(shí)現(xiàn)了簡(jiǎn)單的CMS系統(tǒng)。案例項(xiàng)目采用前后端分離的方式,因此有后端和前端兩個(gè)代碼庫(kù)。

4.1 后端

后端項(xiàng)目使用本文的ddd-archetype創(chuàng)建,實(shí)現(xiàn)了部分CMS的功能,并落地部分DDD的概念。
GitHub鏈接:https://github.com/feiniaojin/ddd-example-cms
手把手教你落地DDD
實(shí)現(xiàn)的DDD概念有:實(shí)體、值對(duì)象、聚合根、Factory、Repository、CQRS。
技術(shù)棧:
  • Spring Boot
  • H2內(nèi)存數(shù)據(jù)庫(kù)
  • Spring Data JDBC
無(wú)外部中間件依賴(lài) ,clone到本地即可編譯運(yùn)行,非常方便。

4.2 前端

前端項(xiàng)目基于vue-element-admin開(kāi)發(fā),詳細(xì)安裝方式見(jiàn)代碼庫(kù)的README。
GitHub鏈接:https://github.com/feiniaojin/ddd-example-cms-front
手把手教你落地DDD

4.3 運(yùn)行截圖

手把手教你落地DDD
五、總結(jié)以及進(jìn)一步學(xué)習(xí)
本文通過(guò)對(duì)貧血三層架構(gòu)進(jìn)行精煉,推導(dǎo)出適合我們落地的應(yīng)用架構(gòu),并且將之實(shí)現(xiàn)為Maven Archetype以應(yīng)用到實(shí)際開(kāi)發(fā),然而應(yīng)用架構(gòu)只是落地DDD的一個(gè)知識(shí)點(diǎn),要完整落地DDD還必須體系化地掌握限界上下文、上下文映射、充血模型、實(shí)體、值對(duì)象、領(lǐng)域服務(wù)、Factory、Repository等知識(shí)點(diǎn)。

-end-

作者|覃玉杰文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-597045.html

到了這里,關(guān)于手把手教你落地DDD的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 手把手教你用video實(shí)現(xiàn)視頻播放功能

    手把手教你用video實(shí)現(xiàn)視頻播放功能

    哈嘍。大家好啊 今天需要做一個(gè)視頻播放列表,讓我想到了video的屬性 下面讓我們先看看實(shí)現(xiàn)效果 這里是我的代碼 width是當(dāng)前播放頁(yè)面的寬度 height是當(dāng)前播放頁(yè)面的高度 Controls屬性用就是控制欄那些了 比如播放按鈕 暫停按鈕 autoplay是指的是自動(dòng)播放 poster是指的是初始化進(jìn)

    2024年02月12日
    瀏覽(32)
  • 手把手教你快速實(shí)現(xiàn)內(nèi)網(wǎng)穿透

    手把手教你快速實(shí)現(xiàn)內(nèi)網(wǎng)穿透

    前言 要想實(shí)現(xiàn)在公網(wǎng)訪(fǎng)問(wèn)到本地的項(xiàng)目,除了將其部署到云服務(wù)器上外,還可以通過(guò)內(nèi)網(wǎng)穿透來(lái)實(shí)現(xiàn),避免了項(xiàng)目出現(xiàn)問(wèn)題修改后需要重新部署到云服務(wù)器上比較繁瑣的步驟,也不需要公網(wǎng)IP以及服務(wù)器。 內(nèi)網(wǎng)穿透,簡(jiǎn)單來(lái)說(shuō)就是通過(guò)公網(wǎng)IP服務(wù)器進(jìn)行數(shù)據(jù)流量轉(zhuǎn)發(fā),將原本

    2024年02月13日
    瀏覽(22)
  • 深入淺出:手把手教你實(shí)現(xiàn)單鏈表

    深入淺出:手把手教你實(shí)現(xiàn)單鏈表

    鏈表是一種 鏈狀數(shù)據(jù)結(jié)構(gòu) 。簡(jiǎn)單來(lái)說(shuō),要存儲(chǔ)的數(shù)據(jù)在內(nèi)存中分別獨(dú)立存放,它們之間通過(guò)某種方式相互關(guān)聯(lián)。 如果我們使用C語(yǔ)言來(lái)實(shí)現(xiàn)鏈表,需要聲明一個(gè) 結(jié)構(gòu)體 作為鏈表的結(jié)點(diǎn),結(jié)點(diǎn)之間使用指針關(guān)聯(lián)。 單向鏈表的每個(gè)結(jié)點(diǎn)內(nèi)都有一個(gè)指針指向下一個(gè)結(jié)點(diǎn),從而把所

    2024年02月10日
    瀏覽(29)
  • 記錄--手把手教你,用electron實(shí)現(xiàn)截圖軟件

    記錄--手把手教你,用electron實(shí)現(xiàn)截圖軟件

    因?yàn)槲覀內(nèi)粘i_(kāi)發(fā)項(xiàng)目的時(shí)候,需要和同事對(duì)接 api 和 文檔 還有 UI圖 ,所以有時(shí)候要同時(shí)打開(kāi)多個(gè)窗口,并在多個(gè)窗口中切換,來(lái)選擇自己要的信息,如果 api 和 文檔 不多的情況還好,但是有時(shí)候就是要做大量的頁(yè)面,為了提升效率我決定自己做一個(gè)截圖工具,并把自己要

    2024年02月12日
    瀏覽(27)
  • 手把手教你用Python實(shí)現(xiàn)2048小游戲

    手把手教你用Python實(shí)現(xiàn)2048小游戲

    感覺(jué)好久沒(méi)有寫(xiě)小游戲玩了,今天恰巧有空.這次我來(lái)用Python做個(gè)2048小游戲吧.廢話(huà)不多說(shuō),文中有非常詳細(xì)的代碼示例,需要的朋友可以參考下 目錄 一、開(kāi)發(fā)環(huán)境 二、環(huán)境搭建 三、原理介紹 四、效果圖 Python版本:3.6.4 相關(guān)模塊: pygame模塊; 以及一些Python自帶的模塊。 安裝

    2024年04月28日
    瀏覽(94)
  • 手把手教你Shiro整合JWT實(shí)現(xiàn)登錄認(rèn)證

    手把手教你Shiro整合JWT實(shí)現(xiàn)登錄認(rèn)證

    SpringBoot Mybatis-plus Shiro JWT Redis Shiro: Shiro 是一個(gè)基于 Java 的開(kāi)源的安全框架。 在 Shiro 的核心架構(gòu)里面,Subject 是訪(fǎng)問(wèn)系統(tǒng)的用戶(hù)。SecurityManager 是安全管理器,負(fù)責(zé)用戶(hù)的認(rèn)證和授權(quán),相當(dāng)于 Shiro 的老大哥。 Realm 相當(dāng)于數(shù)據(jù)源,用戶(hù)的認(rèn)證和授權(quán)都在 Realm 的方法中進(jìn)行。

    2023年04月17日
    瀏覽(16)
  • 手把手教你實(shí)現(xiàn)一個(gè)循環(huán)隊(duì)列(C語(yǔ)言)

    手把手教你實(shí)現(xiàn)一個(gè)循環(huán)隊(duì)列(C語(yǔ)言)

    這是一道leetcode關(guān)于隊(duì)列的經(jīng)典題: 622.?設(shè)計(jì)循環(huán)隊(duì)列 https://leetcode.cn/problems/design-circular-queue/ ?大家注意這個(gè)題目要求,這個(gè)隊(duì)列是定長(zhǎng)的,如果滿(mǎn)了則不能再添加數(shù)據(jù)。那么我們?cè)O(shè)計(jì)一個(gè)隊(duì)頭front和隊(duì)尾rear,每次添加數(shù)據(jù)rear向后走,這時(shí)就有一個(gè)問(wèn)題, 怎么區(qū)分空和滿(mǎn)呢

    2024年02月04日
    瀏覽(24)
  • 應(yīng)用實(shí)踐|基于Python手把手教你實(shí)現(xiàn)雪花算法

    應(yīng)用實(shí)踐|基于Python手把手教你實(shí)現(xiàn)雪花算法

    ?? 作者簡(jiǎn)介:「六月暴雪飛梨花」,專(zhuān)注于研究Java,就職于科技型公司后端工程師 ?? 近期榮譽(yù):華為云云享專(zhuān)家、阿里云專(zhuān)家博主、 ?? 三連支持:歡迎 ??關(guān)注、??點(diǎn)贊、??收藏三連,支持一下博主~ 分布式策略ID的主要應(yīng)用在互聯(lián)網(wǎng)網(wǎng)站、搜索引擎、社交媒體、在線(xiàn)

    2024年02月21日
    瀏覽(27)
  • 【Linux】手把手教你實(shí)現(xiàn)udp服務(wù)器

    【Linux】手把手教你實(shí)現(xiàn)udp服務(wù)器

    網(wǎng)絡(luò)套接字~ 文章目錄 前言 一、udp服務(wù)器的實(shí)現(xiàn) 總結(jié) 上一篇文章中我們講到了很多的網(wǎng)絡(luò)名詞以及相關(guān)知識(shí),下面我們就直接進(jìn)入udp服務(wù)器的實(shí)現(xiàn)。 一、udp服務(wù)器的實(shí)現(xiàn) 首先我們需要?jiǎng)?chuàng)建五個(gè)文件(文件名可以自己命名也可以和我一樣),分別是makefile,udpclient.cc,udpclient.hpp

    2024年02月13日
    瀏覽(24)
  • 用Python手把手教你實(shí)現(xiàn)一個(gè)爬蟲(chóng)(含前端界面)

    用Python手把手教你實(shí)現(xiàn)一個(gè)爬蟲(chóng)(含前端界面)

    前言 爬蟲(chóng)基本原理 使用Python的requests庫(kù)發(fā)送HTTP請(qǐng)求 使用BeautifulSoup庫(kù)解析HTML頁(yè)面 使用PyQt5構(gòu)建前端界面 實(shí)現(xiàn)一個(gè)完整的爬蟲(chóng)程序 結(jié)語(yǔ) 隨著互聯(lián)網(wǎng)的飛速發(fā)展,再加上科技圈的技術(shù)翻天覆地的革新,互聯(lián)網(wǎng)上每天都會(huì)產(chǎn)生海量的數(shù)據(jù),這些數(shù)據(jù)對(duì)于企業(yè)和個(gè)人都具有重要的

    2024年04月28日
    瀏覽(28)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包