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

springboot集成redis之字典緩存詳解

 更新時(shí)間:2024年07月24日 11:17:26   作者:龍泉詩(shī)  
Redis的字典緩存是支撐其高性能的一個(gè)關(guān)鍵因素,它使得Redis能夠以極快的速度處理大量的數(shù)據(jù),這篇文章主要介紹了springboot集成redis之字典緩存,需要的朋友可以參考下

什么是redis的字典緩存?

Redis的緩存是Redis內(nèi)部用于存儲(chǔ)鍵值對(duì)數(shù)據(jù)結(jié)構(gòu)的一種基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。在Redis中,所有的鍵值對(duì)都是通過(guò)字典這種數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)的。字典在Redis中扮演著核心角色,因?yàn)樗粌H用于數(shù)據(jù)庫(kù)中的鍵值對(duì)存儲(chǔ),還用于實(shí)現(xiàn)其他如哈希、集合等復(fù)雜數(shù)據(jù)結(jié)構(gòu)。
以下是關(guān)于Redis字典緩存的一些關(guān)鍵點(diǎn):

  • 數(shù)據(jù)結(jié)構(gòu):Redis的字典使用哈希表作為底層實(shí)現(xiàn),這樣可以提供快速的查找、添加和刪除操作。哈希表通常是一個(gè)數(shù)組,數(shù)組的每個(gè)元素是一個(gè)指向鍵值對(duì)結(jié)構(gòu)的指針。
  • 哈希沖突解決:當(dāng)不同的鍵通過(guò)哈希函數(shù)映射到同一個(gè)位置時(shí),Redis使用鏈表法來(lái)解決沖突。如果一個(gè)位置有多個(gè)鍵值對(duì),它們會(huì)形成一個(gè)鏈表。
  • rehash:隨著鍵值對(duì)數(shù)量的增加或減少,為了維持哈希表的性能,Redis會(huì)進(jìn)行rehash操作,即重新計(jì)算所有鍵的哈希值,并將它們重新分布到新的哈希表中。
  • 漸進(jìn)式rehash:為了避免rehash操作帶來(lái)的性能問(wèn)題,Redis使用漸進(jìn)式rehash。它將rehash操作分散到對(duì)字典的每個(gè)添加、刪除、查找和更新操作中,從而避免了一次性rehash可能導(dǎo)致的長(zhǎng)時(shí)間延遲。
  • 緩存作用:由于字典的高效訪問(wèn)特性,Redis可以快速讀寫(xiě)數(shù)據(jù),這使得Redis非常適合作為緩存系統(tǒng)使用。在字典中存儲(chǔ)的數(shù)據(jù)可以直接從內(nèi)存中訪問(wèn),大大減少了數(shù)據(jù)讀取的時(shí)間。
  • 持久化:雖然字典是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),但Redis支持將字典中的數(shù)據(jù)持久化到硬盤上,以保證在系統(tǒng)故障時(shí)數(shù)據(jù)不會(huì)丟失。
  • 類型特定字典:Redis支持多種數(shù)據(jù)類型,如字符串、列表、集合、哈希、有序集合等,每種數(shù)據(jù)類型在內(nèi)部都可能使用到字典結(jié)構(gòu)來(lái)存儲(chǔ)元數(shù)據(jù)或數(shù)據(jù)本身。

Redis的字典緩存是支撐其高性能的一個(gè)關(guān)鍵因素,它使得Redis能夠以極快的速度處理大量的數(shù)據(jù)。

項(xiàng)目目錄

代碼實(shí)踐

entity層

package com.wyl.redis.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
 * @Description 
 * @Author wuyilong
 * @Date 2024-07-03
 */
@Data
@TableName("full_city")
@Entity
@Table(name="full_city")
public class FullCity extends Model<FullCity> {
    private static final long serialVersionUID = 1L;
    /**
     * 主鍵id
     */
    @TableId(value = "id", type = IdType.AUTO)
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 名稱
     */
    @TableField("name")
    private String name;
    /**
     * 行政編碼
     */
    @TableField("code")
    private String code;
    /**
     * 全名稱
     */
    @TableField("full_name")
    private String fullName;
    /**
     * 級(jí)別,1省,2市,3區(qū),4街道
     */
    @TableField("level")
    private Integer level;
    /**
     * 創(chuàng)建時(shí)間
     */
    @TableField("create_time")
    private Date createTime;
    /**
     * 中心點(diǎn)
     */
    @TableField("center")
    private String center;
    /**
     * 是否被撤銷,0否,1是
     */
    @TableField("is_revoke")
    private Integer isRevoke;
    /**
     * 父級(jí)編碼
     */
    private String parentCode;
    @Override
    public Serializable pkVal() {
        return this.id;
    }
}

service層

package com.wyl.redis.service.impl;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.map.MapUtil;
import com.wyl.redis.bean.DictionaryBean;
import com.wyl.redis.constant.DictionaryConst;
import com.wyl.redis.entity.FullCity;
import com.wyl.redis.service.DictionaryOperate;
import com.wyl.redis.service.FullCityService;
import com.wyl.redis.vo.FullCityVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @Description
 * @Author WuYiLong
 * @Date 2024/7/3 17:36
 */
@Slf4j
@Service
public class FullCityOperate implements DictionaryOperate {
    @Autowired
    private FullCityService fullCityService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public List list(String key) {
        if(!redisTemplate.hasKey(key)) {
            List<FullCity> list = fullCityService.list();
            List<DictionaryBean> dictionaryBeans = list.stream().map(m -> {
                DictionaryBean dictionaryBean = new DictionaryBean();
                dictionaryBean.setCode(m.getCode());
                dictionaryBean.setName(m.getName());
                dictionaryBean.setLevel(m.getLevel());
                dictionaryBean.setParentCode(m.getParentCode());
                return dictionaryBean;
            }).collect(Collectors.toList());
            redisTemplate.opsForValue().set(key,dictionaryBeans);
            return dictionaryBeans;
        }
        List<DictionaryBean> list = (List<DictionaryBean>)redisTemplate.opsForValue().get(key);
        return list;
    }
    @Override
    public List<Tree<String>> tree(String key) {
        if(!redisTemplate.hasKey(key)) {
            List<FullCity> list = fullCityService.list();
            List<Tree<String>> build = TreeUtil.build(list, "0", (t1, t2) -> {
                t2.setId(t1.getCode());
                t2.setName(t1.getName());
                t2.setParentId(t1.getParentCode());
            });
            redisTemplate.opsForValue().set(key,build);
            return build;
        }
        List<Tree<String>> trees = (List<Tree<String>>)redisTemplate.opsForValue().get(key);
        return trees;
    }
    @Override
    public String codeNameMap(String key, String code) {
        if(!redisTemplate.opsForHash().hasKey(key,code)) {
            FullCityVo fullCityVo = fullCityService.getByCode(code);
            if(fullCityVo != null) {
                redisTemplate.opsForHash().putIfAbsent(key,fullCityVo.getCode(),fullCityVo.getName());
                return fullCityVo.getName();
            }
            return null;
        }
        String name = (String)redisTemplate.opsForHash().get(key, code);
        return name;
    }
    @Override
    public String nameCodeMap(String key, String name) {
        if(!redisTemplate.opsForHash().hasKey(key,name)) {
            FullCityVo fullCityVo = fullCityService.getByFullName(name);
            if(fullCityVo != null) {
                redisTemplate.opsForHash().putIfAbsent(key,fullCityVo.getFullName(),fullCityVo.getCode());
                return fullCityVo.getCode();
            }
            return null;
        }
        String code = (String)redisTemplate.opsForHash().get(key, name);
        return code;
    }
    @Override
    public String supportType() {
        return DictionaryConst.FULL_CITY;
    }
}
package com.wyl.redis.service.impl;
import cn.hutool.core.lang.tree.Tree;
import com.wyl.redis.constant.DictionaryConst;
import com.wyl.redis.exception.BusinessException;
import com.wyl.redis.service.DictionaryOperate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.*;
/**
 * @Description
 * @Author WuYiLong
 * @Date 2024/7/3 17:23
 */
@Slf4j
@Component
public class DictionaryService implements ApplicationContextAware {
    private Map<String,DictionaryOperate>  dictionaryMaps = new HashMap<>();
    @Autowired
    private RedisTemplate redisTemplate;
    public DictionaryOperate buildDictionaryOperate(String key) {
        DictionaryOperate dictionaryOperate = dictionaryMaps.get(key);
        if(dictionaryOperate == null) {
            throw new BusinessException("字典的key不存在");
        }
        return dictionaryOperate;
    }
    public List list(String key) {
        String listKey = DictionaryConst.DIC+key+DictionaryConst.LIST;
        if(key.contains(":")) {
            String[] split = key.split(":");
            key = split[0];
            listKey = DictionaryConst.DIC+key+DictionaryConst.LIST+":"+split[1];
        }
        List list = buildDictionaryOperate(key).list(listKey);
        return list;
    }
    public List<Tree<String>> tree(String key) {
        String listKey = DictionaryConst.DIC+key+DictionaryConst.TREE;
        if(key.contains(":")) {
            String[] split = key.split(":");
            key = split[0];
            listKey = DictionaryConst.DIC+key+DictionaryConst.TREE+":"+split[1];
        }
        List<Tree<String>> tree =buildDictionaryOperate(key).tree(listKey);
        return tree;
    }
    public String codeNameMap(String key, String code) {
        String name = buildDictionaryOperate(key).codeNameMap(DictionaryConst.DIC+key+":codeNameMap", code);
        return name;
    }
    public String nameCodeMap(String key, String name) {
        String code = buildDictionaryOperate(key).nameCodeMap(DictionaryConst.DIC+key+":nameCodeMap", name);
        return code;
    }
    public void refresh() {
        Set keys = redisTemplate.keys("dic*");
        keys.forEach(v->{
            redisTemplate.delete(v);
        });
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, DictionaryOperate> dictionaryOperateMap = applicationContext.getBeansOfType(DictionaryOperate.class);
        dictionaryOperateMap.forEach((k,v)->{
            dictionaryMaps.put(v.supportType(),v);
        });
    }
}

controller層

package com.wyl.redis.controller;
import com.wyl.common.bean.ResponseData;
import com.wyl.redis.service.impl.DictionaryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
 *
 * @Description
 * @Author WuYiLong
 * @Date 2024/7/8 10:21
 */
@Api(tags = "字典api")
@RestController
@RequestMapping(value = "dictionary")
public class DictionaryController {
    @Autowired
    private DictionaryService dictionaryService;
    @ApiOperation(value = "字典刷新")
    @GetMapping(value = "refresh")
    public ResponseData refresh() {
        dictionaryService.refresh();
        return ResponseData.success();
    }
    @ApiOperation(value = "字典列表")
    @GetMapping(value = "list")
    public ResponseData list(String key) {
        return ResponseData.successInstance(dictionaryService.list(key));
    }
    @ApiOperation(value = "字典樹(shù)")
    @GetMapping(value = "tree")
    public ResponseData tree(String key) {
        return ResponseData.successInstance(dictionaryService.tree(key));
    }
    @ApiOperation(value = "根據(jù)code獲取名稱")
    @GetMapping(value = "codeNameMap")
    public ResponseData codeNameMap(String key, String code) {
        return ResponseData.successInstance(dictionaryService.codeNameMap(key,code));
    }
    @ApiOperation(value = "根據(jù)名稱獲取code")
    @GetMapping(value = "nameCodeMap")
    public ResponseData nameCodeMap(String key, String name) {
        return ResponseData.successInstance(dictionaryService.nameCodeMap(key, name));
    }
}

測(cè)試

根據(jù)code獲取名稱

字典列表

字典樹(shù)

字典在redis客戶端的存儲(chǔ)

項(xiàng)目說(shuō)明

只需要配置好本地的數(shù)據(jù)庫(kù),連接上自己本地的redis,啟動(dòng)項(xiàng)目,就會(huì)自動(dòng)初始化數(shù)據(jù)庫(kù)腳本到本地?cái)?shù)據(jù)庫(kù)。

package com.wyl.redis.config;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.dynamic.datasource.support.ScriptRunner;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.Map;
/**
 * @Description 公共初始化配置
 * @Author WuYiLong
 * @Date 2024/7/8 9:38
 */
@Slf4j
@ConditionalOnProperty(prefix = "init",value = "enabled",havingValue = "true")
@Component
public class InitConfig implements ApplicationRunner {
    @Autowired
    private DynamicDataSourceProperties dynamicDataSourceProperties;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("****************初始化數(shù)據(jù)庫(kù)腳本開(kāi)始*************");
        Map<String, DataSourceProperty> datasource = dynamicDataSourceProperties.getDatasource();
        DataSourceProperty master = datasource.get("master");
        DataSource build = DataSourceBuilder
                .create()
                .url(master.getUrl())
                .driverClassName(master.getDriverClassName())
                .password(master.getPassword())
                .type(master.getType())
                .username(master.getUsername())
                .build();
        ScriptRunner scriptRunner = new ScriptRunner(true, ";");
        scriptRunner.runScript(build,"classpath:/db/**");
        log.info("****************初始化數(shù)據(jù)庫(kù)腳本結(jié)束*************");
    }
}

在配置文件那里配置,設(shè)置init.enabled=true

init:
  enabled: false

項(xiàng)目地址

github

到此這篇關(guān)于springboot集成redis之字典緩存的文章就介紹到這了,更多相關(guān)springboot集成redis內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java泛型繼承原理與用法詳解

    Java泛型繼承原理與用法詳解

    這篇文章主要介紹了Java泛型繼承原理與用法,結(jié)合實(shí)例形式分析了java泛型繼承的相關(guān)原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • Java之PreparedStatement的使用詳解

    Java之PreparedStatement的使用詳解

    這篇文章主要介紹了Java之PreparedStatement的使用詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • maven依賴關(guān)系中的<scope>provided</scope>使用詳解

    maven依賴關(guān)系中的<scope>provided</scope>使用詳解

    這篇文章主要介紹了maven依賴關(guān)系中的<scope>provided</scope>使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java數(shù)組的基本操作方法整理

    Java數(shù)組的基本操作方法整理

    這篇文章主要介紹了Java數(shù)組的基本操作方法整理,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-08-08
  • Java本地高性能緩存的幾種常見(jiàn)實(shí)現(xiàn)方式

    Java本地高性能緩存的幾種常見(jiàn)實(shí)現(xiàn)方式

    在Java中緩存是一種常用的性能優(yōu)化技術(shù),用于在應(yīng)用程序中加速訪問(wèn)和查詢數(shù)據(jù)的速度,下面這篇文章主要給大家介紹了關(guān)于Java本地高性能緩存的幾種常見(jiàn)實(shí)現(xiàn)方式,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • SpringBoot JS-SDK自定義微信分享的實(shí)現(xiàn)

    SpringBoot JS-SDK自定義微信分享的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot JS-SDK自定義微信分享的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Jmeter正則表達(dá)式提取器實(shí)現(xiàn)過(guò)程圖解

    Jmeter正則表達(dá)式提取器實(shí)現(xiàn)過(guò)程圖解

    這篇文章主要介紹了Jmeter正則表達(dá)式提取器實(shí)現(xiàn)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Springboot如何獲取配置文件application.yml中自定義的變量并使用

    Springboot如何獲取配置文件application.yml中自定義的變量并使用

    這篇文章主要介紹了Springboot中獲取配置文件(application.yml)中自定義的變量并使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • springboot集成本地緩存Caffeine的三種使用方式(小結(jié))

    springboot集成本地緩存Caffeine的三種使用方式(小結(jié))

    本文主要介紹了springboot集成本地緩存Caffeine的三種使用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 掌握J(rèn)ava拼音轉(zhuǎn)換:pinyin4j庫(kù)使用方法及應(yīng)用價(jià)值

    掌握J(rèn)ava拼音轉(zhuǎn)換:pinyin4j庫(kù)使用方法及應(yīng)用價(jià)值

    pinyin4j是一個(gè)開(kāi)源的Java庫(kù),用于將漢字轉(zhuǎn)換為拼音,它支持將中文字符轉(zhuǎn)換為標(biāo)準(zhǔn)的全拼形式,并能夠處理多音字和聲調(diào),本文詳細(xì)解析pinyin4j庫(kù)的核心特性、使用方法及其應(yīng)用價(jià)值,感興趣的朋友一起看看吧
    2025-08-08

最新評(píng)論

外汇| 金山区| 湘西| 华亭县| 拜城县| 启东市| 锡林浩特市| 石家庄市| 忻城县| 个旧市| 高尔夫| 乐安县| 敦煌市| 南宁市| 株洲县| 建水县| 阳西县| 会理县| 贡觉县| 东台市| 定陶县| 石嘴山市| 军事| 沐川县| 伊川县| 焉耆| 临漳县| 临海市| 长泰县| 大洼县| 满洲里市| 新巴尔虎左旗| 贡嘎县| 孟连| 吴旗县| 砀山县| 安塞县| 凉城县| 普安县| 景东| 体育|