SpringBoot集成Redis
引入依赖
- pom.xml
<!-- 引入redis依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 引入redis连接池的依赖 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
Redis配置
- application.yml 配置
spring: redis: database: 0 host: 127.0.0.1 port: 6379 timeout: 5000 lettuce: pool: max-active: 32 max-wait: -1 max-idle: 16 min-idle: 8
- RedisConfig.java 配置
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @author ZhangFZ * @date 2020/9/4 16:33 **/ @Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); //使用fastjson序列化 FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); // value值的序列化采用fastJsonRedisSerializer template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); // key的序列化采用StringRedisSerializer template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }
常用命令工具类
import org.springframework.data.redis.core.*; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @author Maple * @date 2018/9/19 */ @Component public class RedisUtil { @Resource private RedisTemplate<String, Object> redisTemplate; /** * 写入缓存 */ public boolean set(final String key, Object value) { boolean result = false; try { ValueOperations<String, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 写入缓存设置时效时间 */ public boolean set(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<String, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 更新缓存 */ public boolean getAndSet(final String key, String value) { boolean result = false; try { redisTemplate.opsForValue().getAndSet(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 批量删除对应的value */ public void remove(final String... keys) { for (String key : keys) { remove(key); } } /** * 批量删除key */ public void removePattern(final String pattern) { Set<String> keys = redisTemplate.keys(pattern); if (keys.size() > 0){ redisTemplate.delete(keys); } } /** * 删除对应的value * @param key */ public void remove(final String key) { if (exists(key)) { redisTemplate.delete(key); } } /** * 判断缓存中是否有对应的value */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 读取缓存 */ public Object get(final String key) { Object result = null; ValueOperations<String, Object> operations = redisTemplate.opsForValue(); result = operations.get(key); return result; } /** * 哈希 添加 */ public void hmSet(String key, Object hashKey, Object value){ HashOperations<String, Object, Object> hash = redisTemplate.opsForHash(); hash.put(key,hashKey,value); } /** * 哈希获取数据 */ public Object hmGet(String key, Object hashKey){ HashOperations<String, Object, Object> hash = redisTemplate.opsForHash(); return hash.get(key,hashKey); } /** * 列表添加 */ public void lPush(String k,Object v){ ListOperations<String, Object> list = redisTemplate.opsForList(); list.rightPush(k,v); } /** * 列表获取 */ public List<Object> lRange(String k, long l, long l1){ ListOperations<String, Object> list = redisTemplate.opsForList(); return list.range(k,l,l1); } /** * 集合添加 */ public void addSet(String key,Object value){ SetOperations<String, Object> set = redisTemplate.opsForSet(); set.add(key,value); } /** * 删除集合下的所有值 */ public void removeSetAll(String key) { SetOperations<String, Object> set = redisTemplate.opsForSet(); Set<Object> objectSet = set.members(key); if(objectSet != null && objectSet.size() > 0){ for (Object o : objectSet){ set.remove(key, o); } } } /** * 判断集合里面是否包含某个元素 */ public Boolean isMember(String key, Object member){ SetOperations<String, Object> set = redisTemplate.opsForSet(); return set.isMember(key, member); } /** * 集合获取 */ public Set<Object> setMembers(String key){ SetOperations<String, Object> set = redisTemplate.opsForSet(); return set.members(key); } /** * 有序集合添加 */ public void zAdd(String key,Object value,double scoure){ ZSetOperations<String, Object> zset = redisTemplate.opsForZSet(); zset.add(key,value,scoure); } /** * 有序集合获取 */ public Set<Object> rangeByScore(String key,double scoure,double scoure1){ ZSetOperations<String, Object> zset = redisTemplate.opsForZSet(); return zset.rangeByScore(key, scoure, scoure1); } /** * setNX * @param lockKey 锁 * @param value 请求标识 * @param exptime 过期时间 * @return 是否获取到锁 */ public boolean tryGetDistributedRedisLock( String lockKey, Serializable value, final long exptime) { return (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection connection) { RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); RedisSerializer keySerializer = redisTemplate.getKeySerializer(); Object obj = connection.execute("set", keySerializer.serialize(lockKey), valueSerializer.serialize(value), SafeEncoder.encode("NX"), SafeEncoder.encode("EX"), Protocol.toByteArray(exptime)); return obj != null; } }); } /** * 释放锁 */ private final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 * @param lockKey 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public boolean releaseDistributedRedisLock(String lockKey, String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = redisTemplate.execute(new DefaultRedisScript(script,Long.class), Collections.singletonList(lockKey), requestId); return RELEASE_SUCCESS.equals(result); } }
监听redis Key过期的事件
- 开始redis过期Key的监听事件
修改redis.conf配置为文件
notify-keyspace-events Ex
K:keyspace事件,事件以__keyspace@<db>__为前缀进行发布; E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布; g:一般性的,非特定类型的命令,比如del,expire,rename等; $:字符串特定命令; l:列表特定命令; s:集合特定命令; h:哈希特定命令; z:有序集合特定命令; x:过期事件,当某个键过期并删除时会产生该事件; e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件; A:g$lshzxe的别名,因此”AKE”意味着所有事件。
- 配置RedisConfig.java文件
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @author ZhangFZ * @date 2020/9/4 16:33 **/ @Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); //使用fastjson序列化 FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); // value值的序列化采用fastJsonRedisSerializer template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); // key的序列化采用StringRedisSerializer template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } /** * 开启监听redis Key过期事件 */ @Bean public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory){ RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
- 定义监听器RedisKeyExpireListener
import com.hege.sale.bean.common.GlobalField; import com.hege.sale.service.sale.IContractProductService; import com.hege.sale.util.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.stereotype.Component; /** * Redis监听key过期 * @author ZhangFZ * @date 2020/10/31 10:41 **/ @Slf4j @Component public class RedisKeyExpireListener extends KeyExpirationEventMessageListener { @Autowired private RedisUtil redisUtil; public RedisKeyExpireListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { String expireKey = message.toString(); // 根据过期的key处理对应的业务逻辑 System.out.println(expireKey + "已过期-------------------"); } }