package com.zzg.framework.config; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * redis配置 * * @author ruoyi */ @Configuration @EnableCaching @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig extends CachingConfigurerSupport { @Bean @SuppressWarnings(value = {"unchecked", "rawtypes"}) public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); // 使用StringRedisSerializer来序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); // Hash的key也采用StringRedisSerializer的序列化方式 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } @Bean public DefaultRedisScript limitScript() { DefaultRedisScript redisScript = new DefaultRedisScript<>(); redisScript.setScriptText(limitScriptText()); redisScript.setResultType(Long.class); return redisScript; } @Bean public RedisConnectionFactory redisConnectionFactory(RedisProperties properties) { // 配置连接池 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMinIdle(properties.getLettuce().getPool().getMinIdle()); poolConfig.setMaxIdle(properties.getLettuce().getPool().getMaxIdle()); poolConfig.setMaxTotal(properties.getLettuce().getPool().getMaxActive()); poolConfig.setMaxWaitMillis(properties.getLettuce().getPool().getMaxWait().toMillis()); // 配置 Lettuce 客户端 LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig) .build(); // 创建连接工厂 RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration(); serverConfig.setHostName(properties.getHost()); serverConfig.setPort(properties.getPort()); serverConfig.setPassword(properties.getPassword()); return new LettuceConnectionFactory(serverConfig, clientConfig); } /** * 限流脚本 */ private String limitScriptText() { return "local key = KEYS[1]\n" + "local count = tonumber(ARGV[1])\n" + "local time = tonumber(ARGV[2])\n" + "local current = redis.call('get', key);\n" + "if current and tonumber(current) > count then\n" + " return tonumber(current);\n" + "end\n" + "current = redis.call('incr', key)\n" + "if tonumber(current) == 1 then\n" + " redis.call('expire', key, time)\n" + "end\n" + "return tonumber(current);"; } }