文章目录
1. Jedis
Jedis
是 Redis
官方推荐的 Java
连接开发工具。
2. 添加 Jedis 依赖
在 Java
项目添加 Jedis
的 maven 依赖 ,导入相应的 jar 包即可使用。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
3. 使用 Jedis 连接 Redis
使用 Jedis
连接 Redis
,在 Jedis 的构造方法传入 Redis 的 host 和端口号,如果 Redis 有密码的话,再设置 Jedis 的 auth 参数即可。
void connectRedisTest(){
Jedis jedis = new Jedis("127.0.0.1", 6375);
jedis.auth("xxxxxxx");
System.out.println("Connect redis success!");
jedis.set("test", "testString");
System.out.println(jedis.get("test"));
jedis.hset("player", "name", "kobe");
jedis.hset("player", "num", "24");
System.out.println(jedis.hget("player","name"));
System.out.println(jedis.hgetAll("player"));
}
结果
Connect redis success!
testString
kobe
{name=kobe, num=24}
4. SpringBoot 整合 Redis
SpringBoot
极大简化了整合 Redis
需要的配置,我们只需要在配置文件(application.yml 或者 application.properities)中配置连接 Redis
的相关参数,就可以使用官方默认提供的 RedisTemplate
类来操作 Redis
。但是默认的 RedisTemplate
模板只支持字符串,所以我们需要重新封装 RedisTemplate
,设置新的序列化规则,以便我们能够操作 Java 实例对象。
4.1 添加 Maven 依赖
<!-- spring boot redis 缓存引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
4.2 application.yml 配置文件
spring:
redis:
database: 0 # Redis数据库索引(默认为0)
sentinel:
master: iproject-custom-alarm
hosts: xx.xx.xx.xx:36379,xx.xx.xx.xx:36379,xx.xx.xx.xx:36379 # 哨兵节点
password: iB4jJ8nL9aJ5fK1nF7iL2iBPLM-21024371aK5lH1 # redis 密码
sentinelPwd: SYI3BU/lX+7jK0ebsMIpK5Lums+bmUwLH99MeN+ln+y2r9UDRDsiyCRNYlXbCSt2 # 哨兵密码
# redis 连接池相关参数
pool:
maxActive: 50 # 连接池最大连接数
maxWait: 20 # 连接池最大阻塞等待时间
maxIdle: 20 # 连接池中的最大空闲连接
minIdle: 5 # 连接池中的最小空闲连接
minEvictableIdleTimeMillis: 60000
timeout: 3000
enable: 1 # 开关,是否启用redis功能
4.3 解析 host 和 port
配置文件中 hosts
可能配置了多个节点,需要从中解析出每个节点的 host
和 port
,这里写了一个工具类。
package com.zte.rdcloud.iproject.domain.versionplan.alarm.infra.redis.config;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class RedisAddressUtils {
public RedisAddressUtils() {
}
public static List<RedisNode> splitHosts(String hosts) {
List<RedisNode> nodes = new ArrayList();
String[] var2 = StringUtils.commaDelimitedListToStringArray(hosts);
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String node = var2[var4];
try {
String[] parts = StringUtils.split(node, ":");
Assert.state(Objects.nonNull(parts) && parts.length == 2, "Must be defined as 'host:port'");
nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
} catch (RuntimeException var7) {
throw new IllegalStateException("Invalid redis property '" + node + "'", var7);
}
}
return nodes;
}
}
4.4 Redis 配置类
在 Redis
配置类中,我们要根据 application.yml
配置文件完成 Jedis
连接池、Redis
连接和 RedisTemplate
序列化的配置。
package com.zte.rdcloud.iproject.domain.versionplan.alarm.infra.redis.config;
import com.zte.rdcloud.wbs.util.RedisUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@ConditionalOnProperty(name = "msa.redis.enable", havingValue = "1")
public class PlanRedisConfig {
@Value("${msa.redis.sentinel.master}")
private String sentinelMaster;
@Value("${msa.redis.hosts}")
private String sentinelNodes;
@Value("${msa.redis.password}")
private String redisPassword;
@Value("${msa.redis.sentinelPwd}")
private String sentinelPassword;
@Value("${msa.redis.pool.maxActive}")
private int maxTotal;
@Value("${msa.redis.pool.maxIdle}")
private int maxIdle;
@Value("${msa.redis.pool.minIdle}")
private int minIdle;
@Value("${msa.redis.pool.maxWait}")
private long maxWaitMillis;
@Value("${msa.redis.pool.minEvictableIdleTimeMillis}")
private long minEvictableIdleTimeMillis;
@Value("${msa.redis.timeout}")
private int timeout;
@Bean
public JedisConnectionFactory redisConnectionFactory() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration().master(sentinelMaster);
sentinelConfig.setSentinelPassword(sentinelPassword);
sentinelConfig.setSentinels(RedisAddressUtils.splitHosts(sentinelNodes));
sentinelConfig.setDatabase(0);
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(sentinelConfig);
jedisConnectionFactory.setPassword(redisPassword);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.setTimeout(timeout);
return jedisConnectionFactory;
}
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWaitMillis);
poolConfig.setEvictorShutdownTimeoutMillis(minEvictableIdleTimeMillis);
return poolConfig;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
//配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置连接工厂
redisTemplate.setConnectionFactory(factory);
// 使用 StringRedisSerializer 来序列化 redis 的 key
StringRedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
// 使用 Jackson2JsonRedisSerializer 来序列化 redis 的 value
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
RedisUtils.setRedisTemplate(redisTemplate);
return redisTemplate;
}
}
至此,我们已经可以使用 RedisTemplate
来操作 Redis
,当然我们也可以进一步对 RedisTemplate
进行封装,将 Java
的数据类型和 Redis
的数据结构命令对应,提供对外的统一接口。
4.5 Redis 工具类
下面只是一个简单的例子,可以根据自己项目的需要封装对应的接口。
package com.zte.rdcloud.wbs.util;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class RedisUtils {
@Setter
private static RedisTemplate<String, Object> redisTemplate;
/**
* 为键值设置过期时间,单位秒
*
* @param key 键
* @param time 时间(秒)
* @return true:成功;false:失败
*/
public static boolean expire(String key, long time) {
try {
if (time > 0){
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
}catch (Exception e){
log.error(e.getMessage());
return false;
}
}
//------------------------------String-----------------------------
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public static boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
}
/**
* 普通缓存放入并设置过期时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public static boolean set(String key, Object value, long time) {
try {
if(time > 0){
redisTemplate.opsForValue().set(key, value, time);
}else{
set(key, value);
}
return true;
}catch (Exception e){
log.error(e.getMessage());
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public static void del(String... key) {
try {
if(null != key && key.length > 0){
if(key.length == 1){
redisTemplate.delete(key[0]);
}else{
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}catch(Exception e){
log.error(e.getMessage());
}
}
/**
* 普通缓存获取
*
* @param key
* @return
*/
public static Object get(String key){
try {
return null == key ? null : redisTemplate.opsForValue().get(key);
}catch(Exception e){
log.error(e.getMessage());
return null;
}
}
/**
* 获取旧值,缓存新值
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public static Object getAndSet(String key, Object value) {
try {
return redisTemplate.opsForValue().getAndSet(key, value);
} catch (Exception e) {
return null;
}
}
//------------------------------Hash-----------------------------
/**
* 向一张hash表中放入数据,如果不存在将创建,存在则覆盖
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public static boolean hSet(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
}catch (Exception e){
log.error(e.getMessage());
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建,存在则覆盖,并设置过期时间
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public static boolean hSet(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if(time > 0){
expire(key, time);
}
return true;
}catch (Exception e){
log.error(e.getMessage());
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建,存在则只设置失效时间(不会设置新值)
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public static boolean hSetIfAbsent(String key, String item, Object value, long time) {
try {
Boolean result = redisTemplate.opsForHash().putIfAbsent(key, item, value);
if (time > 0) {
expire(key, time);
}
return result;
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public static boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以是多个 不能为null
*/
public static void hDel(String key, Object... item) {
try {
redisTemplate.opsForHash().delete(key, item);
}catch(Exception e){
log.error("redis failed hdel", e);
}
}
/**
* 获取指定键对应的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public static Object hGet(String key, String item) {
try {
return redisTemplate.opsForHash().get(key, item);
}catch (Exception e){
log.error(e.getMessage());
return null;
}
}
}