⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_27242695/article/details/112618063/ 「放牛放牛放牛」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

SpringBoot整合Redis

  • SpringBoot版本:2.x以上
  • 本案例版本:2.4.1

1 整合Redis

1.1 pom.xml添加依赖

<!--redis配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--进行redisTemplate配置时需要此包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>

<!--reids版本为1.4.1版本以上需要添加-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>

1.2 application.properties配置

1.2.1 哨兵连接配置

注意:redis高版本配置信息做了调整

SpringBoot 1.4版本之后配置如下

# 连接工厂使用的数据库索引,redis默认有16个db,索引0-15
spring.redis.database= 0
# 哨兵配置过程中,给主机命名的名字
spring.redis.sentinel.master=mymaster
# 哨兵,配置多个 都好隔开
spring.redis.sentinel.nodes=ip1:port1,ip2:port2,ip3:port3
# 登录redis服务器的密码,无设置密码可以不填写
spring.redis.password=password
# 给定时间池可以分配的最大连接数 使用负值为无限制
spring.redis.pool.max-active= 8
# 连接分配在池耗尽之前在抛出异常之前应阻止的最大时间量(连接池最大阻塞等待时间以毫秒为单位) 使用负值无限期地阻止
spring.redis.pool.max-wait= -1
# 连接池中的最大空闲连接 使用负值来表示无限数量的空闲连接
spring.redis.pool.max-idle= 8
# 连接池中的最小空闲连接 此设置只有在正值时才有效果
spring.redis.pool.min-idle= 0
# 连接超时(毫秒)
spring.redis.timeout=30000

SpringBoot 2.x版本配置如下

# 连接工厂使用的数据库索引,redis默认有16个db,索引0-15
spring.redis.database= 0
# 哨兵配置过程中,给主机命名的名字
spring.redis.sentinel.master=mymaster
# 哨兵,配置多个 都好隔开
spring.redis.sentinel.nodes=ip1:port1,ip2:port2,ip3:port3
# 登录redis服务器的密码,无设置密码可以不填写
spring.redis.password=password
# 给定时间池可以分配的最大连接数 使用负值为无限制
spring.redis.lettuce.pool.max-active= 8
# 连接分配在池耗尽之前在抛出异常之前应阻止的最大时间量(连接池最大阻塞等待时间以毫秒为单位) 使用负值无限期地阻止
spring.redis.lettuce.pool.max-wait= -1
# 连接池中的最大空闲连接 使用负值来表示无限数量的空闲连接
spring.redis.lettuce.pool.max-idle= 8
# 连接池中的最小空闲连接 此设置只有在正值时才有效果
spring.redis.lettuce.pool.min-idle= 0
# 连接超时(毫秒)
spring.redis.timeout=30000

1.2.2 单机版连接配置

SpringBoot 1.4版本之后配置如下

# 连接工厂使用的数据库索引,redis默认有16个db,索引0-15
spring.redis.database= 0
# Redis服务器主机
spring.redis.host=127.0.0.1
# redis服务器端口
spring.redis.port= 6379
# 登录redis服务器的密码,无设置密码可以不填写
spring.redis.password=password
# 给定时间池可以分配的最大连接数 使用负值为无限制
spring.redis.pool.max-active= 8
# 连接分配在池耗尽之前在抛出异常之前应阻止的最大时间量(连接池最大阻塞等待时间以毫秒为单位) 使用负值无限期地阻止
spring.redis.pool.max-wait= -1
# 连接池中的最大空闲连接 使用负值来表示无限数量的空闲连接
spring.redis.pool.max-idle= 8
# 连接池中的最小空闲连接 此设置只有在正值时才有效果
spring.redis.pool.min-idle= 0
# 连接超时(毫秒)
spring.redis.timeout=30000

SpringBoot 2.x之前版本配置如下

# 连接工厂使用的数据库索引,redis默认有16个db,索引0-15
spring.redis.database= 0
# Redis服务器主机
spring.redis.host=127.0.0.1
# redis服务器端口
spring.redis.port=6379
# 登录redis服务器的密码,无设置密码可以不填写
spring.redis.password=password
# 给定时间池可以分配的最大连接数 使用负值为无限制
spring.redis.lettuce.pool.max-active= 8
# 连接分配在池耗尽之前在抛出异常之前应阻止的最大时间量(连接池最大阻塞等待时间以毫秒为单位) 使用负值无限期地阻止
spring.redis.lettuce.pool.max-wait= -1
# 连接池中的最大空闲连接 使用负值来表示无限数量的空闲连接
spring.redis.lettuce.pool.max-idle= 8
# 连接池中的最小空闲连接 此设置只有在正值时才有效果
spring.redis.lettuce.pool.min-idle= 0
# 连接超时(毫秒)
spring.redis.timeout=30000

1.2.3 注意

当配置文件哨兵也单机版配置同时存在,哨兵连接机制优先。

注意SpringBoot版本,选择指定的配置。

1.3 Redis核心配置类-RedisConfig.java

/**
* Redis的核心配置类,这个类提供了两个方法(其实提供了两个bean,这两个bean会加载到spring的context里边,供使用者进行调用)
*/
@Configuration//这个标签,通常与@bean结合使用,当@bean使用到该类的方法上,代表将该方法做为一个bean交给了spring的context
@EnableCaching//允许我们使用缓存
public class RedisConfig {

@Bean//此时,将我们的redisTemplate加载到了我们的spring的上下文中,applicationContext
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//为了自己开发方便,使用String,Object类型
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(factory);
//序列化配置,使用json解析任意的对象,将对象解析成可以序列化的对象
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//使用Mapper对象进行转义
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
//开始序列化对象
jackson2JsonRedisSerializer.setObjectMapper(om);

// String 类型的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String序列化的方式
template.setKeySerializer(stringRedisSerializer);
//hash采用String序列化的方式
template.setHashKeySerializer(stringRedisSerializer);
//value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value序列化方式采用jackson
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}

@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
//1.序列话(一般用于key值)
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
//2.引入json串的转化类(一般用于value的处理)
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
//2.1设置objectMapper的访问权限
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//2.2指定序列化输入类型,就是将数据库里的数据按照一定类型存储到redis缓存中。
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);//最近升级SpringBoot,发现enableDefaultTyping方法过期过期了。可以使用下面的方法代替
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
//3.序列话配置,乱码问题解决以及我们缓存的时效性
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().
entryTtl(Duration.ofSeconds(1000)).//缓存时效性设置
serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).//key序列化
serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).//value序列化
disableCachingNullValues();//空值不存入缓存
//4.创建cacheManager链接并设置属性
RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
return cacheManager;
}
}

1.3.1 Spring提供的序列化器(使用方式自行百度)

  • Jackson2JsonRedisSerializer
  • JdkSerializationRedisSerializer
  • OxmSerializer
  • StringRedisSerializer
  • GenericToStringRedisSerializer
  • GenericJackson2JsonRedisSerializer

1.3.2 为什么要序列化?

在JAVA中,一切皆对象,而将对象的状态信息转为存储或传输的形式需要序列化。

2. 验证

2.1 单元测试redis中存储student对象

代码

@SpringBootTest(classes = DemoApplication.class)
public class RedisTest {

@Test
public void test1() {
Student student = new Student();
student.setName("学生1");
student.setSex("男");
student.setAge(18);
RedisUtil.set("student1", student);
System.out.println(RedisUtil.get("student1").toString());

}
}

控制台输出

redis控制台查看

xxx.xxx.xxx.xxx:6377[1]> get student1
"[\"com.exp.demo.dto.Student\",{\"name\":\"\xe5\xad\xa6\xe7\x94\x9f1\",\"sex\":\"\xe7\x94\xb7\",\"age\":18}]"

2 资源

2.1 工具类

工具类 RedisUtil

/**
* Redis工具类,使用之前请确保RedisTemplate成功注入
*
* @author lxq
*/

public class RedisUtil {

private RedisUtil() {
}

@SuppressWarnings("unchecked")
private static RedisTemplate<String, Object> redisTemplate = SpringUtil.getBean("redisTemplate", RedisTemplate.class);

/**
* 设置有效时间
* 单位默认秒
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public static boolean expire(final String key, final long timeout) {

return expire(key, timeout, TimeUnit.SECONDS);
}

/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public static boolean expire(final String key, final long timeout, final TimeUnit unit) {

Boolean ret = redisTemplate.expire(key, timeout, unit);
return ret != null && ret;
}

/**
* 删除单个key
*
* @param key 键
* @return true=删除成功;false=删除失败
*/
public static boolean del(final String key) {

Boolean ret = redisTemplate.delete(key);
return ret != null && ret;
}

/**
* 删除多个key
*
* @param keys 键集合
* @return 成功删除的个数
*/
public static long del(final Collection<String> keys) {

Long ret = redisTemplate.delete(keys);
return ret == null ? 0 : ret;
}

/**
* 存入普通对象
*
* @param key Redis键
* @param value 值
*/
public static void set(final String key, final Object value) {

redisTemplate.opsForValue().set(key, value);
}

// 存储普通对象操作

/**
* 存入普通对象
*
* @param key 键
* @param value 值
* @param timeout 有效期,单位秒
*/
public static void set(final String key, final Object value, final long timeout) {

redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}

/**
* 获取普通对象
*
* @param key 键
* @return 对象
*/
public static Object get(final String key) {

return redisTemplate.opsForValue().get(key);
}

// 存储Hash操作

/**
* 往Hash中存入数据
*
* @param key Redis键
* @param filed Hash filed键
* @param value 值
*/
public static void hPut(final String key, final String filed, final Object value) {

redisTemplate.opsForHash().put(key, filed, value);
}

/**
* 往Hash中存入多个数据
*
* @param key Redis键
* @param filedMap Hash键值对
*/
public static void hPutAll(final String key, final Map<String, Object> filedMap) {

redisTemplate.opsForHash().putAll(key, filedMap);
}

/**
* 获取Hash中的数据
*
* @param key Redis键
* @param filed Hash filed键
* @return Hash中的对象
*/
public static Object hGet(final String key, final String filed) {

return redisTemplate.opsForHash().get(key, filed);
}

/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param fileds Hash filed键集合
* @return Hash对象集合
*/
public static List<Object> hMultiGet(final String key, final Collection<Object> fileds) {

return redisTemplate.opsForHash().multiGet(key, fileds);
}

// 存储Set相关操作

/**
* 往Set中存入数据
*
* @param key Redis键
* @param values 值
* @return 存入的个数
*/
public static long sSet(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().add(key, values);
return count == null ? 0 : count;
}

/**
* 删除Set中的数据
*
* @param key Redis键
* @param values 值
* @return 移除的个数
*/
public static long sDel(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().remove(key, values);
return count == null ? 0 : count;
}

// 存储List相关操作

/**
* 往List左侧中存入数据
*
* @param key Redis键
* @param value 数据
* @return 存入的个数
*/
public static long lPush(final String key, final Object value) {
Long count = redisTemplate.opsForList().leftPush(key, value);
return count == null ? 0 : count;
}

/**
* 往List右侧中存入数据
*
* @param key Redis键
* @param value 数据
* @return 存入的个数
*/
public static long rPush(final String key, final Object value) {
Long count = redisTemplate.opsForList().rightPush(key, value);
return count == null ? 0 : count;
}

/**
* 往List中左侧存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public static long lPushAll(final String key, final Collection<Object> values) {
Long count = redisTemplate.opsForList().leftPushAll(key, values);
return count == null ? 0 : count;
}

/**
* 往List中左侧存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public static long lPushAll(final String key, final Object... values) {
Long count = redisTemplate.opsForList().leftPushAll(key, values);
return count == null ? 0 : count;
}

/**
* 往List中右侧存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public static long rPushAll(final String key, final Collection<Object> values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}


/**
* 往List中右侧存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public static long rPushAll(final String key, final Object... values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}


/**
* 从List中获取begin到end之间的元素
*
* @param key Redis键
* @param start 开始位置
* @param end 结束位置(start=0,end=-1表示获取全部元素)
* @return List对象
*/
public static List<Object> listGetRange(final String key, final int start, final int end) {
return redisTemplate.opsForList().range(key, start, end);
}


/**
* 从List左侧弹出数据
*
* @param key Redis键
* @return 对象
*/
public static Object listGetL(final String key) {
return redisTemplate.opsForList().leftPop(key);
}


/**
* 从List右侧弹出数据
*
* @param key Redis键
* @return 对象
*/
public static Object listGetR(final String key) {
return redisTemplate.opsForList().rightPop(key);
}
}

SpringUtil

/**
* SpringBoot 容器工具类
*/
@Component
public class SpringUtil implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;

@Override
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtil.applicationContext = applicationContext;
}

/**
* 获取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}

/**
* 通过name获取 Bean.
* @param name 参数传入要获取的实例的类名 首字母小写,这是默认的
* @return
*/
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}

/**
* 通过class获取Bean.
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}

/**
* 通过name,以及Clazz返回指定的Bean
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}

2.2 代码

https://pan.baidu.com/s/1C8t8eCNwZzpSFHxJP0h3qQ 提取码: 7mp7

文章目录
  1. 1. SpringBoot整合Redis
    1. 1.1. 1 整合Redis
      1. 1.1.1. 1.1 pom.xml添加依赖
      2. 1.1.2. 1.2 application.properties配置
      3. 1.1.3. 1.3 Redis核心配置类-RedisConfig.java
    2. 1.2. 2. 验证
      1. 1.2.1. 2.1 单元测试redis中存储student对象
    3. 1.3. 2 资源
      1. 1.3.1. 2.1 工具类
    4. 1.4. 2.2 代码