spring boot集成redis
直接上代码
pom依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
application.yml
spring:
redis:
database: 1
host: 127.0.0.1 # ip
port: 6379
password: 123456 # 密码
timeout: 6000
jedis:
pool:
max-active: 100
max-wait: 1000
max-idle: 100
min-idle: 5
java代码
RedisCommonAutoConfiguration.java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisCommonAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(@Qualifier("jedisConnectionFactory") JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory);
redisTemplate.setDefaultSerializer(new GenericToStringSerializer<>(String.class));
redisTemplate.setKeySerializer(new GenericToStringSerializer<>(String.class));
redisTemplate.setValueSerializer(new GenericToStringSerializer<>(String.class));
return redisTemplate;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(@Qualifier("jedisConnectionFactory") JedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
return stringRedisTemplate;
}
}
kotlin代码
JedisConfig.kotlin
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.data.redis.connection.RedisPassword
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
import redis.clients.jedis.JedisPoolConfig
import java.time.Duration
@Configuration
open class JedisConfig {
@Value("\${spring.redis.host}")
private lateinit var redisHost: String
@Value("\${spring.redis.port}")
private lateinit var redisPost: String
@Value("\${spring.redis.database:0}")
private var redisDB: Int = 0
@Value("\${spring.redis.password}")
private lateinit var redisPassword: String
@Value("\${spring.redis.timeout:6000}")
private var timeOut: Long = 6000L
@Value("\${spring.redis.jedis.max-idle:1000}")
private var maxIdle: Int = 1000
@Value("\${spring.redis.jedis.min-idle:5}")
private var minIdle: Int = 5
@Value("\${spring.redis.jedis.max-wait:10000}")
private var maxWait: Long = 10000L
@Value("\${spring.redis.jedis.max-wait:100}")
private var maxTotal: Int = 100
@Bean
@Primary
open fun jedisPoolConfig(): JedisPoolConfig {
val jedisPoolConfig = JedisPoolConfig()
jedisPoolConfig.maxIdle = maxIdle
jedisPoolConfig.minIdle = minIdle
jedisPoolConfig.maxWaitMillis = maxWait
jedisPoolConfig.maxTotal = maxTotal
jedisPoolConfig.testOnBorrow = false
jedisPoolConfig.testOnReturn = true
return jedisPoolConfig
}
@Bean
open fun jedisConnectionFactory(@Qualifier("jedisPoolConfig") jedisPoolConfig: JedisPoolConfig): JedisConnectionFactory {
val redisStandaloneConfiguration = RedisStandaloneConfiguration()
redisStandaloneConfiguration.hostName = redisHost
redisStandaloneConfiguration.password = RedisPassword.of(redisPassword)
redisStandaloneConfiguration.port = redisPost.toInt()
redisStandaloneConfiguration.database = redisDB
val jedisClientConfiguration = JedisClientConfiguration.builder()
jedisClientConfiguration.connectTimeout(Duration.ofMinutes(timeOut))
jedisClientConfiguration.usePooling().poolConfig(jedisPoolConfig)
val factory = JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration.build())
return factory
}
}
RedissonConfig.kt
import org.redisson.Redisson
import org.redisson.api.RRateLimiter
import org.redisson.api.RateIntervalUnit
import org.redisson.api.RateType
import org.redisson.api.RedissonClient
import org.redisson.config.Config
import org.redisson.config.TransportMode
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
open class RedissonConfig {
@Value("\${spring.redis.host}")
private lateinit var redisHost: String
@Value("\${spring.redis.port}")
private lateinit var redisPost: String
@Value("\${spring.redis.password}")
private lateinit var redisPassword: String
@Value("\${spring.redis.timeout:6000}")
private var timeOut: Long = 6000
@Value("\${spring.redis.database:0}")
private var redisDB: Int = 0
@Value("\${issue.submit.limit.intervalLimit:25}")
private var intervalLimit: Long = 25
@Value("\${issue.submit.limit.intervalSeconds:10}")
private var intervalSeconds: Long = 10
@Bean
open fun submitRateLimiter(): RRateLimiter {
val config = Config()
config.useSingleServer().setAddress("redis://$redisHost:$redisPost").setTimeout(this.timeOut.toInt())
.setPassword(this.redisPassword).database = this.redisDB
config.transportMode = TransportMode.NIO;
val client = Redisson.create(config)
val rateLimiter = client.getRateLimiter("SUBMIT_ISSUE_RATE_LIMITER")
rateLimiter.trySetRate(RateType.OVERALL, this.intervalLimit, this.intervalSeconds, RateIntervalUnit.SECONDS)
return rateLimiter
}
@Bean
open fun redissonClient(): RedissonClient {
val config = Config()
config.useSingleServer().setAddress("redis://$redisHost:$redisPost")
.setPassword(this.redisPassword).database = this.redisDB
return Redisson.create(config)
}
}
其他
在resource目录下添加META-INF
文件夹新建spring.factories
文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
包名.RedisCommonAutoConfiguration, \
包名.RedissonConfig
分布式锁
RedisLock.kt
import org.slf4j.LoggerFactory
import org.springframework.data.redis.core.RedisTemplate
import redis.clients.jedis.Jedis
import redis.clients.jedis.JedisCluster
import redis.clients.jedis.params.SetParams
import java.util.UUID
open class RedisLock constructor(
private val redisTemplate: RedisTemplate<Any, Any>,
private val key: String,
private val timeSeconds: Long
) {
companion object {
private const val OK = "OK"
private const val LUA_CMD = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1])" +
" else return 0 end"
private val logger = LoggerFactory.getLogger(RedisLock::class.java)
}
private var result = false
private val value = UUID.randomUUID().toString()
/**
* 加锁
*/
fun lock() {
logger.info("start add luck key:$key")
while (true) {
set(key, value, timeSeconds)
if (result) {
logger.info("add luck complete key: $key")
return
}
Thread.sleep(100)
}
}
/**
* 尝试加锁
*/
fun tryLock(): Boolean {
set(key, value, timeSeconds)
return result
}
/**
* 释放锁
*/
fun unLock(): Boolean? {
return redisTemplate.execute{
logger.info("start try unLock key:$key")
val nativeConnection = it.nativeConnection
val keys = listOf(key)
val values = listOf(value)
val res = when(nativeConnection) {
is Jedis -> nativeConnection.eval(LUA_CMD, keys, values)
is JedisCluster -> nativeConnection.eval(LUA_CMD, keys, values)
else -> {
logger.warn("unlock failure key: $key")
""
}
}
result = res.equals("1")
result
}
}
/**
* 重写set方法
*/
fun set(key: String, value: String, seconds: Long): Boolean? {
return redisTemplate.execute {
val setParams = SetParams()
setParams.nx().ex(seconds.toInt())
val res = when (val native = it.nativeConnection) {
is Jedis -> native.set(key,value, setParams)
is JedisCluster -> native.set(key,value, setParams)
else -> {
logger.warn("redis connection failure $key")
""
}
}
result = res.equals(OK, true)
result
}
}
/**
* 获取当前状态
*/
fun getResult(): Boolean {
return result
}
}
工具类
这个工具类不全,可以找其他的工具类
RedisUtil.java
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 默认过期时长,单位:秒
*/
public static final long DEFAULT_EXPIRE = 60 * 60 * 24L;
public String get(String key) {
if (StringUtils.isNotBlank(key)) {
Object obj = redisTemplate.opsForValue().get(key);
if (Objects.nonNull(obj)) {
return String.valueOf(obj);
}
}
return null;
}
public void del(String key) {
redisTemplate.delete(key);
}
public void delListKey(List<String> list) {
redisTemplate.delete(list);
}
public void set(String key, Object value) {
set(key, value, DEFAULT_EXPIRE, TimeUnit.SECONDS);
}
public void set(String key, Object value, Long expire, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, expire, unit);
}
public void setNotExpire(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 覆盖
* @param key
*/
public void cover(String key, String value) {
if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
Long expire = redisTemplate.getExpire(key);
if (expire == null) {
expire = DEFAULT_EXPIRE;
}
redisTemplate.delete(key);
redisTemplate.opsForValue().set(key, value);
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
return;
}
set(key, value, DEFAULT_EXPIRE, TimeUnit.SECONDS);
}
public void addSet(String key, String ele) {
redisTemplate.opsForSet().add(key, ele);
}
public String popSet(String key) {
return String.valueOf(redisTemplate.opsForSet().pop(key));
}
public Long getSetLength(String key) {
return redisTemplate.opsForSet().size(key);
}
public boolean setIsMember(String key, String value) {
return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));
}
public boolean contains(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
public void addListEle(String key, String ele) {
redisTemplate.opsForList().leftPush(key, ele);
}
public <T> List<T> getCacheList(String key, Class<T> type) {
List<Object> range = redisTemplate.opsForList().range(key, 0, -1);
if (range == null) {
return null;
}
List<T> list = new ArrayList<>();
for (Object o : range) {
list.add(JSON.parseObject(o.toString(), type));
}
return list;
}
public Long increment(String key, Long count) {
return redisTemplate.opsForValue().increment(key, count);
}
}