package com.futu.course.common.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.BoundListOperations; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.support.atomic.RedisAtomicInteger; import org.springframework.data.redis.support.atomic.RedisAtomicLong; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.*; import java.util.concurrent.TimeUnit; /** * redisTemplate封装 */ @Component public class RedisUtil { @Autowired private final RedisTemplate redisTemplate; //锁名称前缀 public static final String LOCK_PREFIX = "redis_lock"; //加锁失效时间,毫秒 public static final int LOCK_EXPIRE = 10; // ms public static Integer workId=0; public static Integer dataId=0; public RedisUtil(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } /** * redis发布消息 * * @param channel * @param message */ public void sendMessage(String channel, String message) { redisTemplate.convertAndSend(channel, message); } /** * 指定缓存失效时间 * * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time, TimeUnit timeUnit) { try { if (time > 0) { redisTemplate.expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } /** * 删除缓存 * * @param keys 集合 */ public void del(Collection keys) { redisTemplate.delete(keys); } //============================String============================= /** * 普通缓存获取 * * @param key 键 * @return 值 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time, TimeUnit timeUnit) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, timeUnit); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().decrement(key, delta); } //================================Map================================= /** * HashGet * * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * * @param key 键 * @return 对应的多个键值 */ public Map hmget(String key) { return redisTemplate.opsForHash().entries(key); } /** * HashSet * * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map map, long time, TimeUnit timeUnit) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ 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; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value, long time, TimeUnit timeUnit) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } /** * 判断hash表中是否有该项的值 * * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, -by); } //============================set============================= /** * 根据key获取Set中的所有值 * * @param key 键 * @return */ public Set sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获得锁 * * @param lock * @return */ public boolean lock(String lock) { return (boolean) redisTemplate.execute((RedisCallback) connection -> { //获取时间毫秒值 long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1; //获取锁 Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes()); if (acquire) { return true; } else { byte[] bytes = connection.get(lock.getBytes()); //非空判断 if (Objects.nonNull(bytes) && bytes.length > 0) { long expireTime = Long.parseLong(new String(bytes)); // 如果锁已经过期 if (expireTime < System.currentTimeMillis()) { // 重新加锁,防止死锁 byte[] set = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes()); return Long.parseLong(new String(set)) < System.currentTimeMillis(); } } } return false; }); } /** * 获得锁 * * @param lock * @return */ public boolean lock(String lock,Long timeOut) { return (boolean) redisTemplate.execute((RedisCallback) connection -> { //获取时间毫秒值 long expireAt = System.currentTimeMillis() + timeOut + 1; //获取锁 Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes()); if (acquire) { return true; } else { byte[] bytes = connection.get(lock.getBytes()); //非空判断 if (Objects.nonNull(bytes) && bytes.length > 0) { long expireTime = Long.parseLong(new String(bytes)); // 如果锁已经过期 if (expireTime < System.currentTimeMillis()) { // 重新加锁,防止死锁 byte[] set = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes()); return Long.parseLong(new String(set)) < System.currentTimeMillis(); } } } return false; }); } /** * 删除锁 * * @param key */ public void deleteLock(String key) { redisTemplate.delete(key); } /** * 加锁,⽆阻塞 *

* 锁 * * @param key 请求标识 * @param userId 超期时间 * @param expireTime 上锁时间,单位TimeUnit.SECONDS * @param timeout 等待时间,单位TimeUnit.SECONDS * @return */ public Boolean lock(String key, long expireTime, Long userId, long timeout) { Long start = System.currentTimeMillis(); //在⼀定时间内获取锁,超时则返回错误 // for (; ; ) { //,则证明获取锁成功 //Set // OK Boolean ret = redisTemplate.opsForValue().setIfAbsent(key, userId, expireTime, TimeUnit.SECONDS); if (ret != null && ret) { return true; } // 否则循环等待,在 // 时间内仍未获取到锁,则获取失败 long end = System.currentTimeMillis() - start; if (end >= timeout * 1000) { return false; } } } public Boolean lock(String key, long expireTime, Long userId) { Boolean ret = redisTemplate.opsForValue().setIfAbsent(key, userId, expireTime, TimeUnit.SECONDS); return ret != null && ret; } public Boolean unlock(String key, Long userId) { Object o = redisTemplate.opsForValue().get(key); if(userId.equals(o)){ return redisTemplate.delete(key); }else{ return false; } } /** * 将set数据放入缓存 * * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, TimeUnit timeUnit, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) { expire(key, time, timeUnit); } return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * * @param key 键 * @return */ public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } //===============================list================================= /** * 获取list缓存的内容 * * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List listGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 弹出对象 * @param key * @return */ public Object popLeftList(String key){ return redisTemplate.opsForList().leftPop(key); } /** * 获取list缓存的长度 * * @param key 键 * @return */ public long listSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object listGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean listSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public void listTrim(String key, long start,long end) { try { redisTemplate.opsForList().trim(key,start,end); } catch (Exception e) { e.printStackTrace(); } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean listSet(String key, Object value, long time, TimeUnit timeUnit) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) { expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean listSet(String key, List value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * list大小 * @param key * @return */ public Long getListSize(String key){ return redisTemplate.opsForList().size(key); } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean listSet(String key, List value, long time, TimeUnit timeUnit) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) { expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean listUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long listRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 模糊查询获取key值 * * @param pattern * @return */ public Set keys(String pattern) { return redisTemplate.keys(pattern); } /** * 使用Redis的消息队列 * * @param channel * @param message 消息内容 */ public void convertAndSend(String channel, Object message) { redisTemplate.convertAndSend(channel, message); } //=========BoundListOperations 用法 start============ /** * 将数据添加到Redis的list中(从右边添加) * * @param listKey * @param time 过期时间 * @param values 待添加的数据 */ public void addToListRight(String listKey, long time, Object... values) { //绑定操作 BoundListOperations boundValueOperations = redisTemplate.boundListOps(listKey); //插入数据 boundValueOperations.rightPushAll(values); //设置过期时间 boundValueOperations.expire(time, TimeUnit.SECONDS); } /** * 根据起始结束序号遍历Redis中的list * * @param listKey * @param start 起始序号 * @param end 结束序号 * @return */ public List rangeList(String listKey, long start, long end) { //绑定操作 BoundListOperations boundValueOperations = redisTemplate.boundListOps(listKey); //查询数据 return boundValueOperations.range(start, end); } /** * 弹出右边的值 --- 并且移除这个值 * * @param listKey */ public Object rifhtPop(String listKey) { //绑定操作 BoundListOperations boundValueOperations = redisTemplate.boundListOps(listKey); return boundValueOperations.rightPop(); } /** * @param key * @return */ public Long getIncr(String key) { RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); Long increment = entityIdCounter.getAndIncrement(); return increment; } /** * @return */ public synchronized Integer getSequenceId() { String key = "sms_sequence_id"; RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); int sequenceId = idCount.getAndIncrement(); if (sequenceId <= 1000 || sequenceId >= 1000000000) { idCount.set(1000); sequenceId = idCount.getAndIncrement(); return sequenceId; } return sequenceId; } public void setCount(String key ,int initValue){ RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); idCount.set(initValue); } /** * @return */ public Integer getCount(String key) { RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); int count = idCount.getAndIncrement(); if (count ==Integer.MAX_VALUE-1) { idCount.set(0); count = idCount.getAndIncrement(); return count; } return count; } public Integer getStartCount(String key) { RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); int count = idCount.getAndIncrement(); if(count<=1){ this.expire(key, CacheKey.DAY1,TimeUnit.DAYS); } if (count ==Integer.MAX_VALUE-1) { idCount.set(0); count = idCount.getAndIncrement(); return count; } return count; } public String getStartNum(Integer num){ String str=num.toString(); int len=str.length(); if(str.length()<5){ StringBuilder sb = new StringBuilder(); for(int i=0;i<5-len;i++){ sb.append("0"); } sb.append(str); return sb.toString(); } return str; } public String getStartNum(String key){ Integer num=getStartCount(key); String str=num.toString(); int len=str.length(); if(str.length()<5){ StringBuilder sb = new StringBuilder(); for(int i=0;i<5-len;i++){ sb.append("0"); } sb.append(str); return sb.toString(); } return str; } public synchronized Integer getSequenceNumber3(String key) { RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); int sequenceId = idCount.getAndIncrement(); if (sequenceId < 0 || sequenceId >= Integer.MAX_VALUE) { idCount.set(0); sequenceId = idCount.getAndIncrement(); return sequenceId; } return sequenceId; } public synchronized Integer getWorkId(String key) { RedisAtomicInteger idCount = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); int sequenceId = idCount.getAndIncrement(); if (sequenceId < 0 || sequenceId >= 31) { idCount.set(0); sequenceId = idCount.getAndIncrement(); return sequenceId; } return sequenceId; } /** * 14 * @Description: 初始化自增长值 * 15 * @param key key * 16 * @param value 当前值 * 17 */ public void setIncr(String key, int value) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.set(value); } /** * 14 * @Description: 初始化自增长值 * 15 * @param key key * 16 * @param value 当前值 * 17 */ public void setInteger(String key, int value) { RedisAtomicInteger counter = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory()); counter.set(value); } /** * 保存到hash * @param key * @param hashKey * @param value */ public void setHashMap(String key,Object hashKey,Object value){ redisTemplate.opsForHash().put(key,hashKey,value); } /** * 获取hashvalue * @param key * @param hashKey * @return */ public Object getHashValue(String key,Object hashKey){ return redisTemplate.opsForHash().get(key,hashKey); } /** * 删除hash中单个对象 * @param key * @param hashKey */ public void remove(String key,Object hashKey){ redisTemplate.opsForHash().delete(key,hashKey); } /** * 获取redisTemplate * @return */ public RedisTemplate getRedisTemplate(){ return redisTemplate; } /** * 存储数据或修改数据 * * @param modelMap * @param mapName */ public void setMap(String mapName, Map modelMap) { HashOperations hps = redisTemplate.opsForHash(); hps.putAll(mapName, modelMap); } /** * 获取数据Map * * @param mapName * @return */ public Map getMapValue(String mapName) { HashOperations hps = this.redisTemplate.opsForHash(); return hps.entries(mapName); } /** * 获取数据Map size * * @param mapName * @return */ public int getMapSize(String mapName) { HashOperations hps = this.redisTemplate.opsForHash(); return hps.entries(mapName).size(); } /** * 获取数据value * * @param mapName * @param hashKey * @return */ public Object getValue(String mapName, String hashKey) { HashOperations hps = this.redisTemplate.opsForHash(); return hps.get(mapName, hashKey); } /** * 批量删除缓存数据 * * @param keys */ public long deleteData(String key,Object ...keys) { // 执行批量删除操作时先序列化template long b= redisTemplate.opsForHash().delete(key,keys); return b; } private void batchCacheMarketInfo(List dataList, long expire) { //使用pipeline方式 redisTemplate.executePipelined(new RedisCallback>() { @Override public List doInRedis(RedisConnection connection) throws DataAccessException { for (Object marketInfo : dataList) { String key = ""; byte[] rawKey = redisTemplate.getKeySerializer().serialize(key); connection.setEx(rawKey, expire, redisTemplate.getValueSerializer().serialize(marketInfo)); } return null; } }); } //=========BoundListOperations 用法 End============ }