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

SpringBoot 整合Redisson重寫(xiě)cacheName支持多參數(shù)的案例代碼

 更新時(shí)間:2024年01月10日 09:53:42   作者:酒醉的胡鐵  
這篇文章主要介紹了SpringBoot 整合Redisson重寫(xiě)cacheName支持多參數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

依賴

<!--常用工具類(lèi) -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-extra</artifactId>
</dependency>
<!--redisson -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>${redisson.version}</version>
</dependency>

配置文件

spring:
  data:
    redis:
      # 地址
      host: localhost
      # 端口,默認(rèn)為6379
      port: 6379
      # 數(shù)據(jù)庫(kù)索引
      database: 0
      # 密碼(如沒(méi)有密碼請(qǐng)注釋掉)
#      password: ******
      # 連接超時(shí)時(shí)間
      timeout: 10s
      # 是否開(kāi)啟ssl
      ssl:
        enabled: false
redisson:
  # redis key前綴
  keyPrefix:
  # 線程池?cái)?shù)量
  threads: 4
  # Netty線程池?cái)?shù)量
  nettyThreads: 8
  # 單節(jié)點(diǎn)配置
  singleServerConfig:
    # 客戶端名稱(chēng)
    clientName: ${ruoyi.name}
    # 最小空閑連接數(shù)
    connectionMinimumIdleSize: 8
    # 連接池大小
    connectionPoolSize: 32
    # 連接空閑超時(shí),單位:毫秒
    idleConnectionTimeout: 10000
    # 命令等待超時(shí),單位:毫秒
    timeout: 3000
    # 發(fā)布和訂閱連接池大小
    subscriptionConnectionPoolSize: 50

Properties

package com.example.redisson.config.properties;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.redisson.config.ReadMode;
import org.redisson.config.SubscriptionMode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * Redisson 配置屬性
 *
 * @author Lion Li
 */
@Data
@Component
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
    /**
     * redis緩存key前綴
     */
    private String keyPrefix;
    /**
     * 線程池?cái)?shù)量,默認(rèn)值 = 當(dāng)前處理核數(shù)量 * 2
     */
    private int threads;
    /**
     * Netty線程池?cái)?shù)量,默認(rèn)值 = 當(dāng)前處理核數(shù)量 * 2
     */
    private int nettyThreads;
    /**
     * 單機(jī)服務(wù)配置
     */
    private SingleServerConfig singleServerConfig;
    /**
     * 集群服務(wù)配置
     */
    private ClusterServersConfig clusterServersConfig;
    @Data
    @NoArgsConstructor
    public static class SingleServerConfig {
        /**
         * 客戶端名稱(chēng)
         */
        private String clientName;
        /**
         * 最小空閑連接數(shù)
         */
        private int connectionMinimumIdleSize;
        /**
         * 連接池大小
         */
        private int connectionPoolSize;
        /**
         * 連接空閑超時(shí),單位:毫秒
         */
        private int idleConnectionTimeout;
        /**
         * 命令等待超時(shí),單位:毫秒
         */
        private int timeout;
        /**
         * 發(fā)布和訂閱連接池大小
         */
        private int subscriptionConnectionPoolSize;
    }
    @Data
    @NoArgsConstructor
    public static class ClusterServersConfig {
        /**
         * 客戶端名稱(chēng)
         */
        private String clientName;
        /**
         * master最小空閑連接數(shù)
         */
        private int masterConnectionMinimumIdleSize;
        /**
         * master連接池大小
         */
        private int masterConnectionPoolSize;
        /**
         * slave最小空閑連接數(shù)
         */
        private int slaveConnectionMinimumIdleSize;
        /**
         * slave連接池大小
         */
        private int slaveConnectionPoolSize;
        /**
         * 連接空閑超時(shí),單位:毫秒
         */
        private int idleConnectionTimeout;
        /**
         * 命令等待超時(shí),單位:毫秒
         */
        private int timeout;
        /**
         * 發(fā)布和訂閱連接池大小
         */
        private int subscriptionConnectionPoolSize;
        /**
         * 讀取模式
         */
        private ReadMode readMode;
        /**
         * 訂閱模式
         */
        private SubscriptionMode subscriptionMode;
    }
}

Config

注入自定義PlusSpringCacheManager支持多參數(shù)

package org.dromara.common.redis.config;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.config.properties.RedissonProperties;
import org.dromara.common.redis.handler.KeyPrefixHandler;
import org.dromara.common.redis.manager.PlusSpringCacheManager;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.CompositeCodec;
import org.redisson.codec.TypedJsonJacksonCodec;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
/**
 * redis配置
 *
 * @author Lion Li
 */
@Slf4j
@AutoConfiguration
@EnableCaching
@EnableConfigurationProperties(RedissonProperties.class)
public class RedisConfig {
    @Autowired
    private RedissonProperties redissonProperties;
    @Autowired
    private ObjectMapper objectMapper;
    @Bean
    public RedissonAutoConfigurationCustomizer redissonCustomizer() {
        return config -> {
            ObjectMapper om = objectMapper.copy();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            // 指定序列化輸入的類(lèi)型,類(lèi)必須是非final修飾的。序列化時(shí)將對(duì)象全類(lèi)名一起保存下來(lái)
            om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
            TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om);
            // 組合序列化 key 使用 String 內(nèi)容使用通用 json 格式
            CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec);
            config.setThreads(redissonProperties.getThreads())
                .setNettyThreads(redissonProperties.getNettyThreads())
                // 緩存 Lua 腳本 減少網(wǎng)絡(luò)傳輸(redisson 大部分的功能都是基于 Lua 腳本實(shí)現(xiàn))
                .setUseScriptCache(true)
                .setCodec(codec);
            RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
            if (ObjectUtil.isNotNull(singleServerConfig)) {
                // 使用單機(jī)模式
                config.useSingleServer()
                    //設(shè)置redis key前綴
                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
                    .setTimeout(singleServerConfig.getTimeout())
                    .setClientName(singleServerConfig.getClientName())
                    .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
                    .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
                    .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
                    .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
            }
            // 集群配置方式 參考下方注釋
            RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
            if (ObjectUtil.isNotNull(clusterServersConfig)) {
                config.useClusterServers()
                    //設(shè)置redis key前綴
                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
                    .setTimeout(clusterServersConfig.getTimeout())
                    .setClientName(clusterServersConfig.getClientName())
                    .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
                    .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
                    .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
                    .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
                    .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
                    .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
                    .setReadMode(clusterServersConfig.getReadMode())
                    .setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
            }
            log.info("初始化 redis 配置");
        };
    }
    /**
     * 自定義緩存管理器 整合spring-cache
     */
    @Bean
    public CacheManager cacheManager() {
        return new PlusSpringCacheManager();
    }
    /**
     * redis集群配置 yml
     *
     * --- # redis 集群配置(單機(jī)與集群只能開(kāi)啟一個(gè)另一個(gè)需要注釋掉)
     * spring.data:
     *   redis:
     *     cluster:
     *       nodes:
     *         - 192.168.0.100:6379
     *         - 192.168.0.101:6379
     *         - 192.168.0.102:6379
     *     # 密碼
     *     password:
     *     # 連接超時(shí)時(shí)間
     *     timeout: 10s
     *     # 是否開(kāi)啟ssl
     *     ssl.enabled: false
     *
     * redisson:
     *   # 線程池?cái)?shù)量
     *   threads: 16
     *   # Netty線程池?cái)?shù)量
     *   nettyThreads: 32
     *   # 集群配置
     *   clusterServersConfig:
     *     # 客戶端名稱(chēng)
     *     clientName: ${ruoyi.name}
     *     # master最小空閑連接數(shù)
     *     masterConnectionMinimumIdleSize: 32
     *     # master連接池大小
     *     masterConnectionPoolSize: 64
     *     # slave最小空閑連接數(shù)
     *     slaveConnectionMinimumIdleSize: 32
     *     # slave連接池大小
     *     slaveConnectionPoolSize: 64
     *     # 連接空閑超時(shí),單位:毫秒
     *     idleConnectionTimeout: 10000
     *     # 命令等待超時(shí),單位:毫秒
     *     timeout: 3000
     *     # 發(fā)布和訂閱連接池大小
     *     subscriptionConnectionPoolSize: 50
     *     # 讀取模式
     *     readMode: "SLAVE"
     *     # 訂閱模式
     *     subscriptionMode: "MASTER"
     */
}

重寫(xiě)cacheName方法

/**
 * Copyright (c) 2013-2021 Nikita Koksharov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dromara.common.redis.manager;
import org.dromara.common.redis.utils.RedisUtils;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonCache;
import org.springframework.boot.convert.DurationStyle;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
 * A {@link org.springframework.cache.CacheManager} implementation
 * backed by Redisson instance.
 * <p>
 * 修改 RedissonSpringCacheManager 源碼
 * 重寫(xiě) cacheName 處理方法 支持多參數(shù)
 *
 * @author Nikita Koksharov
 *
 */
@SuppressWarnings("unchecked")
public class PlusSpringCacheManager implements CacheManager {
    private boolean dynamic = true;
    private boolean allowNullValues = true;
    private boolean transactionAware = true;
    Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();
    ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();
    /**
     * Creates CacheManager supplied by Redisson instance
     */
    public PlusSpringCacheManager() {
    }
    /**
     * Defines possibility of storing {@code null} values.
     * <p>
     * Default is <code>true</code>
     *
     * @param allowNullValues stores if <code>true</code>
     */
    public void setAllowNullValues(boolean allowNullValues) {
        this.allowNullValues = allowNullValues;
    }
    /**
     * Defines if cache aware of Spring-managed transactions.
     * If {@code true} put/evict operations are executed only for successful transaction in after-commit phase.
     * <p>
     * Default is <code>false</code>
     *
     * @param transactionAware cache is transaction aware if <code>true</code>
     */
    public void setTransactionAware(boolean transactionAware) {
        this.transactionAware = transactionAware;
    }
    /**
     * Defines 'fixed' cache names.
     * A new cache instance will not be created in dynamic for non-defined names.
     * <p>
     * `null` parameter setups dynamic mode
     *
     * @param names of caches
     */
    public void setCacheNames(Collection<String> names) {
        if (names != null) {
            for (String name : names) {
                getCache(name);
            }
            dynamic = false;
        } else {
            dynamic = true;
        }
    }
    /**
     * Set cache config mapped by cache name
     *
     * @param config object
     */
    public void setConfig(Map<String, ? extends CacheConfig> config) {
        this.configMap = (Map<String, CacheConfig>) config;
    }
    protected CacheConfig createDefaultConfig() {
        return new CacheConfig();
    }
    @Override
    public Cache getCache(String name) {
        // 重寫(xiě) cacheName 支持多參數(shù)
        String[] array = StringUtils.delimitedListToStringArray(name, "#");
        name = array[0];
        Cache cache = instanceMap.get(name);
        if (cache != null) {
            return cache;
        }
        if (!dynamic) {
            return cache;
        }
        CacheConfig config = configMap.get(name);
        if (config == null) {
            config = createDefaultConfig();
            configMap.put(name, config);
        }
        if (array.length > 1) {
            config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());
        }
        if (array.length > 2) {
            config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());
        }
        if (array.length > 3) {
            config.setMaxSize(Integer.parseInt(array[3]));
        }
        if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {
            return createMap(name, config);
        }
        return createMapCache(name, config);
    }
    private Cache createMap(String name, CacheConfig config) {
        RMap<Object, Object> map = RedisUtils.getClient().getMap(name);
        Cache cache = new RedissonCache(map, allowNullValues);
        if (transactionAware) {
            cache = new TransactionAwareCacheDecorator(cache);
        }
        Cache oldCache = instanceMap.putIfAbsent(name, cache);
        if (oldCache != null) {
            cache = oldCache;
        }
        return cache;
    }
    private Cache createMapCache(String name, CacheConfig config) {
        RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);
        Cache cache = new RedissonCache(map, config, allowNullValues);
        if (transactionAware) {
            cache = new TransactionAwareCacheDecorator(cache);
        }
        Cache oldCache = instanceMap.putIfAbsent(name, cache);
        if (oldCache != null) {
            cache = oldCache;
        } else {
            map.setMaxSize(config.getMaxSize());
        }
        return cache;
    }
    @Override
    public Collection<String> getCacheNames() {
        return Collections.unmodifiableSet(configMap.keySet());
    }
}

支持多參數(shù)

key 格式為 cacheNames#ttl#maxIdleTime#maxSize
ttl 過(guò)期時(shí)間 如果設(shè)置為0則不過(guò)期 默認(rèn)為0
maxIdleTime 最大空閑時(shí)間 根據(jù)LRU算法清理空閑數(shù)據(jù) 如果設(shè)置為0則不檢測(cè) 默認(rèn)為0
maxSize 組最大長(zhǎng)度 根據(jù)LRU算法清理溢出數(shù)據(jù) 如果設(shè)置為0則無(wú)限長(zhǎng) 默認(rèn)為0
例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500

package com.example.redisson.core;
public interface CacheNames {
    /**
     * 演示案例
     */
    String DEMO_CACHE = "demo:cache#60s#10m#20";
    /**
     * 系統(tǒng)配置
     */
    String SYS_CONFIG = "sys_config";
    /**
     * 數(shù)據(jù)字典
     */
    String SYS_DICT = "sys_dict";
    /**
     * 租戶
     */
    String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
    /**
     * 用戶賬戶
     */
    String SYS_USER_NAME = "sys_user_name#30d";
    /**
     * 用戶名稱(chēng)
     */
    String SYS_NICKNAME = "sys_nickname#30d";
    /**
     * 部門(mén)
     */
    String SYS_DEPT = "sys_dept#30d";
    /**
     * OSS內(nèi)容
     */
    String SYS_OSS = "sys_oss#30d";
    /**
     * OSS配置
     */
    String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
    /**
     * 在線用戶
     */
    String ONLINE_TOKEN = "online_tokens";
}

使用

@Cacheable會(huì)先判斷有沒(méi)有緩存,如果有則不執(zhí)行方法體
@CachePut無(wú)論如何都會(huì)先執(zhí)行方法體然后將緩存保存供其他地方使用

package com.example.redisson.controller;
import com.example.redisson.core.CacheNames;
import com.example.redisson.core.R;
import com.example.redisson.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
/**
 * spring-cache 演示案例
 *
 * @author Lion Li
 */
// 類(lèi)級(jí)別 緩存統(tǒng)一配置
//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/cache")
public class RedisCacheController {
    /**
     * 測(cè)試 @Cacheable
     * <p>
     * 表示這個(gè)方法有了緩存的功能,方法的返回值會(huì)被緩存下來(lái)
     * 下一次調(diào)用該方法前,會(huì)去檢查是否緩存中已經(jīng)有值
     * 如果有就直接返回,不調(diào)用方法
     * 如果沒(méi)有,就調(diào)用方法,然后把結(jié)果緩存起來(lái)
     * 這個(gè)注解「一般用在查詢方法上」
     * <p>
     * 重點(diǎn)說(shuō)明: 緩存注解嚴(yán)謹(jǐn)與其他篩選數(shù)據(jù)功能一起使用
     * 例如: 數(shù)據(jù)權(quán)限注解 會(huì)造成 緩存擊穿 與 數(shù)據(jù)不一致問(wèn)題
     * <p>
     * cacheNames 命名規(guī)則 查看 {@link CacheNames} 注釋 支持多參數(shù)
     */
    @Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null")
    @GetMapping("/test1")
    public R<String> test1(String key, String value) {
        System.out.println("test1-->調(diào)用方法體");
        return R.ok("操作成功", value);
    }
    /**
     * 測(cè)試 @CachePut
     * <p>
     * 加了@CachePut注解的方法,會(huì)把方法的返回值put到緩存里面緩存起來(lái),供其它地方使用
     * 它「通常用在新增或者實(shí)時(shí)更新方法上」
     * <p>
     * cacheNames 命名規(guī)則 查看 {@link CacheNames} 注釋 支持多參數(shù)
     */
    @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
    @GetMapping("/test2")
    public R<String> test2(String key, String value) {
        System.out.println("test2-->調(diào)用方法體");
        return R.ok("操作成功", value);
    }
    /**
     * 測(cè)試 @CacheEvict
     * <p>
     * 使用了CacheEvict注解的方法,會(huì)清空指定緩存
     * 「一般用在刪除的方法上」
     * <p>
     * cacheNames 命名規(guī)則 查看 {@link CacheNames} 注釋 支持多參數(shù)
     */
    @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
    @GetMapping("/test3")
    public R<String> test3(String key, String value) {
        return R.ok("操作成功", value);
    }
    /**
     * 測(cè)試設(shè)置過(guò)期時(shí)間
     * 手動(dòng)設(shè)置過(guò)期時(shí)間10秒
     * 11秒后獲取 判斷是否相等
     */
    @GetMapping("/test6")
    public R<Boolean> test6(String key, String value) {
        RedisUtils.setCacheObject(key, value);
        boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
        System.out.println("***********" + flag);
        try {
            Thread.sleep(11 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Object obj = RedisUtils.getCacheObject(key);
        return R.ok(value.equals(obj));
    }
}

到此這篇關(guān)于SpringBoot 整合Redisson重寫(xiě)cacheName支持多參數(shù)的文章就介紹到這了,更多相關(guān)SpringBoot 整合Redisson內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論