一、引入pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
二、redis配置
package com.neo.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
@Slf4j
public class RedisConfig extends CachingConfigurerSupport{
/**
* redisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置值(value)的序列化采用FastJsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
//自定义缓存管理,包括超时时间
@Bean
@Primary
public RedisCacheManager commonManager(RedisConnectionFactory factory){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.entryTtl(Duration.ofMinutes(60000))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues();
return RedisCacheManager
.builder(factory)
.cacheDefaults(config)
.build();
}
/**
* 自定义键生成规则
*/
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
}
三、service/impl:
package com.neo.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* tll
* 2020/4/2
*/
@Service
@Slf4j
public class RedisServiceImpl implements RedisService {
private static String TOKEN_PREFIX = "safe_interface_%s";
@Autowired
private StringRedisTemplate redisTemplate;
@Qualifier("commonManager")
@Resource
private RedisCacheManager redisCacheManager;
@Override
public boolean lock(String key, String value) {
key = formatKey(key);
if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
//currentValue=A 这两个线程的value都是B 其中一个线程拿到锁
String currentValue = redisTemplate.opsForValue().get(key);
log.info("【Redis Service 】 ,key = {}", key);
log.info("【Redis Service 】 ,value = {}", value);
log.info("【Redis Service 】 ,currentValue = {}", currentValue);
//如果锁过期
if (!StringUtils.isEmpty(currentValue)
&& Long.parseLong(currentValue) < System.currentTimeMillis()) {
//获取上一个锁的时间
String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
}
return false;
}
@Override
public void unlock(String key, String value) {
key = formatKey(key);
try {
String currentValue = redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
log.error("【redis分布式锁】解锁异常, {}", e);
}
}
@Override
public String get(String key) {
return redisTemplate.opsForValue().get(String.format(TOKEN_PREFIX, key));
}
@Override
public void set(String key, String value, Integer expire) {
redisTemplate.opsForValue().set(formatKey(key), value, expire, TimeUnit.SECONDS);
}
@Override
public void expire(String key, long expire) {
redisTemplate.expire(formatKey(key), expire, TimeUnit.SECONDS);
}
@Override
public void reset(String key, Integer expire) {
key = formatKey(key);
String value = redisTemplate.opsForValue().get(key);
redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
}
@Override
public void removeAllKeysLike(String prefix) {
String key = formatKey(prefix + "*");
Set<String> keys = redisTemplate.keys(key);
assert keys != null;
for (String str : keys) {
redisTemplate.delete(str);
log.info("redis Service】删除key = {}", str);
}
}
@Override
public void remove(String key) {
key = formatKey(key);
redisTemplate.delete(key);
}
private String formatKey(String key) {
return String.format(TOKEN_PREFIX, key);
}
@Override
public void deleteCacheByName(String cacheName) {
Cache cache = redisCacheManager.getCache(cacheName);
if (cache != null){
cache.clear();
}
}
}
四、controller:
package com.neo.web;
import com.neo.service.RedisService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* tll
* 2020/4/2
*/
@RestController
public class RedisController {
@Resource
private RedisService redisService;
//设置缓存
@RequestMapping("/redis")
public String redisTest(Integer id) {
redisService.set("test::" + id, "测试" + id, 6000);
return "redis" + id;
}
//删除这个缓存下所有的key
@RequestMapping("/deleteCacheByName")
public void deleteCacheByName(Integer id) {
redisService.deleteCacheByName("test");
}
//删除指定的key
@RequestMapping("/deleteKey")
public void deleteKey(Integer id) {
redisService.remove("test::" + id);
}
}
五、效果图: