技術交流QQ羣【JAVA,C++,Python,.NET,BigData,AI】:170933152
1.pom.xml添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.application.properties中添加redis配置
#redis緩存配置
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.pool.max-active=-1
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.pool.min-idle=0
spring.redis.database=5
spring.redis.host=172.19.128.38
spring.redis.password=123456
spring.redis.port=6379
#redis緩存配置
spring.redis.database2=6
spring.redis.host2=172.19.128.38
spring.redis.password2=123456
spring.redis.port2=6379
#6個小時
spring.redis.timeout=21600
#redis緩存配置
spring.redis2.database=6
spring.redis2.host=172.19.128.38
spring.redis2.password=123456
spring.redis2.port=6379
#6個小時
spring.redis2.timeout=21600
3.新建配置類
RedisConfig
package cn.gov.credream.scsupport.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import java.lang.reflect.Method;
/**
* spring-boot-data-packing 設置Redis多實例的基類
*
* @Author credream
* @Date 2019/10/12
*/
@EnableCaching
@Configuration
public class RedisConfig {
@Value("${spring.redis.pool.max-active}")
private int redisPoolMaxActive;
@Value("${spring.redis.pool.max-wait}")
private int redisPoolMaxWait;
@Value("${spring.redis.pool.max-idle}")
private int redisPoolMaxIdle;
@Value("${spring.redis.pool.min-idle}")
private int redisPoolMinIdle;
/**
* 配置Key的生成方式
*
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(o.getClass().getName())
.append(method.getName());
for (Object object : objects) {
stringBuilder.append(object.toString());
}
return stringBuilder.toString();
}
};
}
/**
* 創建redis連接工廠
*
* @param dbIndex
* @param host
* @param port
* @param password
* @param timeout
* @return
*/
public JedisConnectionFactory createJedisConnectionFactory(int dbIndex, String host, int port, String password, int timeout) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setDatabase(dbIndex);
jedisConnectionFactory.setHostName(host);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setPassword(password);
jedisConnectionFactory.setTimeout(timeout);
jedisConnectionFactory.setPoolConfig(setPoolConfig(redisPoolMaxIdle, redisPoolMinIdle, redisPoolMaxActive, redisPoolMaxWait, true));
return jedisConnectionFactory;
}
/**
* 配置CacheManager
*
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
return redisCacheManager;
}
/**
* 設置連接池屬性
*
* @param maxIdle
* @param minIdle
* @param maxActive
* @param maxWait
* @param testOnBorrow
* @return
*/
public JedisPoolConfig setPoolConfig(int maxIdle, int minIdle, int maxActive, int maxWait, boolean testOnBorrow) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxWaitMillis(maxWait);
poolConfig.setTestOnBorrow(testOnBorrow);
return poolConfig;
}
/**
* 設置RedisTemplate的序列化方式
*
* @param redisTemplate
*/
public void setSerializer(RedisTemplate redisTemplate) {
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//設置鍵(key)的序列化方式
redisTemplate.setKeySerializer(new StringRedisSerializer());
//設置值(value)的序列化方式
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
}
}
4.配置第一個數據源的配置類
DefaultRedisConfig
package cn.gov.credream.scsupport.config;
import org.springframework.beans.factory.annotation.Value;
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.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* llld-parent 配置默認Redis操作實例 到Spring中
*
* @Author credream
* @Date 2018/8/2
*/
@Configuration
@EnableCaching
public class DefaultRedisConfig extends RedisConfig {
@Value("${spring.redis.database}")
private int dbIndex;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.timeout}")
private int timeout;
/**
* 配置redis連接工廠
*
* @return
*/
@Bean
public RedisConnectionFactory defaultRedisConnectionFactory() {
return createJedisConnectionFactory(dbIndex, host, port, password, timeout);
}
/**
* 配置redisTemplate 注入方式使用@Resource(name="") 方式注入
*
* @return
*/
@Bean(name = "defaultRedisTemplate")
public StringRedisTemplate defaultRedisTemplate() {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(defaultRedisConnectionFactory());
setSerializer(template);
template.afterPropertiesSet();
return template;
}
}
5.配置第2個數據源,配置類
CacheRedisConfig
package cn.gov.credream.scsupport.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* llld-parent 配置緩存Redis操作實例 到Spring中
*
* @Author credream
* @Date 2018/8/2
*/
@Configuration
@EnableCaching
public class CacheRedisConfig extends RedisConfig {
@Value("${spring.redis2.database}")
private int dbIndex;
@Value("${spring.redis2.host}")
private String host;
@Value("${spring.redis2.port}")
private int port;
@Value("${spring.redis2.password}")
private String password;
@Value("${spring.redis2.timeout}")
private int timeout;
/**
* 配置redis連接工廠
*
* @return
*/
@Primary
@Bean
public RedisConnectionFactory cacheRedisConnectionFactory() {
return createJedisConnectionFactory(dbIndex, host, port, password, timeout);
}
/**
* 配置redisTemplate 注入方式使用@Resource(name="") 方式注入
*
* @return
*/
@Primary
@Bean(name = "cacheRedisTemplate")
public StringRedisTemplate cacheRedisTemplate() {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(cacheRedisConnectionFactory());
setSerializer(template);
template.afterPropertiesSet();
return template;
}
}
6.爲了方便創建工具類:
CacheSosUtils
package cn.gov.credream.scsupport.util;
import cn.gov.credream.sccommon.core.ConstantKey;
import cn.gov.credream.sccommon.core.Result;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 描述: 操作redis 工具類
* author: credream
* Date: 2018/09/19 15:01
*/
@Component
public class CacheSosUtils {
@Resource(name="cacheRedisTemplate")
private StringRedisTemplate redisTemplate;
private static CacheSosUtils cacheUtils;
private static final Logger logger = LoggerFactory.getLogger(CacheSosUtils.class);
@PostConstruct
public void init() {
cacheUtils = this;
cacheUtils.redisTemplate = this.redisTemplate;
}
/**
* 獲取所有登錄的用戶
*
* @return
*/
public static Integer getOnlineUsers() {
Integer userCount = 0;
userCount = cacheUtils.redisTemplate.keys("*").size();
return userCount;
}
/**
* 將數據存入緩存
*
* @param key
* @param val
* @return
*/
public static void saveString(String key, String val) {
ValueOperations<String, String> vo = cacheUtils.redisTemplate.opsForValue();
vo.set(key, val);
}
/**
* 將數據存入緩存的集合中
*
* @param key
* @param val
* @return
*/
public static void saveToSet(String key, String val) {
SetOperations<String, String> so = cacheUtils.redisTemplate.opsForSet();
so.add(key, val);
}
/**
* key 緩存Key
*
* @param key
* @return
*/
public static String getFromSet(String key) {
return cacheUtils.redisTemplate.opsForSet().pop(key);
}
/**
* 將 key的值保存爲 value ,當且僅當 key 不存在。 若給定的 key 已經存在,則 SETNX 不做任何動作。 SETNX 是『SET if
* Not eXists』(如果不存在,則 SET)的簡寫。 <br>
* 保存成功,返回 true <br>
* 保存失敗,返回 false
*/
public static boolean saveNX(String key, String val) {
/** 設置成功,返回 1 設置失敗,返回 0 **/
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.setNX(key.getBytes(), val.getBytes());
});
}
/**
* 將 key的值保存爲 value ,當且僅當 key 不存在。 若給定的 key 已經存在,則 SETNX 不做任何動作。 SETNX 是『SET if
* Not eXists』(如果不存在,則 SET)的簡寫。 <br>
* 保存成功,返回 true <br>
* 保存失敗,返回 false
*
* @param key
* @param val
* @param expire 超時時間
* @return 保存成功,返回 true 否則返回 false
*/
public static boolean saveNX(String key, String val, int expire) {
boolean ret = saveNX(key, val);
if (ret) {
cacheUtils.redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return ret;
}
/**
* 將數據存入緩存(並設置失效時間)
*
* @param key
* @param val
* @param seconds
* @return
*/
public static void saveString(String key, String val, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, val, seconds, TimeUnit.SECONDS);
}
/**
* 將自增變量存入緩存
*/
public static void saveSeq(String key, long seqNo) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, seqNo);
}
/**
* 將遞增浮點數存入緩存
*/
public static void saveFloat(String key, float data) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, data);
}
/**
* 保存複雜類型數據到緩存
*
* @param key
* @param obj
* @return
*/
public static void saveBean(String key, Object obj) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj));
}
/**
* 保存複雜類型數據到緩存(並設置失效時間)
*
* @param key
* @param obj
* @param seconds
*/
public static void saveBean(String key, Object obj, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj), seconds, TimeUnit.SECONDS);
}
/**
* 存到指定的隊列中
*
* @param key
* @param val
* @param size
*/
public static void saveToQueue(String key, String val, long size) {
ListOperations<String, String> lo = cacheUtils.redisTemplate.opsForList();
if (size > 0 && lo.size(key) >= size) {
lo.rightPop(key);
}
lo.leftPush(key, val);
}
/**
* 保存到hash集合中
*
* @param hName 集合名
* @param key
* @param value
*/
public static void hashSet(String hName, String key, String value) {
cacheUtils.redisTemplate.opsForHash().put(hName, key, value);
}
/**
* 根據key獲取所以值
*
* @param key
* @return
*/
public static Map<Object, Object> hgetAll(String key) {
return cacheUtils.redisTemplate.opsForHash().entries(key);
}
/**
* 保存到hash集合中
*
* @param <T>
* @param hName 集合名
* @param key
* @param t
*/
public static <T> void hashSet(String hName, String key, T t) {
hashSet(hName, key, JSON.toJSONString(t));
}
/**
* 取得複雜JSON數據
*
* @param key
* @param clazz
* @param clazz
* @return
*/
public static <T> T getBean(String key, Class<T> clazz) {
String value = cacheUtils.redisTemplate.opsForValue().get(key);
if (value == null) {
return null;
}
return JSON.parseObject(value, clazz);
}
/**
* 從緩存中取得字符串數據
*
* @param key
* @return 數據
*/
public static String getString(String key) {
cacheUtils.redisTemplate.opsForValue().get(key);
return cacheUtils.redisTemplate.opsForValue().get(key);
}
/**
* 從指定隊列裏取得數據
*
* @param key
* @param size
* @return
*/
public static List<String> getFromQueue(String key, long size) {
boolean flag = cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.exists(key.getBytes());
});
if (flag) {
return new ArrayList<>();
}
ListOperations<String, String> lo = cacheUtils.redisTemplate.opsForList();
if (size > 0) {
return lo.range(key, 0, size - 1);
} else {
return lo.range(key, 0, lo.size(key) - 1);
}
}
/**
* 從指定隊列裏取得數據
*
* @param key
* @return
*/
public static String popQueue(String key) {
return cacheUtils.redisTemplate.opsForList().rightPop(key);
}
/**
* 取得序列值的下一個
*
* @param key
* @return
*/
public static Long getSeqNext(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incr(key.getBytes());
});
}
/**
* 取得序列值的下一個
*
* @param key
* @return
*/
public static Long getSeqNext(String key, long value) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incrBy(key.getBytes(), value);
});
}
/**
* 將序列值回退一個
*
* @param key
* @return
*/
public static void getSeqBack(String key) {
cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> connection.decr(key.getBytes()));
}
/**
* 從hash集合裏取得
*
* @param hName
* @param key
* @return
*/
public static Object hashGet(String hName, String key) {
return cacheUtils.redisTemplate.opsForHash().get(hName, key);
}
public static <T> T hashGet(String hName, String key, Class<T> clazz) {
return JSON.parseObject((String) hashGet(hName, key), clazz);
}
/**
* 增加浮點數的值
*
* @param key
* @return
*/
public static Double incrFloat(String key, double incrBy) {
return cacheUtils.redisTemplate.execute((RedisCallback<Double>) connection -> {
return connection.incrBy(key.getBytes(), incrBy);
});
}
/**
* 判斷是否緩存了數據
*
* @param key 數據KEY
* @return 判斷是否緩存了
*/
public static boolean isCached(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.exists(key.getBytes());
});
}
/**
* 判斷hash集合中是否緩存了數據
*
* @param hName
* @param key 數據KEY
* @return 判斷是否緩存了
*/
public static boolean hashCached(String hName, String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.hExists(key.getBytes(), key.getBytes());
});
}
/**
* 判斷是否緩存在指定的集合中
*
* @param key 數據KEY
* @param val 數據
* @return 判斷是否緩存了
*/
public static boolean isMember(String key, String val) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.sIsMember(key.getBytes(), val.getBytes());
});
}
/**
* 從緩存中刪除數據
*
* @param key
* @return
*/
public static void delKey(String key) {
cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> connection.del(key.getBytes()));
}
/**
* 設置超時時間
*
* @param key
* @param seconds
*/
public static void expire(String key, int seconds) {
cacheUtils.redisTemplate
.execute((RedisCallback<Boolean>) connection -> connection.expire(key.getBytes(), seconds));
}
/**
* 列出set中所有成員
*
* @param setName set名
* @return
*/
public static Set<Object> listSet(String setName) {
return cacheUtils.redisTemplate.opsForHash().keys(setName);
}
/**
* 向set中追加一個值
*
* @param setName set名
* @param value
*/
public static void setSave(String setName, String value) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.sAdd(setName.getBytes(), value.getBytes()));
}
/**
* 利用redis實現分佈式鎖,防止集羣環境下 schedule定時任務重複執行的情況
* @param key
* @param value
* @return
*/
public static boolean setScheduler(final String key, String value) {
boolean result = false;
synchronized (cacheUtils){
try {
ValueOperations<String, String> operations = cacheUtils.redisTemplate.opsForValue();
return operations.setIfAbsent(key, value);
} catch (Exception e) {
logger.error("定時器鎖設定失敗,失敗原因:",e);
}
return result;
}
}
/**
* 刪除對應的key
* @param key
*/
public static void remove(String key){
cacheUtils.redisTemplate.delete(key);
}
/**
* 逆序列出sorted set包括分數的set列表
*
* @param key set名
* @param start 開始位置
* @param end 結束位置
* @return 列表
*/
public static Set<Tuple> listSortedsetRev(String key, int start, int end) {
return cacheUtils.redisTemplate.execute((RedisCallback<Set<Tuple>>) connection -> {
return connection.zRevRangeWithScores(key.getBytes(), start, end);
});
}
/**
* 逆序取得sorted sort排名
*
* @param key set名
* @param member 成員名
* @return 排名
*/
public static Long getRankRev(String key, String member) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.zRevRank(key.getBytes(), member.getBytes());
});
}
/**
* 根據成員名取得sorted sort分數
*
* @param key set名
* @param member 成員名
* @return 分數
*/
public static Double getMemberScore(String key, String member) {
return cacheUtils.redisTemplate.execute((RedisCallback<Double>) connection -> {
return connection.zScore(key.getBytes(), member.getBytes());
});
}
/**
* 向sorted set中追加一個值
*
* @param key set名
* @param score 分數
* @param member 成員名稱
*/
public static void saveToSortedset(String key, Double score, String member) {
cacheUtils.redisTemplate.execute(
(RedisCallback<Boolean>) connection -> connection.zAdd(key.getBytes(), score, member.getBytes()));
}
/**
* 從sorted set刪除一個值
*
* @param key set名
* @param member 成員名稱
*/
public static void delFromSortedset(String key, String member) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.zRem(key.getBytes(), member.getBytes()));
}
/**
* 從hash map中取得複雜JSON數據
*
* @param key
* @param field
* @param clazz
*/
public static <T> T getBeanFromMap(String key, String field, Class<T> clazz) {
byte[] input = cacheUtils.redisTemplate.execute((RedisCallback<byte[]>) connection -> {
return connection.hGet(key.getBytes(), field.getBytes());
});
return JSON.parseObject(input, clazz, Feature.AutoCloseSource);
}
/**
* 從hashmap中刪除一個值
*
* @param key map名
* @param field 成員名稱
*/
public static void delFromMap(String key, String field) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.hDel(key.getBytes(), field.getBytes()));
}
/**
* @param key
* @return
* @Description: 根據key增長 ,計數器
* @author clg
* @date 2016年6月30日 下午2:37:52
*/
public static long incr(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incr(key.getBytes());
});
}
/**
* 根據key獲取當前計數結果
*
* @param key
* @return
*/
public static String getCount(String key) {
return cacheUtils.redisTemplate.opsForValue().get(key);
}
/**
* 將所有指定的值插入到存於 key 的列表的頭部。如果 key 不存在,那麼在進行 push 操作前會創建一個空列表
*
* @param <T>
* @param key
* @param value
* @return
*/
public static <T> Long lpush(String key, T value) {
return cacheUtils.redisTemplate.opsForList().leftPush(key, JSON.toJSONString(value));
}
/**
* 只有當 key 已經存在並且存着一個 list 的時候,在這個 key 下面的 list 的頭部插入 value。 與 LPUSH 相反,當 key
* 不存在的時候不會進行任何操作
*
* @param key
* @param value
* @return
*/
public static <T> Long lpushx(String key, T value) {
return cacheUtils.redisTemplate.opsForList().leftPushIfPresent(key, JSON.toJSONString(value));
}
/**
* 返回存儲在 key 裏的list的長度。 如果 key 不存在,那麼就被看作是空list,並且返回長度爲 0
*
* @param key
* @return
*/
public static Long llen(String key) {
return cacheUtils.redisTemplate.opsForList().size(key);
}
/**
* 返回存儲在 key 的列表裏指定範圍內的元素。 start 和 end
* 偏移量都是基於0的下標,即list的第一個元素下標是0(list的表頭),第二個元素下標是1,以此類推
*
* @param key
* @return
*/
public static List<String> lrange(String key, long start, long end) {
return cacheUtils.redisTemplate.opsForList().range(key, start, end);
}
/**
* 移除並且返回 key 對應的 list 的第一個元素
*
* @param key
* @return
*/
public static String lpop(String key) {
return cacheUtils.redisTemplate.opsForList().leftPop(key);
}
/**
* 保存到hash集合中 只在 key 指定的哈希集中不存在指定的字段時,設置字段的值。如果 key 指定的哈希集不存在,會創建一個新的哈希集並與 key
* 關聯。如果字段已存在,該操作無效果。
*
* @param hName 集合名
* @param key
* @param value
*/
public static void hsetnx(String hName, String key, String value) {
cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.hSetNX(key.getBytes(),
key.getBytes(), value.getBytes()));
}
/**
* 保存到hash集合中 只在 key 指定的哈希集中不存在指定的字段時,設置字段的值。如果 key 指定的哈希集不存在,會創建一個新的哈希集並與 key
* 關聯。如果字段已存在,該操作無效果。
*
* @param hName 集合名
* @param key
* @param t
* @param <T>
*/
public static <T> void hsetnx(String hName, String key, T t) {
hsetnx(hName, key, JSON.toJSONString(t));
}
/**
* 驗證token是否有效
*
* @param token
* @return 驗證結果
*/
private static Result tokenVerify(String token) {
Result result = new Result();
if (token != null && !token.equals("")) {
try {
Jwts.parser()
.setSigningKey(ConstantKey.SIGNING_KEY)
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getSubject();
result.setCode("200");
result.setSuccess(true);
return result;
} catch (ExpiredJwtException e) {
logger.error("Token已過期: {} " + e);
result.setSuccess(false);
result.setCode("401");
result.setMessage("請求超時");
return result;
} catch (UnsupportedJwtException e) {
logger.error("Token格式錯誤: {} " + e);
result.setSuccess(false);
result.setCode("413");
result.setMessage("不被支持的令牌");
return result;
} catch (MalformedJwtException e) {
logger.error("Token沒有被正確構造: {} " + e);
result.setSuccess(false);
result.setCode("414");
result.setMessage("令牌格式錯誤");
return result;
} catch (SignatureException e) {
logger.error("簽名失敗: {} " + e);
result.setSuccess(false);
result.setCode("415");
result.setMessage("令牌簽名失敗");
return result;
} catch (IllegalArgumentException e) {
logger.error("非法參數異常: {} " + e);
result.setSuccess(false);
result.setCode("416");
result.setMessage("錯誤的參數");
return result;
}
} else {
result.setSuccess(false);
result.setCode("417");
result.setMessage("沒有接收到令牌");
return result;
}
}
}
7.爲了方便創建第二個數據源使用的
package cn.gov.credream.scsupport.util;
import cn.gov.credream.sccommon.core.ConstantKey;
import cn.gov.credream.sccommon.core.Result;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 描述: 操作redis 工具類
* author: credream
* Date: 2018/09/19 15:01
*/
@Component
public class CacheUtils {
@Resource(name="defaultRedisTemplate")
private StringRedisTemplate redisTemplate;
private static CacheUtils cacheUtils;
private static final Logger logger = LoggerFactory.getLogger(CacheUtils.class);
@PostConstruct
public void init() {
cacheUtils = this;
cacheUtils.redisTemplate = this.redisTemplate;
}
/**
* 獲取所有登錄的用戶
*
* @return
*/
public static Integer getOnlineUsers() {
Integer userCount = 0;
userCount = cacheUtils.redisTemplate.keys("*").size();
return userCount;
}
/**
* 將數據存入緩存
*
* @param key
* @param val
* @return
*/
public static void saveString(String key, String val) {
ValueOperations<String, String> vo = cacheUtils.redisTemplate.opsForValue();
vo.set(key, val);
}
/**
* 將數據存入緩存的集合中
*
* @param key
* @param val
* @return
*/
public static void saveToSet(String key, String val) {
SetOperations<String, String> so = cacheUtils.redisTemplate.opsForSet();
so.add(key, val);
}
/**
* key 緩存Key
*
* @param key
* @return
*/
public static String getFromSet(String key) {
return cacheUtils.redisTemplate.opsForSet().pop(key);
}
/**
* 將 key的值保存爲 value ,當且僅當 key 不存在。 若給定的 key 已經存在,則 SETNX 不做任何動作。 SETNX 是『SET if
* Not eXists』(如果不存在,則 SET)的簡寫。 <br>
* 保存成功,返回 true <br>
* 保存失敗,返回 false
*/
public static boolean saveNX(String key, String val) {
/** 設置成功,返回 1 設置失敗,返回 0 **/
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.setNX(key.getBytes(), val.getBytes());
});
}
/**
* 將 key的值保存爲 value ,當且僅當 key 不存在。 若給定的 key 已經存在,則 SETNX 不做任何動作。 SETNX 是『SET if
* Not eXists』(如果不存在,則 SET)的簡寫。 <br>
* 保存成功,返回 true <br>
* 保存失敗,返回 false
*
* @param key
* @param val
* @param expire 超時時間
* @return 保存成功,返回 true 否則返回 false
*/
public static boolean saveNX(String key, String val, int expire) {
boolean ret = saveNX(key, val);
if (ret) {
cacheUtils.redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return ret;
}
/**
* 將數據存入緩存(並設置失效時間)
*
* @param key
* @param val
* @param seconds
* @return
*/
public static void saveString(String key, String val, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, val, seconds, TimeUnit.SECONDS);
}
/**
* 將自增變量存入緩存
*/
public static void saveSeq(String key, long seqNo) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, seqNo);
}
/**
* 將遞增浮點數存入緩存
*/
public static void saveFloat(String key, float data) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, data);
}
/**
* 保存複雜類型數據到緩存
*
* @param key
* @param obj
* @return
*/
public static void saveBean(String key, Object obj) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj));
}
/**
* 保存複雜類型數據到緩存(並設置失效時間)
*
* @param key
* @param obj
* @param seconds
*/
public static void saveBean(String key, Object obj, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj), seconds, TimeUnit.SECONDS);
}
/**
* 存到指定的隊列中
*
* @param key
* @param val
* @param size
*/
public static void saveToQueue(String key, String val, long size) {
ListOperations<String, String> lo = cacheUtils.redisTemplate.opsForList();
if (size > 0 && lo.size(key) >= size) {
lo.rightPop(key);
}
lo.leftPush(key, val);
}
/**
* 保存到hash集合中
*
* @param hName 集合名
* @param key
* @param value
*/
public static void hashSet(String hName, String key, String value) {
cacheUtils.redisTemplate.opsForHash().put(hName, key, value);
}
/**
* 根據key獲取所以值
*
* @param key
* @return
*/
public static Map<Object, Object> hgetAll(String key) {
return cacheUtils.redisTemplate.opsForHash().entries(key);
}
/**
* 保存到hash集合中
*
* @param <T>
* @param hName 集合名
* @param key
* @param t
*/
public static <T> void hashSet(String hName, String key, T t) {
hashSet(hName, key, JSON.toJSONString(t));
}
/**
* 取得複雜JSON數據
*
* @param key
* @param clazz
* @param clazz
* @return
*/
public static <T> T getBean(String key, Class<T> clazz) {
String value = cacheUtils.redisTemplate.opsForValue().get(key);
if (value == null) {
return null;
}
return JSON.parseObject(value, clazz);
}
/**
* 從緩存中取得字符串數據
*
* @param key
* @return 數據
*/
public static String getString(String key) {
cacheUtils.redisTemplate.opsForValue().get(key);
return cacheUtils.redisTemplate.opsForValue().get(key);
}
/**
* 從指定隊列裏取得數據
*
* @param key
* @param size
* @return
*/
public static List<String> getFromQueue(String key, long size) {
boolean flag = cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.exists(key.getBytes());
});
if (flag) {
return new ArrayList<>();
}
ListOperations<String, String> lo = cacheUtils.redisTemplate.opsForList();
if (size > 0) {
return lo.range(key, 0, size - 1);
} else {
return lo.range(key, 0, lo.size(key) - 1);
}
}
/**
* 從指定隊列裏取得數據
*
* @param key
* @return
*/
public static String popQueue(String key) {
return cacheUtils.redisTemplate.opsForList().rightPop(key);
}
/**
* 取得序列值的下一個
*
* @param key
* @return
*/
public static Long getSeqNext(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incr(key.getBytes());
});
}
/**
* 取得序列值的下一個
*
* @param key
* @return
*/
public static Long getSeqNext(String key, long value) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incrBy(key.getBytes(), value);
});
}
/**
* 將序列值回退一個
*
* @param key
* @return
*/
public static void getSeqBack(String key) {
cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> connection.decr(key.getBytes()));
}
/**
* 從hash集合裏取得
*
* @param hName
* @param key
* @return
*/
public static Object hashGet(String hName, String key) {
return cacheUtils.redisTemplate.opsForHash().get(hName, key);
}
public static <T> T hashGet(String hName, String key, Class<T> clazz) {
return JSON.parseObject((String) hashGet(hName, key), clazz);
}
/**
* 增加浮點數的值
*
* @param key
* @return
*/
public static Double incrFloat(String key, double incrBy) {
return cacheUtils.redisTemplate.execute((RedisCallback<Double>) connection -> {
return connection.incrBy(key.getBytes(), incrBy);
});
}
/**
* 判斷是否緩存了數據
*
* @param key 數據KEY
* @return 判斷是否緩存了
*/
public static boolean isCached(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.exists(key.getBytes());
});
}
/**
* 判斷hash集合中是否緩存了數據
*
* @param hName
* @param key 數據KEY
* @return 判斷是否緩存了
*/
public static boolean hashCached(String hName, String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.hExists(key.getBytes(), key.getBytes());
});
}
/**
* 判斷是否緩存在指定的集合中
*
* @param key 數據KEY
* @param val 數據
* @return 判斷是否緩存了
*/
public static boolean isMember(String key, String val) {
return cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> {
return connection.sIsMember(key.getBytes(), val.getBytes());
});
}
/**
* 從緩存中刪除數據
*
* @param key
* @return
*/
public static void delKey(String key) {
cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> connection.del(key.getBytes()));
}
/**
* 設置超時時間
*
* @param key
* @param seconds
*/
public static void expire(String key, int seconds) {
cacheUtils.redisTemplate
.execute((RedisCallback<Boolean>) connection -> connection.expire(key.getBytes(), seconds));
}
/**
* 列出set中所有成員
*
* @param setName set名
* @return
*/
public static Set<Object> listSet(String setName) {
return cacheUtils.redisTemplate.opsForHash().keys(setName);
}
/**
* 向set中追加一個值
*
* @param setName set名
* @param value
*/
public static void setSave(String setName, String value) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.sAdd(setName.getBytes(), value.getBytes()));
}
/**
* 利用redis實現分佈式鎖,防止集羣環境下 schedule定時任務重複執行的情況
* @param key
* @param value
* @return
*/
public static boolean setScheduler(final String key, String value) {
boolean result = false;
synchronized (cacheUtils){
try {
ValueOperations<String, String> operations = cacheUtils.redisTemplate.opsForValue();
return operations.setIfAbsent(key, value);
} catch (Exception e) {
logger.error("定時器鎖設定失敗,失敗原因:",e);
}
return result;
}
}
/**
* 刪除對應的key
* @param key
*/
public static void remove(String key){
cacheUtils.redisTemplate.delete(key);
}
/**
* 逆序列出sorted set包括分數的set列表
*
* @param key set名
* @param start 開始位置
* @param end 結束位置
* @return 列表
*/
public static Set<Tuple> listSortedsetRev(String key, int start, int end) {
return cacheUtils.redisTemplate.execute((RedisCallback<Set<Tuple>>) connection -> {
return connection.zRevRangeWithScores(key.getBytes(), start, end);
});
}
/**
* 逆序取得sorted sort排名
*
* @param key set名
* @param member 成員名
* @return 排名
*/
public static Long getRankRev(String key, String member) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.zRevRank(key.getBytes(), member.getBytes());
});
}
/**
* 根據成員名取得sorted sort分數
*
* @param key set名
* @param member 成員名
* @return 分數
*/
public static Double getMemberScore(String key, String member) {
return cacheUtils.redisTemplate.execute((RedisCallback<Double>) connection -> {
return connection.zScore(key.getBytes(), member.getBytes());
});
}
/**
* 向sorted set中追加一個值
*
* @param key set名
* @param score 分數
* @param member 成員名稱
*/
public static void saveToSortedset(String key, Double score, String member) {
cacheUtils.redisTemplate.execute(
(RedisCallback<Boolean>) connection -> connection.zAdd(key.getBytes(), score, member.getBytes()));
}
/**
* 從sorted set刪除一個值
*
* @param key set名
* @param member 成員名稱
*/
public static void delFromSortedset(String key, String member) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.zRem(key.getBytes(), member.getBytes()));
}
/**
* 從hash map中取得複雜JSON數據
*
* @param key
* @param field
* @param clazz
*/
public static <T> T getBeanFromMap(String key, String field, Class<T> clazz) {
byte[] input = cacheUtils.redisTemplate.execute((RedisCallback<byte[]>) connection -> {
return connection.hGet(key.getBytes(), field.getBytes());
});
return JSON.parseObject(input, clazz, Feature.AutoCloseSource);
}
/**
* 從hashmap中刪除一個值
*
* @param key map名
* @param field 成員名稱
*/
public static void delFromMap(String key, String field) {
cacheUtils.redisTemplate
.execute((RedisCallback<Long>) connection -> connection.hDel(key.getBytes(), field.getBytes()));
}
/**
* @param key
* @return
* @Description: 根據key增長 ,計數器
* @author clg
* @date 2016年6月30日 下午2:37:52
*/
public static long incr(String key) {
return cacheUtils.redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.incr(key.getBytes());
});
}
/**
* 根據key獲取當前計數結果
*
* @param key
* @return
*/
public static String getCount(String key) {
return cacheUtils.redisTemplate.opsForValue().get(key);
}
/**
* 將所有指定的值插入到存於 key 的列表的頭部。如果 key 不存在,那麼在進行 push 操作前會創建一個空列表
*
* @param <T>
* @param key
* @param value
* @return
*/
public static <T> Long lpush(String key, T value) {
return cacheUtils.redisTemplate.opsForList().leftPush(key, JSON.toJSONString(value));
}
/**
* 只有當 key 已經存在並且存着一個 list 的時候,在這個 key 下面的 list 的頭部插入 value。 與 LPUSH 相反,當 key
* 不存在的時候不會進行任何操作
*
* @param key
* @param value
* @return
*/
public static <T> Long lpushx(String key, T value) {
return cacheUtils.redisTemplate.opsForList().leftPushIfPresent(key, JSON.toJSONString(value));
}
/**
* 返回存儲在 key 裏的list的長度。 如果 key 不存在,那麼就被看作是空list,並且返回長度爲 0
*
* @param key
* @return
*/
public static Long llen(String key) {
return cacheUtils.redisTemplate.opsForList().size(key);
}
/**
* 返回存儲在 key 的列表裏指定範圍內的元素。 start 和 end
* 偏移量都是基於0的下標,即list的第一個元素下標是0(list的表頭),第二個元素下標是1,以此類推
*
* @param key
* @return
*/
public static List<String> lrange(String key, long start, long end) {
return cacheUtils.redisTemplate.opsForList().range(key, start, end);
}
/**
* 移除並且返回 key 對應的 list 的第一個元素
*
* @param key
* @return
*/
public static String lpop(String key) {
return cacheUtils.redisTemplate.opsForList().leftPop(key);
}
/**
* 保存到hash集合中 只在 key 指定的哈希集中不存在指定的字段時,設置字段的值。如果 key 指定的哈希集不存在,會創建一個新的哈希集並與 key
* 關聯。如果字段已存在,該操作無效果。
*
* @param hName 集合名
* @param key
* @param value
*/
public static void hsetnx(String hName, String key, String value) {
cacheUtils.redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.hSetNX(key.getBytes(),
key.getBytes(), value.getBytes()));
}
/**
* 保存到hash集合中 只在 key 指定的哈希集中不存在指定的字段時,設置字段的值。如果 key 指定的哈希集不存在,會創建一個新的哈希集並與 key
* 關聯。如果字段已存在,該操作無效果。
*
* @param hName 集合名
* @param key
* @param t
* @param <T>
*/
public static <T> void hsetnx(String hName, String key, T t) {
hsetnx(hName, key, JSON.toJSONString(t));
}
/**
* 驗證token是否有效
*
* @param token
* @return 驗證結果
*/
private static Result tokenVerify(String token) {
Result result = new Result();
if (token != null && !token.equals("")) {
try {
Jwts.parser()
.setSigningKey(ConstantKey.SIGNING_KEY)
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getSubject();
result.setCode("200");
result.setSuccess(true);
return result;
} catch (ExpiredJwtException e) {
logger.error("Token已過期: {} " + e);
result.setSuccess(false);
result.setCode("401");
result.setMessage("請求超時");
return result;
} catch (UnsupportedJwtException e) {
logger.error("Token格式錯誤: {} " + e);
result.setSuccess(false);
result.setCode("413");
result.setMessage("不被支持的令牌");
return result;
} catch (MalformedJwtException e) {
logger.error("Token沒有被正確構造: {} " + e);
result.setSuccess(false);
result.setCode("414");
result.setMessage("令牌格式錯誤");
return result;
} catch (SignatureException e) {
logger.error("簽名失敗: {} " + e);
result.setSuccess(false);
result.setCode("415");
result.setMessage("令牌簽名失敗");
return result;
} catch (IllegalArgumentException e) {
logger.error("非法參數異常: {} " + e);
result.setSuccess(false);
result.setCode("416");
result.setMessage("錯誤的參數");
return result;
}
} else {
result.setSuccess(false);
result.setCode("417");
result.setMessage("沒有接收到令牌");
return result;
}
}
}
8.新建測試類測試:
package cn.gov.credream.scsupport;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ScSupportApplicationTests {
@Test
public void contextLoads() {
}
@Resource(name = "defaultRedisTemplate")
private StringRedisTemplate redisTemplate;
@Resource(name = "cacheRedisTemplate")
private StringRedisTemplate redisTemplate1;
@Test
public void stringRedisTest() {
redisTemplate.opsForValue().set("slzzzz", "111111");
redisTemplate1.opsForValue().set("slzzzz", "222222");
}
@Test
public void objectRedisTest() {
redisTemplate.opsForValue().set("person", "777777777777777");
redisTemplate1.opsForValue().set("person", "1234564564");
}
}
9.注意,如果測試的時候報錯:
java.lang.NoSuchMethodError: org.springframework.util.Assert.state(ZLjava/util/function/Supplier;)V
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:379) at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:312) at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:265) at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:108) at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:82) at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:139) at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:124) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:151) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:142) at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104) at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33) at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
需要把:
<!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-test</artifactId>--> <!--<version>RELEASE</version>--> <!--</dependency>-->
刪除然後重新啓動就可以了.