一、添加依赖jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
二、新建一个RedisConfig.java类
pakage com.dm.krystal.redis;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.cache.CacheManager;
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.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching//开启注解
public class RedisConfig extends CachingConfigurerSupport {
@Bean
@Primary
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
// set key serializer
StringRedisSerializer serializer = new StringRedisSerializer();
// 设置key序列化类,否则key前面会多了一些乱码
template.setKeySerializer(serializer);
template.setHashKeySerializer(serializer);
// fastjson serializer
GenericFastJsonRedisSerializer fastSerializer = new GenericFastJsonRedisSerializer();
template.setValueSerializer(fastSerializer);
template.setHashValueSerializer(fastSerializer);
// 如果 KeySerializer 或者 ValueSerializer 没有配置,则对应的 KeySerializer、ValueSerializer 才使用这个 Serializer
template.setDefaultSerializer(fastSerializer);
LettuceConnectionFactory factory = (LettuceConnectionFactory) redisConnectionFactory;
// factory
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
@Bean
public RedisFactory redisFactory(RedisConnectionFactory redisConnectionFactory) {
RedisFactory redisFactory = new RedisFactory();
redisFactory.setRedisTemplate(redisTemplate(redisConnectionFactory));
return redisFactory;
}
}
三、新建一个用于保存数据的RedisFactory.java工具类
package com.dm.krystal.redis;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class RedisFactory {
private String mutexDefaultExt = "_mutex";
private long mutextDefaultExpireTime = 60l;
private RedisTemplate<String, Object> redisTemplate;
public RedisTemplate<String, Object> getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(
RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void saveByStr(final String key, final String value) {
redisTemplate.execute(new RedisCallback() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
connection.set(
redisSerializer.serialize(
key),
redisSerializer.serialize(
value));
return null;
}
});
}
public String getByStr(final String key) {
return (String) (redisTemplate.execute(new RedisCallback() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
byte[] keys = redisSerializer.serialize(key);
if (connection.exists(keys)) {
byte[] values = connection.get(keys);
String retval = redisSerializer.deserialize(values);
return retval;
}
return null;
}
}));
}
public String getSetByStr(final String key, final String value) {
return (String) (redisTemplate.execute(new RedisCallback() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
byte[] keys = redisSerializer.serialize(key);
if (connection.exists(keys)) {
byte[] values = redisSerializer.serialize(value);
byte[] results = connection.getSet(keys, values);
String retval = redisSerializer.deserialize(results);
return retval;
}
return null;
}
}));
}
public void saveByStr(final String key, final long timer, final String value) {
redisTemplate.execute(new RedisCallback() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
connection.set(
redisSerializer.serialize(
key),
redisSerializer.serialize(
value));
if (timer != -1) {
byte[] keys = redisSerializer.serialize(key);
connection.expire(keys, timer);
}
return null;
}
});
}
public <T> void saveByObj(final String key, final T value) {
redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer());
connection.set(
redisTemplate.getStringSerializer().serialize(key),
redisSerializer.serialize(value));
return null;
}
});
}
public <T> T getByObj(final String key) {
return (T) (redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(key);
if (connection.exists(keys)) {
byte[] values = connection.get(keys);
RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer());
T retval = redisSerializer.deserialize(values);
return retval;
}
return null;
}
}));
}
public <T> T getSetByObj(final String key, final T value) {
return (T) (redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(key);
if (connection.exists(keys)) {
RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer());
byte[] values = redisSerializer.serialize(value);
byte[] results = connection.getSet(keys, values);
T retval = redisSerializer.deserialize(results);
return retval;
}
return null;
}
}));
}
public <T> void saveByObj(final String key, final long timer, final T value) {
redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer());
connection.set(
redisTemplate.getStringSerializer().serialize(key),
redisSerializer.serialize(value));
if (timer != -1) {
byte[] keys = redisTemplate.getStringSerializer().serialize(key);
connection.expire(keys, timer);
}
return null;
}
});
}
public Long delete(final String key) {
return (Long) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.del(
redisTemplate.getStringSerializer().serialize(
key));
}
}));
}
public void deleteByPrex(final String name) {
List<String> allKeys = getAllKeyByName(name);
allKeys.forEach((key) -> {
delete(key);
});
}
public List<String> getAllKeyByName(final String name) {
Set<byte[]> keyBytes = (Set<byte[]>) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(name + "*");
return connection.keys(keys);
}
}));
if (keyBytes != null && keyBytes.size() > 0) {
List<String> resultList = new ArrayList<String>();
for (Iterator<byte[]> it = keyBytes.iterator(); it.hasNext(); ) {
String keyName = new String(it.next());
resultList.add(keyName);
}
return resultList;
} else {
return null;
}
}
public boolean setNX(final String key) {
return this.setNX(key, "1");
}
public boolean setNX(final String key, final String value) {
return this.setNX(key, -1, value);
}
public boolean setNX(final String key, final long timer, final String value) {
return (boolean) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
boolean nxFlag = connection.setNX(
redisTemplate.getStringSerializer().serialize(
key),
redisTemplate.getStringSerializer().serialize(
value));
if (timer != -1) {
byte[] keys = redisTemplate.getStringSerializer().serialize(key);
connection.expire(keys, timer);
}
return nxFlag;
}
}));
}
public boolean mutexKey(String key, long validTimer, long mutexTimeout) {
boolean mutexFlag = false;
try {
String newKey = key + this.mutexDefaultExt;
if (mutexTimeout == -1) {
//无限时等待
while (true) {
long value = System.currentTimeMillis() + validTimer + 1;
boolean acquired = this.setNX(newKey, validTimer, String.valueOf(value));
if (acquired) {
mutexFlag = true;
break;
} else {
long oldValue = Long.valueOf(this.getByStr(newKey));
//超时
if (oldValue < System.currentTimeMillis()) {
long lastValue = Long.valueOf(getSetByStr(newKey, String.valueOf(value)));
if (lastValue == oldValue) {
// 本线程获取锁成功
mutexFlag = true;
break;
} else {
//已被其他线程抢占
mutexFlag = false;
}
} else {
mutexFlag = false;
}
}
Thread.sleep(300);
}
} else {
//限时等待
long curnano = System.nanoTime();
long nanoMutexTimeout = mutexTimeout * 1000l * 1000l * 1000l;
do {
long value = System.currentTimeMillis() + validTimer + 1;
boolean acquired = this.setNX(newKey, validTimer, String.valueOf(value));
if (acquired) {
mutexFlag = true;
break;
} else {
long oldValue = Long.valueOf(this.getByStr(newKey));
//超时
if (oldValue < System.currentTimeMillis()) {
long lastValue = Long.valueOf(getSetByStr(newKey, String.valueOf(value)));
if (lastValue == oldValue) {
// 本线程获取锁成功
mutexFlag = true;
break;
} else {
//已被其他线程抢占
mutexFlag = false;
}
} else {
mutexFlag = false;
}
}
Thread.sleep(300);
} while ((System.nanoTime() - curnano) < nanoMutexTimeout);
}
} catch (Exception ex) {
mutexFlag = false;
}
return mutexFlag;
}
public Long mutexRemove(String key) {
if (key.contains(mutexDefaultExt)) {
return this.delete(key);
} else {
return this.delete(key + mutexDefaultExt);
}
}
public boolean updateLockAndTransactionByStr(final String[] keys, final String[] values) {
try {
return (boolean) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
for (String key : keys) {
if (mutexKey(key, mutextDefaultExpireTime, mutextDefaultExpireTime)) {
return false;
}
}
for (String key : keys) {
connection.watch(redisSerializer.serialize(key + mutexDefaultExt));
}
connection.multi();
for (int i = 0; i < keys.length; i++) {
connection.set(redisSerializer.serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i]));
}
List<Object> results = connection.exec();
if (results == null || results.isEmpty()) {
return false;
} else {
return true;
}
}
}));
} catch (Exception ex) {
return false;
}
}
public boolean updateTransactionByStr(final String[] keys, final String[] values) {
try {
return (boolean) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
for (String key : keys) {
connection.watch(redisSerializer.serialize(key + mutexDefaultExt));
}
connection.multi();
for (int i = 0; i < keys.length; i++) {
connection.set(redisSerializer.serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i]));
}
List<Object> results = connection.exec();
if (results == null || results.isEmpty()) {
return false;
} else {
return true;
}
}
}));
} catch (Exception ex) {
return false;
}
}
public boolean updateLockAndTransactionByObj(final String[] keys, final Object[] values) {
try {
return (boolean) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
for (String key : keys) {
if (mutexKey(key, mutextDefaultExpireTime, mutextDefaultExpireTime)) {
return false;
}
}
for (String key : keys) {
connection.watch(redisTemplate.getStringSerializer().serialize(key + mutexDefaultExt));
}
connection.multi();
for (int i = 0; i < keys.length; i++) {
RedisSerializer redisSerializer = (RedisSerializer) (redisTemplate.getValueSerializer());
connection.set(redisTemplate.getStringSerializer().serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i]));
}
List<Object> results = connection.exec();
if (results == null || results.isEmpty()) {
return false;
} else {
return true;
}
}
}));
} catch (Exception ex) {
return false;
}
}
public boolean updateTransactionByObj(final String[] keys, final Object[] values) {
try {
return (boolean) (redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
for (String key : keys) {
connection.watch(redisTemplate.getStringSerializer().serialize(key + mutexDefaultExt));
}
connection.multi();
for (int i = 0; i < keys.length; i++) {
RedisSerializer redisSerializer = (RedisSerializer) (redisTemplate.getValueSerializer());
connection.set(redisTemplate.getStringSerializer().serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i]));
}
List<Object> results = connection.exec();
if (results == null || results.isEmpty()) {
return false;
} else {
return true;
}
}
}));
} catch (Exception ex) {
return false;
}
}
public boolean extPushQueue(final String queueName, final String queueTitle, final long timeout) {
boolean result = false;
result = (Boolean) redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(queueName);
byte[] values = redisTemplate.getStringSerializer().serialize(queueTitle);
if (connection.lPush(keys, values) > 0) {
if (timeout != -1l) {
connection.expire(keys, timeout);
}
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
});
return result;
}
public boolean extExpireQueue(final String queueName, final long timeout) {
boolean result = false;
result = (Boolean) redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(queueName);
if (timeout != -1l) {
return connection.expire(keys, timeout);
} else {
return true;
}
}
});
return result;
}
public boolean extRemoveQueueMsg(final String queueName, final String msg) {
boolean result = false;
Long back = (Long) redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(queueName);
byte[] msgs = redisTemplate.getStringSerializer().serialize(msg);
return connection.lRem(keys, 0l, msgs);
}
});
if (back.longValue() == 0l) {
result = false;
} else {
result = true;
}
return result;
}
public List<String> extTraversalQueue(final String queueName) {
List<String> result = null;
List<byte[]> valueList = (List<byte[]>) redisTemplate.execute(new RedisCallback<List<byte[]>>() {
@Override
public List<byte[]> doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(queueName);
List<byte[]> valueList = connection.lRange(keys, 0l, -1l);
return valueList;
}
});
if (valueList != null && valueList.size() > 0) {
result = new ArrayList<String>();
for (int i = 0; i < valueList.size(); i++) {
byte[] valBytes = valueList.get(i);
result.add(new String(valBytes));
}
}
return result;
}
public boolean extTraversalQueueMsg(final String queueName, final String msg) {
boolean result = false;
Boolean back = (Boolean) redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keys = redisTemplate.getStringSerializer().serialize(queueName);
List<byte[]> valueList = connection.lRange(keys, 0l, -1l);
Boolean find = Boolean.FALSE;
if (valueList != null && valueList.size() > 0) {
for (int i = 0; i < valueList.size(); i++) {
byte[] valBytes = valueList.get(i);
String matchKey = new String(valBytes);
if (matchKey.equals(msg)) {
find = Boolean.TRUE;
break;
}
}
}
return find;
}
});
if (!back.booleanValue()) {
result = false;
} else {
result = true;
}
return result;
}
public boolean extHMapSave(final String key, final String field, final String value) {
boolean result = false;
Boolean back = Boolean.FALSE;
try {
back = (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection)
throws DataAccessException {
connection.hSet(
redisTemplate.getStringSerializer().serialize(
key),
redisTemplate.getStringSerializer().serialize(
field),
redisTemplate.getStringSerializer().serialize(
value));
return Boolean.TRUE;
}
});
} catch (Exception ex) {
back = Boolean.FALSE;
}
if (!back.booleanValue()) {
result = false;
} else {
result = true;
}
return result;
}
public String extHMapGet(final String key, final String field) {
return redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] valBytes = connection.hGet(
redisTemplate.getStringSerializer().serialize(
key),
redisTemplate.getStringSerializer().serialize(
field));
if (valBytes == null || valBytes.length == 0) {
return null;
} else {
return new String(valBytes);
}
}
});
}
}
四、使用redis做缓存
//redis
@RequestMapping("queryUserList")
public MsgDataBody<List<SysUser>> queryUserList(){
MsgDataBody<List<SysUser>> msgBody = new MsgDataBody<List<SysUser>>();
// MsgBody msgBody=new MsgBody();
msgBody.setCode(Constant.Error.getCode());
msgBody.setMsg("获取数据失败");
SysUser sysUser=new SysUser();
List<SysUser> list =new ArrayList<>();
try{
if(redisFactory.getByObj("data")!=null){
JSONArray jsonArray = JSONArray.fromObject(redisFactory.getByObj("data"));//将json字符串转为json对象
list = (List<SysUser>)JSONArray.toCollection(jsonArray,SysUser.class) ;//将 json 对象转为list 数组
System.out.println("iam cache 111");
}else {
QueryWrapper<SysUser> wrapper = new QueryWrapper<SysUser>();
// wrapper.eq("id","1");
list=iSysUserService.selectList(wrapper);
redisFactory.saveByObj("data",60*15,list);//60.15数据在redis存活的时间
System.out.println("iam query111");
}
msgBody.setData(list);
msgBody.setCode(Constant.Success.getCode());
msgBody.setMsg("获取数据成功");
}catch (RuntimeException e){
msgBody.setCode(Constant.Error.getCode());
}
return msgBody;
}
redis配置:
redis: # Redis数据库索引(默认为0) database: 0 # Redis服务器连接超时(默认为0) timeout: 5000 # Redis服务器地址 host: 127.0.0.1 # Redis服务器连接端口 port: 6379 # Redis服务器连接密码(默认为空) password: jedis: pool: # 连接池最大连接数(使用负值表示没有限制) max-active: 8 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1 # 连接池中的最大空闲连接 maxIdle: 8 # 连接池中的最小空闲连接 min-idle: 0
五、注意(其实这个和主题没啥关系)
上面使用JSONArray.fromObject要引入import net.sf.json.JSONArray, 而不是import com.alibaba.fastjson.JSONArray,idea每次导包时候都是默认引用import com.alibaba.fastjson.JSONArray出问题。