redis configuration tool class, use LettuceConnectionFactory and close ping

@Slf4j
@Configuration
public class RedisConfig11 extends CachingConfigurerSupport {

    @Value("${redis. maxIdle}")
    private int maxIdle;
    @Value("${redis. minIdle}")
    private int minIdle;
    @Value("${redis. maxTotal}")
    private int maxTotal;
    @Value("${redis. timeout}")
    private int timeout;
    @Value("${redis.cluster.nodes}")
    private String nodes;
    @Value("${redis.password}")
    private String password;

    @Autowired
    private CustomRedisKeySerializer customRedisKeySerializer;
    @Autowired
    private CustomRedisSerializer customRedisSerializer;


    @Bean(destroyMethod = "destroy")
    public LettuceConnectionFactory lettuceConnectionFactory() {
        // Connection pool configuration
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        // The maximum number of idle threads in the thread pool
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        // The minimum number of idle threads in the thread pool
        genericObjectPoolConfig.setMinIdle(minIdle);
        // The maximum number of threads in the thread pool
        genericObjectPoolConfig.setMaxTotal(maxTotal);
        // When the connection pool is exhausted, the client should wait for the maximum time for a new connection, in milliseconds
        genericObjectPoolConfig.setMaxWaitMillis(timeout);
        genericObjectPoolConfig.setTestOnBorrow(false);

        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                // close ping
                .pingBeforeActivateConnection(false)
                .build();

        LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
                .clientOptions(clusterClientOptions)
                // overtime time
                .shutdownTimeout(Duration.ofMillis(timeout))
                .poolConfig(genericObjectPoolConfig)
                .build();

        // redis cluster node ip:port English comma separated
        if (StringUtils. isEmpty(nodes)) {
            log.error("redis cluster node is empty");
            throw new RuntimeException();
        }
        String[] hostAndPorts = nodes. split(",");
        Set<RedisNode> nodes = new HashSet<>();
        for (String hostAndPort : hostAndPorts) {
            String[] ipAndPort = hostAndPort. split(":");
            nodes.add(new RedisNode(ipAndPort[0], Integer.parseInt(ipAndPort[1])));
        }

        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        redisClusterConfiguration.setClusterNodes(nodes);
        redisClusterConfiguration.setMaxRedirects(nodes.size());
        redisClusterConfiguration.setPassword(RedisPassword.of(password));

        // Create a connection according to the configuration and client configuration
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
        lettuceConnectionFactory. afterPropertiesSet();

        return lettuceConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        // set serialization
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jackson2JsonRedisSerializer();
        // configure redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        // key serialization
        redisTemplate.setKeySerializer(customRedisSerializer);
        // value serialization
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // Hash key serialization
        redisTemplate.setHashKeySerializer(customRedisSerializer);
        // Hash value serialization
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
        // Configure serialization (the cache is valid for 6 hours by default)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(6));
        RedisCacheConfiguration redisCacheConfiguration = config
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .computePrefixWith(customRedisKeySerializer);

        return RedisCacheManager
                // Create a RedisCacheWriter object by means of lock writing
                .builder(RedisCacheWriter.lockingRedisCacheWriter(lettuceConnectionFactory))
                .cacheDefaults(redisCacheConfiguration)
                .transactionAware()
                .build();
    }


    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper()
                .setVisibility(PropertyAccessor.ALL, Visibility.ANY).enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL));
        return jackson2JsonRedisSerializer;
    }

}

@Slf4j
@Component
public class CustomRedisSerializer implements RedisSerializer<String> {

    @Value("${system.id}")
    private String systemId;

    @Override
    public byte[] serialize(String s) throws SerializationException {
        String keyPrefix = systemId + ":";
        String key = keyPrefix + s;
        return key.getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public String deserialize(byte[] bytes) throws SerializationException {
        String keyPrefix = systemId + ":";
        String key = new String(bytes, StandardCharsets. UTF_8);
        int indexOf = key. indexOf(keyPrefix);
        if (indexOf > 0) {
            log.info("key missing prefix");
        } else {
            int index = indexOf + keyPrefix. length();
            key = key.substring(index);
        }
        log.info("saveKey:{}", key);
        return key;
    }
}

@Slf4j
@Component
public class CustomRedisKeySerializer implements CacheKeyPrefix {
    @Value("${system.id}")
    private String systemId;

    @Override
    public String compute(String cacheName) {
        // You need to customize the key generation rules, and add the system prefix before the key
        String keyPrefix = systemId + ":";
        return keyPrefix + cacheName + "::";
    }
}
@Component
public class RedisUtils {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * Specifies the cache expiration time
     *
     * @param key key
     * @param time time (seconds)
     */
    public void expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Get the expiration time according to the key
     *
     * @param key key cannot be null
     * @return time (seconds) return 0 means it is permanent
     */
    public long getExpire(String key) {
        Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        return ObjectUtils.isEmpty(expire) ? 0L : expire;
    }

    /**
     * Determine whether the key exists
     *
     * @param key key
     * @return true exists false does not exist
     */
    public boolean hasKey(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.hasKey(key));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * delete cache
     *
     * @param key can pass one value or more
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null & amp; & amp; key. length > 0) {
            if (key. length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }

    // =============================String==================== ==========

    /**
     * Ordinary cache acquisition
     *
     * @param key key
     * @return value
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }


    /**
     * Ordinary cache put
     *
     * @param key key
     * @param value value
     * @return true success false failure
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * Ordinary cache is put in and set time
     *
     * @param key key
     * @param value value
     * @param time time (seconds) time must be greater than 0, if time is less than or equal to 0, it will be set indefinitely
     * @return true success false failure
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * increment
     *
     * @param key key
     * @param delta How much to increase (greater than 0)
     * @return incremented result
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("Increment factor must be greater than 0");
        }
        Long increment = redisTemplate.opsForValue().increment(key, delta);
        return ObjectUtils.isEmpty(increment) ? 0L : increment;
    }

    /**
     * decrement
     *
     * @param key key
     * @param delta how much to reduce (less than 0)
     * @return long decremented result
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("The decrement factor must be greater than 0");
        }
        Long increment = redisTemplate.opsForValue().increment(key, -delta);
        return ObjectUtils.isEmpty(increment) ? 0L : increment;
    }

    // =================================Map================ ===================

    /**
     * HashGet
     *
     * @param key key cannot be null
     * @param item item cannot be null
     * @return value
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * Get all key values corresponding to hashKey
     *
     * @param key key
     * @return corresponding multiple key values
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key key
     * @param map corresponds to multiple key values
     * @return true success false failure
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet and set the time
     *
     * @param key key
     * @param map corresponds to multiple key values
     * @param time time (seconds)
     * @return true success false failure
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put data into a hash table, if it does not exist, it will be created
     *
     * @param key key
     * @param item item
     * @param value value
     * @return true success false failure
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put data into a hash table, if it does not exist, it will be created
     *
     * @param key key
     * @param item item
     * @param value value
     * @param time Time (seconds) Note: If the existing hash table has time, the original time will be replaced here
     * @return true success false failure
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Delete the value in the hash table
     *
     * @param key key cannot be null
     * @param item item can be multiple and cannot be null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * Determine whether there is a value for this item in the hash table
     *
     * @param key key cannot be null
     * @param item item cannot be null
     * @return true exists false does not exist
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash increment If it does not exist, it will create one and return the newly added value
     *
     * @param key key
     * @param item item
     * @param by how much to increase (greater than 0)
     * @return hash incremented result
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash decrement
     *
     * @param key key
     * @param item item
     * @param by to reduce (less than 0)
     * @return hash decremented result
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    // ================================================= ==========

    /**
     * Get all the values in the Set according to the key
     *
     * @param key key
     * @return Set<Object>
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Query from a set according to value, whether it exists
     *
     * @param key key
     * @param value value
     * @return true exists false does not exist
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put the data into the set cache
     *
     * @param key key
     * @param values value can be multiple
     * @return number of successes
     */
    public long sSet(String key, Object... values) {
        try {
            Long add = redisTemplate.opsForSet().add(key, values);
            return ObjectUtils.isEmpty(add) ? 0L : add;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * Put the set data into the cache
     *
     * @param key key
     * @param time time (seconds)
     * @param values value can be multiple
     * @return number of successes
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0) {
                expire(key, time);
            }
            return ObjectUtils.isEmpty(count) ? 0L : count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * Get the length of the set cache
     *
     * @param key key
     * @return Get the length of the set
     */
    public long sGetSetSize(String key) {
        try {
            Long size = redisTemplate.opsForSet().size(key);
            return ObjectUtils.isEmpty(size) ? 0L : size;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * Remove the value of value
     *
     * @param key key
     * @param values value can be multiple
     * @return the number of removed
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return ObjectUtils.isEmpty(count) ? 0L : count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    // ================================= list================== ==================

    /**
     * Get the content of the list cache
     *
     * @param key key
     * @param start start
     * @param end end 0 to -1 represent all values
     * @return List<Object>
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Get the length of the list cache
     *
     * @param key key
     */
    public long lGetListSize(String key) {
        try {
            Long size = redisTemplate.opsForList().size(key);
            return ObjectUtils.isEmpty(size) ? 0L : size;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * Get the value in the list by index
     *
     * @param key key
     * @param index index index>=0, 0 is the header, 1 is the second element, and so on; when index<0, -1 is the end of the table, -2 is the second-to-last element, and so on
     * @return Object
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Put the list into the cache
     *
     * @param key key
     * @param value value
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put the list into the cache and specify the expiration time
     *
     * @param key key
     * @param value value
     * @param time time (seconds)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put the list into the cache in batches
     *
     * @param key key
     * @param value value
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Put the list into the cache
     *
     * @param key key
     * @param value value
     * @param time time (seconds)
     * @return Boolean
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Modify a piece of data in the list according to the index
     *
     * @param key key
     * @param index index
     * @param value value
     * @return operation result
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Remove N values as value
     *
     * @param key key
     * @param count how many to remove
     * @param value value
     * @return the number of removed
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return ObjectUtils.isEmpty(remove) ? 0L : remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

}