spring boot集成redis

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);
    }
}

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值