亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot+Redis?BitMap實現(xiàn)簽到與統(tǒng)計的項目實踐

 更新時間:2023年09月16日 11:51:45   作者:ZNineSun  
最近項目里需要集成簽到和統(tǒng)計功能,連續(xù)簽到后會給用戶發(fā)放一些優(yōu)惠券和獎品,以此來吸引用戶持續(xù)在該品臺進(jìn)行活躍,本文就詳細(xì)的介紹一下如何實現(xiàn),感興趣的可以了解一下

最近項目里需要集成簽到和統(tǒng)計功能,連續(xù)簽到后會給用戶發(fā)放一些優(yōu)惠券和獎品,以此來吸引用戶持續(xù)在該品臺進(jìn)行活躍。下面我們一些來聊一聊目前主流的實現(xiàn)方案。

因為簽到和統(tǒng)計的功能涉及的數(shù)據(jù)量比較大,所以在如此大的數(shù)據(jù)下利用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫進(jìn)行計算和統(tǒng)計是非常耗費(fèi)性能的,所以目前市面上主要依賴于高性能緩存RedisBitMap 功能來實現(xiàn)。

先看看利用Mysql實現(xiàn)以上功能會有哪些缺陷和短板。

1.使用Mysql實現(xiàn)簽到功能

首先我們需要一個簽到表

DROP TABLE IF EXISTS `tb_sign`;
CREATE TABLE `tb_sign` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `user_id` int(11) NOT NULL COMMENT '用戶Id',
  `year` year(4) NOT NULL COMMENT '簽到的年',
  `month` tinyint(2) NOT NULL COMMENT '簽到的月',
  `date` date NOT NULL COMMENT '簽到日期',
  `is_backup` tinyint(1) NOT NULL COMMENT '是否補(bǔ)簽',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

用戶一次簽到,就是一條記錄,假如有1000萬用戶,平均每人每年簽到次數(shù)為10次,則這張表一年的數(shù)據(jù)量為 1億條

每簽到一次需要使用(8 + 8 + 1 + 1 + 3 + 1)共22 字節(jié)的內(nèi)存,一個月則最多需要600多字節(jié)

這樣的壞處,占用內(nèi)存太大了,極大的消耗內(nèi)存空間!

我們可以根據(jù) Redis中 提供的 BitMap 位圖功能來實現(xiàn),每次簽到與未簽到用0 或1 來標(biāo)識 ,一次存31個數(shù)字,只用了2字節(jié) 這樣我們就用極小的空間實現(xiàn)了簽到功能

2.Redis BitMap

2.1 BitMap 的操作指令

  • SETBIT :向指定位置(offset)存入一個0或1
  • GETBIT :獲取指定位置(offset)的bit值
  • BITCOUNT :統(tǒng)計BitMap中值為1的bit位的數(shù)量
  • BITFIELD :操作(查詢、修改、自增)BitMap中bit數(shù)組中的指定位置(offset)的值
  • BITFIELD_RO :獲取BitMap中bit數(shù)組,并以十進(jìn)制形式返回
  • BITOP :將多個BitMap的結(jié)果做位運(yùn)算(與 、或、異或)
  • BITPOS :查找bit數(shù)組中指定范圍內(nèi)第一個0或1出現(xiàn)的位置

2.2 使用 BitMap 完成功能實現(xiàn)

利用SETBIT新增key 進(jìn)行存儲

SETBIT bm1 0 1

看不懂上面的指令?沒關(guān)系,我們可以通過help指令查看提示

help SETBIT

在這里插入圖片描述

通過這個指令可以看出Redis SETBIT 命令用于對 key 所儲存的字符串值,設(shè)置或清除指定偏移量上的位(bit)。位的設(shè)置或清除取決于 value,可以是 0 或者是 1 。

當(dāng) key 不存在時,自動生成一個新的字符串值。字符串會進(jìn)行伸展以確保它可以將 value 保存在指定的偏移量上。當(dāng)字符串值進(jìn)行伸展時,空白位置以 0 填充。 offset 參數(shù)必須大于或等于 0 ,小于 2^32 (bit 被限制在 512 MB 之內(nèi))。

提示:如果 offset 偏移量的值較大,計算機(jī)進(jìn)行內(nèi)存分配時可能會造成 Redis 服務(wù)器被阻塞。

在這里插入圖片描述

這樣的話我們就可以通過偏移量設(shè)置每一天的簽到情況:

  • 偏移量:表示天
  • val值:表示是否簽到
    • 已簽到設(shè)置為1
    • 未簽到設(shè)置0

下面我們只需要通過GETBIT命令就可以查看每一天的簽到情況

GETBIT bm1 2

表示查看bm1用戶第二天的簽到情況

在這里插入圖片描述

同樣,我們可以通過BITCOUNT可以統(tǒng)計出該用戶簽到了多少天

BITCOUNT bm1 

在這里插入圖片描述

BITFIELD

通過BITFIELD以原子方式操作(查詢、修改、自增)BitMap中bit數(shù)組中的指定位置(offset)的值

BITFIELD復(fù)雜度是O(n),其中n是訪問的計數(shù)器數(shù)。

語法:

BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

參數(shù)說明:

  • key :需要操作的鍵名。
  • GET type offset :獲取指定位數(shù)的值
  • type表示數(shù)據(jù)類型,可以是無符號整數(shù)(u)或有符號整數(shù)(i)
  • offset表示偏移量,如果位不存在,返回0。
  • SET type offset value :設(shè)置指定位數(shù)的值,type和offset同上,value表示需要設(shè)置的值,因為此命令只支持設(shè)置8位或更少的位,所以value不能超過8個二進(jìn)制位。
  • INCRBY type offset increment :將指定位的值增加指定的增量,type和offset同上,increment表示需要增加的值,也必須不超過8個二進(jìn)制位。
  • OVERFLOW :做溢出的處理,默認(rèn)是WRAP(循環(huán)),其他兩個選項是SAT(飽和,超出范圍的值都設(shè)置成最大或最小值)和FAIL(不允許溢出,會返回一個錯誤)。

使用方法

  • 獲取一個整數(shù)的二進(jìn)制位

舉個例子,我們有一個整數(shù)值10,它的二進(jìn)制位是00001010,我們想獲取它的第3位到第5位的值,即001。那么可以這樣使用:

127.0.0.1:6379> BITFIELD myint GET u3 3 u1 6
1) (integer) 1
2) (integer) 0

u3:表示3位無符號整數(shù)

指定myint鍵值,通過GET命令獲取它的第3位到第5位,結(jié)果返回一個二進(jìn)制數(shù)001,也就是十進(jìn)制的1。第二個返回值是0,表示其他未指定的位都是0。

  • 設(shè)置一個整數(shù)的二進(jìn)制位
    現(xiàn)在我們想把剛才的整數(shù)值10的第3位到第5位修改為101,即值為5??梢赃@樣設(shè)置:
127.0.0.1:6379> BITFIELD myint SET u3 3 5
(integer) 10

執(zhí)行成功后,該鍵值指定的整數(shù)值變?yōu)?3(二進(jìn)制為00001101)。

所以統(tǒng)計每個用戶的簽到情況和積分,可以使用 Redis BITFIELD 命令記錄每個用戶每天的簽到情況。

每個用戶一年365天,需要使用整數(shù)類型的BITFIELD信息記錄,每個用戶需要365個二進(jìn)制位來表示簽到情況(已簽到為1,未簽到為0),再需要一個整數(shù)位去表示用戶的總積分,就可以方便地統(tǒng)計用戶簽到情況并進(jìn)行排名。

當(dāng)然該命令的功能遠(yuǎn)不止于此,在某些系統(tǒng)中,需要對某些數(shù)據(jù)做計數(shù),比如對每個IP地址訪問次數(shù)的計數(shù)??梢允褂米址愋偷挠嫈?shù)器來達(dá)到這個目的,首先在Redis中創(chuàng)建一個字符串類型的計數(shù)器(值為0),通過INCRBY命令執(zhí)行增減操作,每次給IP地址所代表的計數(shù)器加1,最后獲取到的長度即為IP地址對應(yīng)的訪問次數(shù)。如果訪問量過大,可以使用整數(shù)類型的BITFIELD存儲計數(shù)器,通過INCRBY命令執(zhí)行增減操作。這樣可以優(yōu)化性能并減少內(nèi)存占用。

BITPOS 查詢1 和 0 第一次出現(xiàn)的坐標(biāo)

在這里插入圖片描述

3.SpringBoot整合Redis實現(xiàn)簽到功能

3.1 思路分析

考慮到每月初需要重置連續(xù)簽到次數(shù),我們可以把 年和月 作為BitMap的key,然后保存到一個BitMap中,每次簽到就到對應(yīng)的位上把數(shù)字從0 變?yōu)?,只要是1,就代表是這一天簽到了,反之咋沒有簽到。

key的格式為:“USER_SIGN_KEY:” + userId + keySuffix

  • USER_SIGN_KEY:前綴
  • userId:用戶id
  • keySuffix:yyyyMM

Value則采用長度為4個字節(jié)(32位)的位圖(最大月份只有31天)。位圖的每一位代表一天的簽到,1表示已簽,0表示未簽。

例如:USER_SIGN_KEY:122101:202309:表示ID=122101的用戶在2023年9月的簽到記錄

# 用戶9月17號簽到
SETBIT USER_SIGN_KEY:122101:202309 16 1 # 偏移量是從0開始,所以要把17減1
# 檢查9月17號是否簽到
GETBIT USER_SIGN_KEY:122101:202309 16 # 偏移量是從0開始,所以要把17減1
# 統(tǒng)計9月份的簽到次數(shù)
BITCOUNT USER_SIGN_KEY:122101:202309
# 獲取9月份前30天的簽到數(shù)據(jù),u30表示取0-29位的數(shù)據(jù)
BITFIELD USER_SIGN_KEY:122101:202309 get u30 0
# 獲取9月份首次簽到的日期
BITPOS USER_SIGN_KEY:122101:202309 1 # 返回的首次簽到的偏移量,加上1即為當(dāng)月的某一天

有了上面的理論支撐,下面我開始在項目里去集成,為了節(jié)約篇幅,只展示核心代碼,項目地址在文章末尾,完整代碼可下載之后自行觀看

首先需要我們項目里集成redis,可以參考:《springBoot集成redis(jedis)詳解》

3.2 簽到功能

簽到功能實現(xiàn)方式如下:

    @GetMapping("sign")
    public Object sign() {
        //1. 獲取登錄用戶
        Long userId = 122101L;
        //2.獲取簽到使用的key
        String key = RedisKeyUtils.createSignKey(userId);
        //3. 獲取今天是本月的第幾天設(shè)置偏移量
        LocalDateTime now = LocalDateTime.now();
        int offset = now.getDayOfMonth() - 1;
        System.out.println(String.format("入?yún)ⅲ簁ey:%s,offset:%s", JSON.toJSONString(key), JSON.toJSONString(offset)));
        //5. 寫入redis setbit key offset 1
        Boolean res = jedis.setbit(key, offset, true);
        System.out.println(String.format("出參:%s", JSON.toJSONString(res)));
        return String.format("%s簽到成功,簽到結(jié)果:%s", JSON.toJSONString(now.format(DateTimeFormatter.ofPattern("yyyyMM"))), JSON.toJSONString(res));
    }

測試:

在這里插入圖片描述

在這里插入圖片描述

簽到功能我們已經(jīng)實現(xiàn),只需要將對應(yīng)該月的某天設(shè)置為1則表示簽到成功

檢查用戶是否簽到

    @GetMapping("checkSign")
    public Object checkSign(@RequestParam(value = "sigDate") String sigDate) {
        //1. 獲取登錄用戶
        Long userId = 122101L;
        //2.獲取簽到使用的key
        LocalDateTime time = TimeUtils.str2LocalDateTime(TimeUtils.PATTERN.YYYYMMDD, sigDate);
        if (Objects.isNull(time)) {
            return false;
        }
        String key = RedisKeyUtils.createSignKey(time, userId);
        //3. 獲取今天是本月的第幾天設(shè)置偏移量
        int offset = time.getDayOfMonth() - 1;
        System.out.println(String.format("入?yún)ⅲ簁ey:%s,offset:%s", JSON.toJSONString(key), JSON.toJSONString(offset)));
        Boolean res = jedis.getbit(key, offset);
        System.out.println(String.format("出參:%s", JSON.toJSONString(res)));
        return res;
    }

訪問:http://127.0.0.1:8080/checkSign?sigDate=2023-09-07

在這里插入圖片描述

下面我們繼續(xù)看看簽到統(tǒng)計功能

3.3 簽到統(tǒng)計功能

Q1:什么叫連續(xù)簽到天數(shù)?

從最后一次簽到開始向前統(tǒng)計,直到遇到第一次未簽到為止,計算總的簽到次數(shù),就是連續(xù)簽到天數(shù)。

在這里插入圖片描述

所以我們統(tǒng)計的方式很簡單:

?獲得當(dāng)前這個月的最后一次簽到數(shù)據(jù),定義一個計數(shù)器,然后不停的向前統(tǒng)計,直到獲得第一個非0的數(shù)字即可,每得到一個非0的數(shù)字計數(shù)器+1,直到遍歷完所有的數(shù)據(jù),就可以獲得當(dāng)前月的簽到總天數(shù)了?

Q2:如何得到本月到今天為止的所有簽到數(shù)據(jù)?

那我們則需要借助BITFIELD指令來進(jìn)行實現(xiàn)

BITFIELD key GET u[dayOfMonth-1] 0

假設(shè)今天是5號,那么我們就可以從當(dāng)前月的第一天開始,獲得到當(dāng)前這一天的位數(shù),是5號,那么就是5位,去拿這段時間的數(shù)據(jù),就能拿到所有的數(shù)據(jù)了,那么這5天里邊簽到了多少次呢?統(tǒng)計有多少個1即可。

Q3:如何從后向前遍歷每個Bit位?

值得我們注意的是:?bitMap返回的數(shù)據(jù)是10進(jìn)制,哪假如說返回一個數(shù)字8,那么我哪兒知道到底哪些是0,哪些是1呢??

這是一道很簡單的位運(yùn)算算法題

我們只需要讓得到的10進(jìn)制數(shù)字和1做與運(yùn)算就可以了,因為1只有遇見1 才是1,其他數(shù)字都是0 ,我們把簽到結(jié)果和1進(jìn)行與操作,每與一次,就把簽到結(jié)果向右移動一位,依次類推,我們就能完成逐個遍歷的效果了。

通過上面的幾個方法就可以很容易統(tǒng)計用戶簽到的情況。

下面看看代碼的具體實現(xiàn)

  • 獲取用戶連續(xù)簽到的天數(shù)

為了方便測試,我的當(dāng)前時間為:2023-09-07,所以我對1,3,5,6,7五天的簽到設(shè)置為1

在這里插入圖片描述

那么當(dāng)前緩存里的值則為:1010111,對應(yīng)的10進(jìn)制數(shù)為:87,最大連續(xù)1出現(xiàn)的個數(shù)為3,所以簽到的天數(shù)為3

在這里插入圖片描述

代碼如下:

    @GetMapping("signCount")
    public Object signCount() {
        //1. 獲取登錄用戶
        Long userId = 122101L;
        //2. 獲取日期
        LocalDateTime now = LocalDateTime.now();
        //3. 拼接key
        String key = RedisKeyUtils.createSignKey(now, userId);
        //4. 獲取今天是本月的第幾天
        int offset = now.getDayOfMonth();
        //5. 獲取本月截至今天為止的所有的簽到記錄,返回的是一個十進(jìn)制的數(shù)字 BITFIELD USER_SIGN_KEY1:5:202309 GET u5 0
        String type = String.format("u%d", offset);
        System.out.println(String.format("入?yún)ⅲ簁ey:%s,operationType:%s,type:%s", JSON.toJSONString(key), JSON.toJSONString(RedisHelper.OPERATION_TYPE.GET.name()), JSON.toJSONString(type)));
        List<Long> result = RedisHelper.bitField(key, RedisHelper.OPERATION_TYPE.GET, type, "0");
        //沒有任務(wù)簽到結(jié)果
        if (result == null || result.isEmpty()) {
            return 0;
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            return 0;
        }
        //6. 循環(huán)遍歷
        int count = 0;
        while (true) {
            //6.1 讓這個數(shù)字與1 做與運(yùn)算,得到數(shù)字的最后一個bit位 判斷這個數(shù)字是否為0
            if ((num & 1) == 0) {
                //如果為0,簽到結(jié)束
                break;
            } else {
                count++;
            }
            num >>>= 1;
        }
        System.out.println(String.format("緩存值:%s,簽到天數(shù):%d", JSON.toJSONString(result), count));
        return count;
    }

測試:

在這里插入圖片描述

3.4 獲取當(dāng)月首次簽到日期

利用Bitpos可以幫助我們輕松實現(xiàn)該功能

在這里插入圖片描述

  • bitpos USER_SIGN_KEY:122101:202309 1:表示1首次出現(xiàn)的位置
  • bitpos USER_SIGN_KEY:122101:202309 0:表示0首次出現(xiàn)的位置
    @GetMapping("getFirstSignDate")
    public Object getFirstSignDate(@RequestParam(value = "time") String time) {
        //1. 獲取登錄用戶
        Long userId = 122101L;
        //2. 獲取日期
        LocalDateTime dateTime = TimeUtils.str2LocalDateTime(TimeUtils.PATTERN.YYYYMMDD, time);
        //3. 拼接key
        String key = RedisKeyUtils.createSignKey(dateTime, userId);
        //4. 獲取首次出現(xiàn)的位置索引
        long pos = jedis.bitpos(key, true);
        //5. 轉(zhuǎn)換為日期
        String res = pos < 0 ? "無簽到記錄" : TimeUtils.localDateTime2String(TimeUtils.PATTERN.YYYYMMDD, dateTime.withDayOfMonth((int) (pos + 1)));
        return res;
    }

在這里插入圖片描述

3.5 獲取當(dāng)月的簽到情況

    @GetMapping("getSignInfo")
    public Object getSignInfo(@RequestParam(value = "time") String time) {
        //1. 獲取登錄用戶
        Long userId = 122101L;
        //2. 獲取日期
        LocalDateTime dateTime = TimeUtils.str2LocalDateTime(TimeUtils.PATTERN.YYYYMMDD, time);
        //當(dāng)月天數(shù)
        int monthOfDays = TimeUtils.getDayNumsOfMonth(dateTime);
        Map<String, Boolean> signMap = new HashMap<>(dateTime.getDayOfMonth());
        //3. 拼接key
        String key = RedisKeyUtils.createSignKey(dateTime, userId);
        //4. 設(shè)置位數(shù)
        String type = String.format("u%d", monthOfDays);
        System.out.println(String.format("入?yún)ⅲ簁ey:%s,operationType:%s,type:%s", JSON.toJSONString(key), JSON.toJSONString(RedisHelper.OPERATION_TYPE.GET.name()), JSON.toJSONString(type)));
        List<Long> list = RedisHelper.bitField(key, RedisHelper.OPERATION_TYPE.GET, type, "0");
        if (!CollectionUtils.isEmpty(list)) {
            Long num = list.get(0);
            int i = monthOfDays;
            while (i > 0) {
                String d = TimeUtils.localDateTime2String(TimeUtils.PATTERN.YYYYMMDD, dateTime.withDayOfMonth(i--));
                if ((num & 1) == 0) {
                    signMap.put(d, false);
                } else {
                    signMap.put(d, true);
                }
                num >>>= 1;
            }
        }
        //按照日期排序
        TreeMap sortedMap = new TreeMap(signMap);
        System.out.println("出參:" + JSON.toJSONString(sortedMap));
        return sortedMap;
    }

在這里插入圖片描述

至此簽到所需要的功能我們就全部實現(xiàn)了

本文的核心在于bitMap的使用,但是任何技術(shù)都需要有具體的落地,所以借著簽到的場景帶著大家具體使用一下。

當(dāng)然bitmap的落地場景遠(yuǎn)不止我上文中介紹的簽到統(tǒng)計等業(yè)務(wù)層面的方案,針對緩存穿透的場景,bitMap也是一個極佳的選擇。

4.利用BitMap解決緩存穿透

描述: 緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),而用戶不斷發(fā)起請求,如發(fā)起為id為“-1”的數(shù)據(jù)或id為特別大不存在的數(shù)據(jù)。這時的用戶很可能是攻擊者,攻擊會導(dǎo)致數(shù)據(jù)庫壓力過大。

這種可以認(rèn)為是系統(tǒng)漏洞,一旦發(fā)生這種情況一般都來自于惡意請求。

常見解決方案:

  • 接口層增加校驗,如用戶鑒權(quán)校驗,id做基礎(chǔ)校驗,id<=0的直接攔截;
  • 從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫中也沒有取到,這時也可以將key-value對寫為key-null,緩存有效時間可以設(shè)置短點,如30秒(設(shè)置太長會導(dǎo)致正常情況也沒法使用)。這樣可以防止攻擊用戶反復(fù)用同一個id暴力攻擊

第一種解決方案:遇到的問題是如果用戶訪問的是id不存在的數(shù)據(jù),則此時就無法生效,如id遠(yuǎn)大于某個值,雖然不小于0,但是也無法進(jìn)行過濾。

第二種解決方案:遇到的問題是:如果是不同的id那就可以防止下次過來直擊數(shù)據(jù)

所以我們?nèi)绾谓鉀Q呢?

我們可以將數(shù)據(jù)庫的數(shù)據(jù),所對應(yīng)的id寫入到一個list集合中,當(dāng)用戶過來訪問的時候,我們直接去判斷l(xiāng)ist中是否包含當(dāng)前的要查詢的數(shù)據(jù),如果說用戶要查詢的id數(shù)據(jù)并不在list集合中,則直接返回,如果list中包含對應(yīng)查詢的id數(shù)據(jù),則說明不是一次緩存穿透數(shù)據(jù),則直接放行。

在這里插入圖片描述

現(xiàn)在的問題是這個主鍵其實并沒有那么短,有的可能是通過各種拼接生成的Id,是很長的一個主鍵,所以如果采用以上方案,這個list也會很大,所以我們可以 使用bitmap來減少list的存儲空間

我們可以把list數(shù)據(jù)抽象成一個非常大的bitmap,我們不再使用list,而是將db中的id數(shù)據(jù)利用哈希思想,比如:

id 求余bitmap長度 : index=id%bitmap.size

算出當(dāng)前這個id對應(yīng)應(yīng)該落在bitmap的哪個索引上,然后將這個值從0變成1,然后當(dāng)用戶來查詢數(shù)據(jù)時,此時已經(jīng)沒有了list,讓用戶用他查詢的id去用相同的哈希算法, 算出來當(dāng)前這個id應(yīng)當(dāng)落在bitmap的哪一位,然后判斷這一位是0,還是1,如果是0則表明這一位上的數(shù)據(jù)一定不存在,采用這種方式來處理,需要重點考慮一個事情,就是誤差率, 所謂的誤差率就是指當(dāng)發(fā)生哈希沖突的時候,產(chǎn)生的誤差 。

在這里插入圖片描述

項目地址:https://gitee.com/ninesuntec/redisBitMapSign

到此這篇關(guān)于SpringBoot+Redis BitMap實現(xiàn)簽到與統(tǒng)計的項目實踐的文章就介紹到這了,更多相關(guān)SpringBoot+Redis BitMap簽到與統(tǒng)計內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot如何配置多kafka

    springboot如何配置多kafka

    這篇文章主要介紹了springboot如何配置多kafka問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • MyBatis批量插入幾千條數(shù)據(jù)為何慎用foreach

    MyBatis批量插入幾千條數(shù)據(jù)為何慎用foreach

    這篇文章主要介紹了MyBatis批量插入幾千條數(shù)據(jù)為何慎用foreach問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 如何使用try-with-resource機(jī)制關(guān)閉連接

    如何使用try-with-resource機(jī)制關(guān)閉連接

    這篇文章主要介紹了使用try-with-resource機(jī)制關(guān)閉連接的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中實現(xiàn)定時任務(wù)的兩種方法舉例詳解

    Java中實現(xiàn)定時任務(wù)的兩種方法舉例詳解

    這篇文章主要給大家介紹了關(guān)于Java中實現(xiàn)定時任務(wù)的兩種方法,文中總結(jié)了各種實現(xiàn)方式的優(yōu)缺點,并給出了推薦的使用場景,通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    本文主要是介紹SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁的代碼,分頁在web應(yīng)用中是經(jīng)常要做的事情,實用性比較大,有需要的朋友可以來了解一下。
    2016-10-10
  • SpringBoot DBUnit 單元測試(小結(jié))

    SpringBoot DBUnit 單元測試(小結(jié))

    這篇文章主要介紹了SpringBoot DBUnit 單元測試(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 前端如何傳遞Array、Map類型數(shù)據(jù)到Java后端

    前端如何傳遞Array、Map類型數(shù)據(jù)到Java后端

    這篇文章主要給大家介紹了關(guān)于前端如何傳遞Array、Map類型數(shù)據(jù)到Java后端的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-01-01
  • Mybatis結(jié)果生成鍵值對的實例代碼

    Mybatis結(jié)果生成鍵值對的實例代碼

    這篇文章主要介紹了Mybatis結(jié)果生成鍵值對的實例代碼,以及MyBatis返回Map鍵值對數(shù)據(jù)的實現(xiàn)方法,非常不錯,具有參考借鑒價值,需要的的朋友參考下
    2017-02-02
  • SpringBoot同一接口多個實現(xiàn)類配置的實例詳解

    SpringBoot同一接口多個實現(xiàn)類配置的實例詳解

    這篇文章主要介紹了SpringBoot同一接口多個實現(xiàn)類配置的實例詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • spring?jpa?審計功能自定義填充字段方式

    spring?jpa?審計功能自定義填充字段方式

    這篇文章主要介紹了spring?jpa審計功能自定義填充字段方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評論