点击关注公众号,利用碎片时间学习

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

    }
}

控制台输出

292fc65e5ba9cc0732659acb23f26832.png

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

来源:blog.csdn.net/qq_27242695/article/

details/112618063

推荐:

主流Java进阶技术(学习资料分享)

2880be986a74ccb717952a594ef919c1.png

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐