最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中樂(lè)觀(guān)鎖與悲觀(guān)鎖區(qū)別及使用場(chǎng)景分析

 更新時(shí)間:2024年08月04日 09:35:52   作者:kerwin_code  
本文主要介紹了java中樂(lè)觀(guān)鎖與悲觀(guān)鎖區(qū)別及使用場(chǎng)景分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、什么是樂(lè)觀(guān)鎖?什么是悲觀(guān)鎖

個(gè)人理解一句話(huà)概括就是,在應(yīng)用層面會(huì)造成線(xiàn)程阻塞的是悲觀(guān)鎖,而不會(huì)造成線(xiàn)程阻塞的是樂(lè)觀(guān)鎖,為什么這么說(shuō)會(huì)在后續(xù)的內(nèi)容中做詳細(xì)介紹。

1.1、悲觀(guān)鎖

  • 悲觀(guān)鎖是一種基于悲觀(guān)態(tài)度的數(shù)據(jù)并發(fā)控制機(jī)制,用于防止數(shù)據(jù)沖突。它采取預(yù)防性的措施,在修改數(shù)據(jù)之前將其鎖定,并在操作完成后釋放鎖定,以確保數(shù)據(jù)的一致性和完整性。悲觀(guān)鎖通常用于并發(fā)環(huán)境下的數(shù)據(jù)庫(kù)系統(tǒng),是數(shù)據(jù)庫(kù)本身實(shí)現(xiàn)鎖機(jī)制的一種方式。

  • 在悲觀(guān)鎖的機(jī)制下,當(dāng)一個(gè)使用者要修改某個(gè)數(shù)據(jù)時(shí),首先會(huì)嘗試獲取該數(shù)據(jù)的鎖。如果鎖已經(jīng)被其他使用者持有,則當(dāng)前使用者會(huì)被阻塞,直到對(duì)應(yīng)的鎖被釋放。這種悲觀(guān)的態(tài)度認(rèn)為數(shù)據(jù)沖突是不可避免的,因此在修改數(shù)據(jù)之前先鎖定數(shù)據(jù),以防止沖突的發(fā)生。

  • 在Java中,常見(jiàn)的悲觀(guān)鎖實(shí)現(xiàn)是使用synchronized關(guān)鍵字或ReentrantLock類(lèi)。這些鎖能夠確保同一時(shí)刻只有一個(gè)線(xiàn)程可以訪(fǎng)問(wèn)被鎖定的代碼塊或資源,其他線(xiàn)程必須等待鎖釋放后才能繼續(xù)執(zhí)行。

1.2、樂(lè)觀(guān)鎖

  • 樂(lè)觀(guān)鎖是一種基于版本控制的并發(fā)控制機(jī)制。在樂(lè)觀(guān)鎖的思想中,認(rèn)為數(shù)據(jù)訪(fǎng)問(wèn)沖突的概率很低,因此不加鎖直接進(jìn)行操作,但在更新數(shù)據(jù)時(shí)會(huì)進(jìn)行版本比對(duì),以確保數(shù)據(jù)的一致性。

  • 樂(lè)觀(guān)鎖的原理主要基于版本號(hào)或時(shí)間戳來(lái)實(shí)現(xiàn)。在每次更新數(shù)據(jù)時(shí),先獲取當(dāng)前數(shù)據(jù)的版本號(hào)或時(shí)間戳,然后在更新時(shí)比對(duì)版本號(hào)或時(shí)間戳是否一致,若一致則更新成功,否則表示數(shù)據(jù)已被其他線(xiàn)程修改,更新失敗。

  • 在Java中,常見(jiàn)的樂(lè)觀(guān)鎖實(shí)現(xiàn)是使用Atomic類(lèi),例如AtomicInteger、AtomicLong等。這些類(lèi)提供了原子操作,可以確保對(duì)共享資源的更新操作是原子性的,從而避免了鎖的開(kāi)銷(xiāo)和線(xiàn)程等待,另外,CAS(Compare-And-Swap)是實(shí)現(xiàn)樂(lè)觀(guān)鎖的核心算法,它通過(guò)比較內(nèi)存中的值是否和預(yù)期的值相等來(lái)判斷是否存在沖突。如果存在,則返回失??;如果不存在,則執(zhí)行更新操作。Java中提供了AtomicInteger、AtomicLong、AtomicReference等原子類(lèi)來(lái)支持CAS操作。

二、樂(lè)觀(guān)鎖與悲觀(guān)鎖分別適用于什么場(chǎng)景

2.1、悲觀(guān)鎖適用場(chǎng)景

  • 高并發(fā)且數(shù)據(jù)競(jìng)爭(zhēng)激烈的場(chǎng)景:當(dāng)多個(gè)事務(wù)需要同時(shí)訪(fǎng)問(wèn)和修改同一份數(shù)據(jù)時(shí),使用悲觀(guān)鎖可以確保數(shù)據(jù)在任一時(shí)刻只被一個(gè)事務(wù)訪(fǎng)問(wèn)和修改,從而避免數(shù)據(jù)的不一致性和臟讀。
  • 數(shù)據(jù)一致性要求極高的場(chǎng)景:在金融、醫(yī)療等行業(yè)中,對(duì)數(shù)據(jù)的一致性要求非常高,不允許出現(xiàn)任何的數(shù)據(jù)不一致或臟讀現(xiàn)象。在這些場(chǎng)景中,使用悲觀(guān)鎖可以確保數(shù)據(jù)在任一時(shí)刻只被一個(gè)事務(wù)訪(fǎng)問(wèn)和修改,從而滿(mǎn)足數(shù)據(jù)一致性的要求。
  • 寫(xiě)操作頻繁的場(chǎng)景:如果系統(tǒng)中寫(xiě)操作(如更新、刪除等)遠(yuǎn)多于讀操作(如查詢(xún)),那么使用悲觀(guān)鎖可以更有效地保護(hù)數(shù)據(jù),避免在寫(xiě)操作時(shí)被其他事務(wù)干擾。
  • 事務(wù)執(zhí)行時(shí)間較長(zhǎng)的場(chǎng)景:當(dāng)事務(wù)的執(zhí)行時(shí)間較長(zhǎng)時(shí),使用悲觀(guān)鎖可以確保在該事務(wù)執(zhí)行期間,數(shù)據(jù)不會(huì)被其他事務(wù)修改,從而避免數(shù)據(jù)的不一致性和臟讀。

2.2、樂(lè)觀(guān)鎖適用場(chǎng)景

  • 寫(xiě)操作較少:在這種場(chǎng)景下,多個(gè)事務(wù)或線(xiàn)程大部分時(shí)間都在讀取數(shù)據(jù),而寫(xiě)操作的頻率相對(duì)較低。樂(lè)觀(guān)鎖能夠減少鎖的持有時(shí)間,允許多個(gè)事務(wù)或線(xiàn)程同時(shí)讀取數(shù)據(jù),而不會(huì)相互阻塞。
  • 數(shù)據(jù)沖突較少:如果數(shù)據(jù)更新操作之間的沖突較少,即多個(gè)事務(wù)或線(xiàn)程同時(shí)更新同一份數(shù)據(jù)的概率較低,那么樂(lè)觀(guān)鎖能夠發(fā)揮很好的性能。因?yàn)榧词古紶柍霈F(xiàn)沖突,也只是在更新數(shù)據(jù)時(shí)才會(huì)被檢測(cè)到,而不需要在整個(gè)數(shù)據(jù)處理過(guò)程中都鎖定資源。
  • 重試成本較低:樂(lè)觀(guān)鎖在檢測(cè)到?jīng)_突時(shí)會(huì)回滾事務(wù)或提示沖突,需要客戶(hù)端重新嘗試更新操作。因此,如果重試的成本較低(例如,重試不會(huì)導(dǎo)致大量計(jì)算或I/O操作),那么使用樂(lè)觀(guān)鎖是合適的。
  • 系統(tǒng)能夠容忍一定程度的失敗:由于樂(lè)觀(guān)鎖在更新數(shù)據(jù)時(shí)可能會(huì)因?yàn)榘姹緵_突而失敗,因此系統(tǒng)需要能夠處理這種失敗情況。如果系統(tǒng)能夠容忍一定程度的失敗(例如,通過(guò)重試或其他補(bǔ)償機(jī)制來(lái)恢復(fù)),那么使用樂(lè)觀(guān)鎖是可行的。

三、樂(lè)觀(guān)鎖與悲觀(guān)鎖各自?xún)?yōu)缺點(diǎn)

3.1、悲觀(guān)鎖

優(yōu)點(diǎn)

  • 數(shù)據(jù)一致性高:悲觀(guān)鎖認(rèn)為沖突一定會(huì)發(fā)生,因此在數(shù)據(jù)處理前會(huì)先加鎖,這樣可以確保數(shù)據(jù)在任一時(shí)刻只被一個(gè)事務(wù)訪(fǎng)問(wèn)和修改,從而避免數(shù)據(jù)的不一致性和臟讀。
  • 簡(jiǎn)單易用:悲觀(guān)鎖的實(shí)現(xiàn)相對(duì)簡(jiǎn)單,只需要在操作數(shù)據(jù)前獲取鎖即可。

缺點(diǎn)

  • 性能開(kāi)銷(xiāo)大:悲觀(guān)鎖在操作數(shù)據(jù)前需要獲取鎖,如果有大量的并發(fā)操作,可能會(huì)導(dǎo)致性能問(wèn)題,因?yàn)槠渌聞?wù)需要等待鎖釋放。
  • 容易造成死鎖:如果多個(gè)事務(wù)相互等待對(duì)方釋放鎖,可能會(huì)導(dǎo)致死鎖的發(fā)生,影響系統(tǒng)的穩(wěn)定性和可用性。
  • 可能導(dǎo)致資源浪費(fèi):如果獲取鎖后長(zhǎng)時(shí)間不釋放,可能會(huì)導(dǎo)致其他事務(wù)無(wú)法操作數(shù)據(jù),從而造成資源浪費(fèi)。

3.2、樂(lè)觀(guān)鎖

優(yōu)點(diǎn)

  • 高并發(fā)高吞吐:樂(lè)觀(guān)鎖不會(huì)阻塞其他事務(wù)的讀取操作,只在提交時(shí)檢查數(shù)據(jù)是否被修改,因此可以提供更好的并發(fā)性能。
  • 無(wú)鎖操作:樂(lè)觀(guān)鎖不需要顯式地獲取和釋放鎖,減少了鎖競(jìng)爭(zhēng)和上下文切換的開(kāi)銷(xiāo)。
  • 無(wú)死鎖風(fēng)險(xiǎn):由于樂(lè)觀(guān)鎖不會(huì)阻塞其他事務(wù)的訪(fǎng)問(wèn),因此不會(huì)出現(xiàn)死鎖的情況。

缺點(diǎn)

  • 沖突處理復(fù)雜:由于樂(lè)觀(guān)鎖不會(huì)阻塞其他事務(wù),因此在提交時(shí)需要檢查數(shù)據(jù)是否被其他事務(wù)修改,如果發(fā)現(xiàn)沖突,需要回滾事務(wù)或重新嘗試操作,這增加了沖突處理的復(fù)雜性。
  • 數(shù)據(jù)一致性風(fēng)險(xiǎn):樂(lè)觀(guān)鎖假設(shè)并發(fā)沖突較少,因此可能存在數(shù)據(jù)一致性的風(fēng)險(xiǎn)。如果多個(gè)事務(wù)同時(shí)對(duì)同一數(shù)據(jù)進(jìn)行修改,可能會(huì)導(dǎo)致數(shù)據(jù)不一致的情況。
  • 需要額外字段:為了實(shí)現(xiàn)樂(lè)觀(guān)鎖,通常需要在數(shù)據(jù)表中添加額外的版本號(hào)或時(shí)間戳字段,這增加了存儲(chǔ)空間的需求。
  • 處理不當(dāng)造成死循環(huán)風(fēng)險(xiǎn):在大多數(shù)業(yè)務(wù)中樂(lè)觀(guān)鎖更新失敗都會(huì)進(jìn)行自旋,如果沒(méi)有控制好自旋退出邏輯可能會(huì)造成遞歸死循環(huán)問(wèn)題。

四、樂(lè)觀(guān)鎖與悲觀(guān)鎖使用示例

這里舉例會(huì)以操作數(shù)據(jù)庫(kù)實(shí)現(xiàn)樂(lè)觀(guān)鎖與悲觀(guān)鎖示例,在實(shí)際開(kāi)發(fā)中一般在操作數(shù)據(jù)庫(kù)時(shí)經(jīng)常會(huì)使用到樂(lè)觀(guān)鎖與悲觀(guān)鎖的實(shí)現(xiàn)思路來(lái)確保數(shù)據(jù)一致性問(wèn)題,這里會(huì)以一個(gè)更新用戶(hù)錢(qián)包舉例。

用戶(hù)錢(qián)包表

CREATE TABLE `customer_wallet` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `customer_id` bigint(20) DEFAULT NULL COMMENT '客戶(hù)ID',
  `balance_amount` bigint(20) DEFAULT NULL COMMENT '剩余金額',
  `version` bigint(20) DEFAULT '1' COMMENT '版本鎖',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_customer_id` (`customer_id`)
) COMMENT='客戶(hù)錢(qián)包信息';

4.1、悲觀(guān)鎖實(shí)現(xiàn)更新用戶(hù)錢(qián)包示例

這里提供一個(gè)使用悲觀(guān)鎖扣減錢(qián)包余額的示例,在第一次查詢(xún)時(shí)添加for update操作,那么其它線(xiàn)程進(jìn)入該方法時(shí)則會(huì)阻塞等待上一個(gè)方法事務(wù)提交才能繼續(xù)執(zhí)行,在這整個(gè)方法中都是線(xiàn)程安全的,這就是常見(jiàn)的結(jié)合數(shù)據(jù)庫(kù)實(shí)現(xiàn)悲觀(guān)鎖更新數(shù)據(jù)的示例,所有線(xiàn)程都必須排隊(duì)串行更新數(shù)據(jù)。

    @Transactional(rollbackFor = Exception.class)
    public boolean pessimisticLockSubAmount(Long customerId, Long happenAmount) {
        // 1、查詢(xún)用戶(hù)錢(qián)包 - 并且添加for update 鎖,這里customer_id字段添加了索引最終鎖定的還是索引定義行的ID,和直接使用ID區(qū)別不大
        // 這段代碼相當(dāng)于 select * from customer_wallet where customer_id = ? for update
        CustomerWallet customerWallet = lambdaQuery()
                .eq(CustomerWallet::getCustomerId, customerId)
                .last("for update")
                .one();
        if(customerWallet == null){
            throw new RuntimeException("用戶(hù)錢(qián)包不存在");
        }
        // 2、校驗(yàn)用戶(hù)余額是否足夠
        Long balanceAmount = customerWallet.getBalanceAmount() - happenAmount;
        if(balanceAmount < 0){
            throw new RuntimeException("用戶(hù)余額不足");
        }
        // 3、更新錢(qián)包余額 update customer_wallet set balance_amount = ? where id = ?
        boolean update = lambdaUpdate()
                .eq(CustomerWallet::getId, customerWallet.getId())
                .set(CustomerWallet::getBalanceAmount, balanceAmount)
                .update();
        if(!update){
            throw new RuntimeException("錢(qián)包更新失敗");
        }
        // 4、添加余額明細(xì)
        addWalletDetail(customerWallet.getId(),2,happenAmount,balanceAmount);
        return update;
    }

4.2、樂(lè)觀(guān)鎖實(shí)現(xiàn)更新用戶(hù)錢(qián)包示例1

使用樂(lè)觀(guān)鎖更新數(shù)據(jù)時(shí),執(zhí)行更新語(yǔ)句時(shí)通過(guò)判斷version是否有變動(dòng)來(lái)確認(rèn)數(shù)據(jù)是否有過(guò)變更,如果數(shù)據(jù)庫(kù)當(dāng)前version值和查詢(xún)出來(lái)的version值相等則代表數(shù)據(jù)沒(méi)有變更可以更新,因?yàn)閿?shù)據(jù)庫(kù)指定ID更新某一行數(shù)據(jù)時(shí)是在數(shù)據(jù)庫(kù)層面會(huì)添加行鎖,確保只能有一個(gè)事務(wù)進(jìn)行這行數(shù)據(jù)更新,這樣就保證了數(shù)據(jù)的一致性。

    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public boolean subAmount(Long customerId, Long happenAmount) {
        // 1、獲取用戶(hù)錢(qián)包
        CustomerWallet customerWallet = lambdaQuery().eq(CustomerWallet::getCustomerId, customerId).one();
        if (customerWallet == null) {
            throw new RuntimeException("用戶(hù)錢(qián)包不存在");
        }
        // 2、判斷用戶(hù)余額是否足夠
        Long balanceAmount = customerWallet.getBalanceAmount() - happenAmount;
        if(balanceAmount < 0){
            throw new RuntimeException("用戶(hù)余額不足");
        }
        // 3、進(jìn)行樂(lè)觀(guān)鎖更新 
        // 這段代碼相當(dāng)于 update customer_wallet set balance_amount = ?, version = ? where id = ? and version = ?
        boolean update = lambdaUpdate()
                .eq(CustomerWallet::getId, customerWallet.getId())
                .eq(CustomerWallet::getVersion, customerWallet.getVersion())
                .set(CustomerWallet::getBalanceAmount, balanceAmount)
                .set(CustomerWallet::getVersion, customerWallet.getVersion() + 1)
                .update();
        if(!update){
            log.info("樂(lè)觀(guān)鎖更新失敗,開(kāi)始自旋");
            return subAmount(customerId,happenAmount);
        }
        // 4、添加余額明細(xì)
        addWalletDetail(customerWallet.getId(),2,happenAmount,balanceAmount);
        return update;
    }

PS:注意,在使用樂(lè)觀(guān)鎖更新數(shù)據(jù)時(shí),事務(wù)隔離級(jí)別必須設(shè)置為READ_COMMITTED,在最后注意事項(xiàng)中會(huì)進(jìn)行分析。

4.3、樂(lè)觀(guān)鎖實(shí)現(xiàn)更新用戶(hù)錢(qián)包示例2

樂(lè)觀(guān)鎖實(shí)現(xiàn)更新用戶(hù)錢(qián)包示例1中使用了一個(gè)version字段來(lái)作為樂(lè)觀(guān)鎖更新的標(biāo)記,其實(shí)對(duì)于這種更新錢(qián)包的業(yè)務(wù)想使用樂(lè)觀(guān)鎖完全沒(méi)有必要單獨(dú)加一個(gè)version字段,可以直接使用余額字段作為這個(gè)樂(lè)觀(guān)鎖的比較字段,因?yàn)槲覀冞@里擬定的是用戶(hù)余額需要足夠才能支付,那么在更新錢(qián)包時(shí)判斷一下當(dāng)前余額是否大于等于所需金額,如果滿(mǎn)足調(diào)整則

    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public boolean subAmountV2(Long customerId, Long happenAmount) {
        // 1、獲取用戶(hù)錢(qián)包
        CustomerWallet customerWallet = lambdaQuery().eq(CustomerWallet::getCustomerId, customerId).one();
        if (customerWallet == null) {
            throw new RuntimeException("用戶(hù)錢(qián)包不存在");
        }

        // 2、直接使用余額作為樂(lè)觀(guān)鎖更新依據(jù)進(jìn)行樂(lè)觀(guān)鎖更新
        // 這段代碼相當(dāng)于 update customer_wallet set balance_amount = balance_amount + ? where id = ? and balance_amount >= ?
        boolean update = lambdaUpdate()
                .eq(CustomerWallet::getId, customerWallet.getId())
                .ge(CustomerWallet::getBalanceAmount, happenAmount)
                .setSql("balance_amount = balance_amount - "+happenAmount)
                .update();
        if(!update){
            log.info("樂(lè)觀(guān)鎖更新失敗,用戶(hù)余額不足");
            throw new RuntimeException("用戶(hù)余額不足");
        }
        // 3、添加余額明細(xì) 注意這里需要從新查詢(xún)一次數(shù)據(jù)
        CustomerWallet customerWalletNew = lambdaQuery().eq(CustomerWallet::getCustomerId, customerId).one();
        addWalletDetail(customerWallet.getId(),2,happenAmount,customerWalletNew.getBalanceAmount());
        return update;
    }

PS:注意,在使用樂(lè)觀(guān)鎖更新數(shù)據(jù)時(shí),事務(wù)隔離級(jí)別必須設(shè)置為READ_COMMITTED,在最后注意事項(xiàng)中會(huì)進(jìn)行分析。

五、注意事項(xiàng)

在使用樂(lè)觀(guān)鎖更新數(shù)據(jù)時(shí)要注意一個(gè)事務(wù)隔離級(jí)別的問(wèn)題,我這里使用的是READ COMMITTED(讀已提交),如果使用的是REPEATABLE READ(可重復(fù)讀)會(huì)存在兩個(gè)問(wèn)題,分別對(duì)應(yīng)4.2 和 4.3中的示例。

  • 在4.2示例中通過(guò)version值來(lái)實(shí)現(xiàn)樂(lè)觀(guān)鎖更新,如果這里使用的事務(wù)隔離級(jí)別為REPEATABLE READ(可重復(fù)讀),那么在樂(lè)觀(guān)鎖沖突更新失敗自旋時(shí)因?yàn)镸VCC機(jī)制查詢(xún)到的數(shù)據(jù)會(huì)是一個(gè)副本值,就算別的事務(wù)更新成功了讀取到的version都是歷史值,這樣會(huì)導(dǎo)致死循環(huán)遞歸最后棧溢出。
  • 在4.3示例中采用余額這樣的字段進(jìn)行判斷更新,因?yàn)镸ySQL的更新數(shù)據(jù)采用的是當(dāng)前讀,這里其實(shí)無(wú)論使用REPEATABLE READ(可重復(fù)讀)還是READ COMMITTED(讀已提交)事務(wù)隔離級(jí)別都不會(huì)存在死循環(huán)問(wèn)題,但是如果鎖沖突頻繁在使用REPEATABLE READ(可重復(fù)讀)事務(wù)隔離級(jí)別時(shí)可能會(huì)出現(xiàn)鎖持有時(shí)間過(guò)長(zhǎng)問(wèn)題,因?yàn)樵?code>REPEATABLE READ事務(wù)隔離級(jí)別下,在一個(gè)事務(wù)中執(zhí)行一個(gè)更新語(yǔ)句,就算where id=1 and balance_amount >= 100 這樣的條件不成立,也會(huì)將這一行數(shù)據(jù)進(jìn)行鎖定,需要等待事務(wù)提交或回滾才會(huì)釋放鎖,也就是說(shuō)在自旋時(shí)其它事務(wù)想要更新數(shù)據(jù)等待時(shí)間會(huì)變長(zhǎng)影響系統(tǒng)吞吐量,而使用READ COMMITTED事務(wù)隔離級(jí)別當(dāng)where中條件不成立更新失敗時(shí)不會(huì)持有鎖,也就是說(shuō)事務(wù)A在更新失敗自旋時(shí)事務(wù)B也是可以進(jìn)行更新的,而不需要等待事務(wù)A自旋更新成功后才能進(jìn)行更新,這樣能提高系統(tǒng)吞吐量。

到此這篇關(guān)于java中樂(lè)觀(guān)鎖與悲觀(guān)鎖區(qū)別及使用場(chǎng)景分析的文章就介紹到這了,更多相關(guān)java 樂(lè)觀(guān)鎖與悲觀(guān)鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • java匿名內(nèi)部類(lèi)實(shí)例簡(jiǎn)析

    java匿名內(nèi)部類(lèi)實(shí)例簡(jiǎn)析

    匿名類(lèi)是不能有名稱(chēng)的類(lèi),所以沒(méi)辦法引用它們,必須在創(chuàng)建時(shí),作為new語(yǔ)句的一部分來(lái)聲明它們,需要了解更多的可以參考本文
    2012-11-11
  • SpringBoot多模塊項(xiàng)目創(chuàng)建和初始化問(wèn)題

    SpringBoot多模塊項(xiàng)目創(chuàng)建和初始化問(wèn)題

    本文詳細(xì)介紹了使用SpringBoot框架創(chuàng)建一個(gè)包含數(shù)據(jù)庫(kù)操作、MyBatis-Plus、Knife4j、HTTP請(qǐng)求響應(yīng)等的Java Web項(xiàng)目的步驟和配置方法,內(nèi)容涵蓋創(chuàng)建項(xiàng)目結(jié)構(gòu)、配置數(shù)據(jù)庫(kù)連接、添加依賴(lài)、編寫(xiě)接口、處理異常、序列化和反序列化、配置接口文檔等等內(nèi)容
    2026-05-05
  • 如何在Java中使用支付寶SDK來(lái)獲取用戶(hù)的OpenID

    如何在Java中使用支付寶SDK來(lái)獲取用戶(hù)的OpenID

    在支付寶開(kāi)放平臺(tái)中,獲取用戶(hù)的OpenID通常是在用戶(hù)授權(quán)后通過(guò)支付寶的OAuth 2.0授權(quán)流程實(shí)現(xiàn)的,以下是一個(gè)基本的步驟說(shuō)明,以及如何在Java中使用支付寶SDK來(lái)獲取用戶(hù)的OpenID
    2024-08-08
  • SpringBoot中項(xiàng)目結(jié)構(gòu)的項(xiàng)目實(shí)踐

    SpringBoot中項(xiàng)目結(jié)構(gòu)的項(xiàng)目實(shí)踐

    SpringBoot項(xiàng)目結(jié)構(gòu)遵循Maven或Gradle的標(biāo)準(zhǔn)目錄結(jié)構(gòu),融入了SpringBoot的特定約定,本文就來(lái)介紹一下SpringBoot中項(xiàng)目結(jié)構(gòu)的項(xiàng)目,感興趣的可以了解一下
    2025-03-03
  • 如何使用Docker部署Java項(xiàng)目

    如何使用Docker部署Java項(xiàng)目

    在接觸了docker后,干什么都想用docker來(lái)弄,這篇文章主要給大家介紹了關(guān)于如何使用Docker部署Java項(xiàng)目的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 將JavaDoc注釋生成API文檔的操作

    將JavaDoc注釋生成API文檔的操作

    這篇文章主要介紹了將JavaDoc注釋生成API文檔的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java組件FileUpload上傳文件實(shí)現(xiàn)代碼

    Java組件FileUpload上傳文件實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了Java組件FileUpload上傳文件實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • springboot配合Thymeleaf完美實(shí)現(xiàn)遍歷功能

    springboot配合Thymeleaf完美實(shí)現(xiàn)遍歷功能

    Thymeleaf顯然是一個(gè)開(kāi)發(fā)頁(yè)面的技術(shù),現(xiàn)在各種前端技術(shù)層出不窮,比如現(xiàn)在主流的Vue、React、AngularJS等。這篇文章主要介紹了springboot配合Thymeleaf完美實(shí)現(xiàn)遍歷,需要的朋友可以參考下
    2021-09-09
  • 詳解JAVA中獲取文件MD5值的四種方法

    詳解JAVA中獲取文件MD5值的四種方法

    這篇文章主要介紹了JAVA中獲取文件MD5值的四種方法,獲取文件MD5值主要分為三個(gè)步驟,第一步獲取文件的byte信息,第二步通過(guò)MessageDigest類(lèi)進(jìn)行MD5加密,第三步轉(zhuǎn)換成16進(jìn)制的MD5碼值,需要的朋友可以參考下
    2022-08-08
  • spring cloud-zuul的Filter使用詳解

    spring cloud-zuul的Filter使用詳解

    這篇文章主要介紹了spring cloud-zuul的Filter使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01

最新評(píng)論

广河县| 喜德县| 高要市| 衡阳市| 开江县| 海安县| 盐津县| 无棣县| 通海县| 凌源市| 光山县| 赤水市| 葵青区| 青神县| 罗城| 东安县| 交口县| 大竹县| 柏乡县| 奎屯市| 阳朔县| 武山县| 五家渠市| 施秉县| 额尔古纳市| 根河市| 无锡市| 古丈县| 双鸭山市| 宜城市| 壤塘县| 胶州市| 甘德县| 洪雅县| 方山县| 启东市| 扶风县| 罗江县| 扶沟县| 茂名市| 齐河县|