前言
本篇文章主要介绍如何在Spring Boot 框架中整合Redis缓存以及Jedis客户端访问Redis API。使用Redis和我们在Web应用程序中使用Session缓存用户信息类似,我们只是将缓存换了一个地方存储,而使用Redis的好处在于它为我们提供了多种数据结构存储数据,同时会定期对缓存持久化。
Ubuntu 安装RedisDesktop Manager
一款非常实用的工具,可以监测Redis的使用情况,使用可视化界面操作Redis种存储的数据。
sudo apt update
sudo apt install snapd
sudo snap install redis-desktop-manager
SpringBoot 整合Jedis
pom.xml
添加Redis中间件和Jedis客户端依赖
<!--redis 缓存依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- redis 客户端依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
application.yml
配置Redis 和 Jedis
spring:
redis:
# 数据库索引(0-15)默认为0
database: 0
host: 127.0.0.1
port: 6379
password: password
jedis:
pool:
# 连接池最大连接数 (使用负数表示没有限制)
max-active: -1
# 连接池最大阻塞等待时间 (使用负数表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 500
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间
timeout: 0
# redis配置结束
block-when-exhausted: true
Application.java
使用@EnableCaching开启缓存
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableCaching
public class RuoYiApplication
{
public static void main(String[] args)
{
}
}
ProjectRedisConfig.java
Redis 配置类,主要用于配置和返回Jedis连接池,JedisPool
@Configuration
public class ProjectRedisConfig extends CachingConfigurerSupport {
public static final Logger log = LoggerFactory.getLogger(ProjectRedisConfig.class);
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private long maxWaitMillis;
@Value("${spring.redis.block-when-exhausted}")
private boolean blockWhenExhausted;
@Bean
public JedisPool redisPoolFactory() throws Exception{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// 配置连接耗尽时是否阻塞
jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
// 启用pool的jmx管理功能
jedisPoolConfig.setJmxEnabled(true);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
return jedisPool;
}
}
RedisUtils.java
构建封装Redis访问API
@Component
public class RedisUtils {
public static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
@Autowired
private JedisPool jedisPool;
private void close(Jedis jedis) {
if (jedis != null)
jedis.close();
}
private Jedis getJedis() {
return jedisPool.getResource();
}
/**
* 判断key是否存在
*
* @param key
* @return true or false
*/
public Boolean exists(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.exists(key);
} catch (Exception e) {
log.error(e.getMessage());
return false;
} finally {
close(jedis);
}
}
/**
* 通过key获取存储在redis库中的value
* @param key
* @return 成功返回value, 失败返回null
*/
public String get(String key) {
Jedis jedis = null;
String value = null;
try {
jedis = getJedis();
value = jedis.get(key);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
close(jedis);
}
return value;
}
/**
* 将给定key的值设为value,并返回key的旧值(old value)
* 当key存在但不是字符串类型时,返回一个错误
* @param key
* @param value
* @return 返回给定 key 的旧值。当key不存在时返回null
*/
public String getSet(String key, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.getSet(key, value);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
close(jedis);
}
return null;
}
/**
* 通过key获取value值的长度
* @param key
* @return 失败返回null
*/
public Long serlen(String key) {
Jedis jedis = null;
Long length = null;
try {
jedis = getJedis();
length = jedis.strlen(key);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
close(jedis);
}
return length;
}
/**
* 向redis中存入key和value
* @param key
* @param value
* @return 成功返回"OK", 失败返回"0”
*/
public String set(String key, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.set(key, value);
} catch (Exception e) {
log.error(e.getMessage());
return "0";
} finally {
close(jedis);
}
}
/**
* set Expire : 新增key, 并将 key 的生存时间(以秒为单位)
* @param key
* @param seconds 生存时间 单位:秒
* @param value
* @return 设置成功返回OK。 当seconds参数不合法时, 返回一个错误。
*/
public String setex(String key, int seconds, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.setex(key, seconds, value);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
close(jedis);
}
return null;
}
/**
* set Not Exist : 设置key value, 如果key已经存在则返回0,
*
* @param key
* @param value
* @return
*/
public Long setnx(String key, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.setnx(key, value);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
}
/**
* 通过key 向指定的value值追加值
*
* @param key
* @param str
* @return 成功返回添加后value的长度, 失败返回添加的value长度,异常返回0L
*/
public Long append(String key, String str) {
Jedis jedis = null;
Long length = null;
try {
jedis = getJedis();
length = jedis.append(key, str);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
return length;
}
/**
* 删除指定的key, 也可以传入一个包含key的数组
* @param keys 一个key 或者 一个包含key的数组
* @return 返回删除成功的个数
*/
public Long del(String... keys) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.del(keys);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
}
/**
* 为给定 key 设置生存时间, 当 key 过期时(生存时间为0),它会被自动删除。
* @param key
* @param seconds 过期时间,单位:秒
* @return 成功返回 1, 如果存在和发生异常返回 0
*/
public Long expire(String key, int seconds) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.expire(key, seconds);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
}
/**
* 为给定 key 设置生存时间, 当 key 过期时(生存时间为0),它会被自动删除。
* @param key
* @param timestamp 具体过期时间,单位:ms
* @return 成功返回 1, 如果存在和发生异常返回 0
*/
public Long expireAt(String key, Long timestamp) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.expireAt(key, timestamp);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
}
/**
* 以秒为单位,返回给定key的剩余生存时间
* @param key
* @return 以秒为单位, 返回key的剩余生存时间。当key不存在时,返回-2。没有当key存在但没有设置剩余生存时间时,返回-1。发生异常,返回 0。
*/
public Long ttl(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.ttl(key);
} catch (Exception e) {
log.error(e.getMessage());
return 0L;
} finally {
close(jedis);
}
}
/**
* 移除给定key的生存时间,将这个key从【易失的】(带生存时间)转换为【持久的】(永不过期的)
* @param key
* @return 当生存时间移除成功时,返回 1。如果key不存在或key没有设置生存时间,返回0,发生异常返回-1
*/
public Long persist(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.persist(key);
} catch (Exception e) {
log.error(e.getMessage());
return -1L;
} finally {
close(jedis);
}
}
/**
* 通过key判断值的类型
* @param key
* @return “none", "string", "list", "set"; "none"表示key不存在。
*/
public String type(String key) {
Jedis jedis = null;
String valueType = null;
try {
jedis = getJedis();
valueType = jedis.type(key);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
close(jedis);
}
return valueType;
}
}
注意事项
- 如果在application.yml配置文件中配置了password(值为空也一样),而在redis.conf(redis的配置文件)中没有配置password(没有开启密码验证)那么会报如下异常。
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
ERR Client sent AUTH, but no password is set