千家信息网

SpringBoot整合Redis案例分析

发表于:2024-09-26 作者:千家信息网编辑
千家信息网最后更新 2024年09月26日,这篇文章主要介绍了SpringBoot整合Redis案例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot整合Redis案例分析文章都会有所收获,下面
千家信息网最后更新 2024年09月26日SpringBoot整合Redis案例分析

这篇文章主要介绍了SpringBoot整合Redis案例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot整合Redis案例分析文章都会有所收获,下面我们一起来看看吧。

如果没有Redis,就先去下载
  • 下载路径cmd,然后redis-server.exe redis.windows.conf命令既可以启动服

  • 启动服务后,后面的才可以进行整合
  • 在redis目录下点击redis-cli.exe进行测试结果查看,基本操作如下

    • key * :查看存储内容

    • flushdb :清空数据库

如果redis不熟悉去看

undefined

SpringData也是和SpringBoot齐名的项目!

说明:在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce

jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池!【类似于BIO:同步阻塞IO】

lettuce:采用netty【异步请求,性能更高点】,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数量了【类似于NIO:同步非阻塞IO】

  • 异步请求一般都需要序列化

源码分析:

  • 源码位置:

        @Bean        //当这个Bean不存在的时候,这个类就生效        //这就说明,我们可以自己定义一个redisTemplate来替换这个默认的!        @ConditionalOnMissingBean(name = "redisTemplate")        @ConditionalOnSingleCandidate(RedisConnectionFactory.class)        public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {        //默认的RedisTemplate没有过多的设置,redis,对象都是需要序列化的!        //两个泛型都是Object类型,我们后面使用需要强制转换:我们需要的类型                        RedisTemplate template = new RedisTemplate<>();                template.setConnectionFactory(redisConnectionFactory);                return template;        }        @Bean        @ConditionalOnMissingBean       //由于String是Redis最常用的类型,所以说单独提出来了一个Bean        @ConditionalOnSingleCandidate(RedisConnectionFactory.class)        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {                StringRedisTemplate template = new StringRedisTemplate();                template.setConnectionFactory(redisConnectionFactory);                return template;        }

上手测试【默认的RedisTemplate了解】

1.导入依赖
                    org.springframework.boot            spring-boot-starter-data-redis            org.springframework.boot    spring-boot-starter-data-redis                        io.lettuce            lettuce-core                redis.clients    jedis
2.配置连接
# SpringBoot所有的配置类,都有一个自动配置类  RedisAutoConfiguration#  自动配置类都会绑定一个properties配置文件  RedisPropertiesspring:  redis:    host: 127.0.0.1    # Redis服务器连接端口    port: 6379    # Redis数据库索引(默认为0)    database: 0    # Redis服务器连接密码(默认为空)    password:    # 连接池最大连接数(使用负值表示没有限制)    pool:      max-active: 200    # 连接池最大阻塞等待时间(使用负值表示没有限制)      max-wait: -1    # 连接池中的最大空闲连接      max-idle: 10    # 连接池中的最小空闲连接      min-idle: 0    # 连接超时时间(毫秒)    timeout: 1000
3.测试
  • 实际开发中我们都不会用这种原生的方式来编写代码

  • 一般我们会将这些常用的操作编写成工具类:redisUtils【后面就会有】
    • 前面还有jdbcUtils和MybatisUtils等

@SpringBootTestclass Redis03SpringbootApplicationTests {    //注入RedisAutoConfiguration里面配置的类    @Autowired    public RedisTemplate redisTemplate;    @Test    void contextLoads() {                        //redisTemplate :操作我们的数据库,api和我们的是一样的        //opsForValue   :操作字符串  类似String        //opsForList    :操作List        //除了基本的操作,我们常用的方法都可以直接通过redisTemplate进行操作        //比如事务和基本的CRUD        //获取redis的连接对象,就可以操作数据库的连接了【一般很少来用】/*        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();        connection.flushDb();        connection.flushAll();*/        redisTemplate.opsForValue().set("kami", "g1x");        System.out.println(redisTemplate.opsForValue().get("kami"));    }}
4.结果

问题:写到中文的时候,springboot是正常的,但是从redis中的redis.cli.exe运行keys *会出来乱码

  • 解决方法:默认的RedisTemplate没有过多的设置,redis,对象都是需要序列化的!
  • 这是默认的序列化配置

  • 默认序列化方式是JDK序列化

6.这时候我们就需要自己来写配置类
  • 自己写了后,原来默认的RedisTemplate就会失效

  • 创建一个config

  • @Configurationpublic class RedisConfig {    //编写我们自己的RedisTemplate    @Bean    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {        RedisTemplate template = new RedisTemplate<>();        //这里面到底怎么配置看后面        template.setConnectionFactory(redisConnectionFactory);        return template;    }}


上手测试【自定义的RedisTemplate--实际一般使用】

1.先创建一个pojo,user
//将它变为组件,方便调用@Component@Data@AllArgsConstructor@NoArgsConstructorpublic class User {    private String name;    private Integer age;}
2.测试类写序列化json对象操作【这里默认的序列化是JDK序列化】
    @Test    public void test() throws JsonProcessingException {        //真实开发中一般都使用json来传递对象,所以要序列化json        User user = new User("葛", 3);        //所以要序列化成json对象【变成了json字符串】        String jsonUser = new ObjectMapper().writeValueAsString(user);        redisTemplate.opsForValue().set("user", jsonUser);        System.out.println(redisTemplate.opsForValue().get("user"));    }
  • 如果不用上面的序列化json对象操作会报错!String jsonUser = new ObjectMapper().writeValueAsString(user);

  • 下面是关于对象的保存,但是一般都是用json对象

    • 解决方法:在实体类中序列化即可【在企业中,我们所有的pojo都会序列化!SpringBoot】
    • //将它变为组件,方便调用@Component@Data@AllArgsConstructor@NoArgsConstructorpublic class User implements Serializable {    private String name;    private Integer age;}


3.刚才测试的是默认的序列化(JDK),这时候我们自己写其他方式的序列化
  1. 创建一个config

  2. //这里面到底怎么配置看后面Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer();//配置具体的序列化template.setKeySerializer(objectJackson2JsonRedisSerializer);


    • 多种序列化方式

    1. 写法例子

  3. 自己写很费劲,用已经写好的例子即可

    连接中有不同地方,复制连接中import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer; import java.rmi.UnknownHostException; /** * @author zhangzhixi */@Configurationpublic class RedisConfig {    @Bean    @SuppressWarnings("all")    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {        // 自定义 String Object        RedisTemplate template = new RedisTemplate();        template.setConnectionFactory(redisConnectionFactory);         // Json 序列化配置        Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);        // ObjectMapper 转译        ObjectMapper objectMapper = new ObjectMapper();        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);        objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);         // String 的序列化        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();         // key 采用String的序列化方式        template.setKeySerializer(stringRedisSerializer);        // hash 的key也采用 String 的序列化方式        template.setHashKeySerializer(stringRedisSerializer);        // value 序列化方式采用 jackson        template.setValueSerializer(objectJackson2JsonRedisSerializer);        // hash 的 value 采用 jackson        template.setHashValueSerializer(objectJackson2JsonRedisSerializer);        template.afterPropertiesSet();         return template;    }}


    • 企业中直接拿去使用即可
  4. 编写工具类

    package com.kami.utils;/** * @author zhangzhixi * @date 2021/3/1 23:33 */import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;/** * @author mxz */@Componentpublic final class RedisUtil {    @Autowired    private RedisTemplate redisTemplate;    /**     * 指定缓存失效时间     *     * @param key  键     * @param time 时间(秒)     * @return     */    public boolean expire(String key, long time) {        try {            if (time > 0) {                redisTemplate.expire(key, time, TimeUnit.SECONDS);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 根据 key 获取过期时间     *     * @param key 键(不能为 Null)     * @return 时间(秒) 返回0代表永久有效     */    public long getExpire(String key) {        return redisTemplate.getExpire(key, TimeUnit.SECONDS);    }    /**     * 判断 key 是否存在     *     * @param key 键(不能为 Null)     * @return true 存在 false 不存在     */    public boolean hashKey(String key) {        try {            return redisTemplate.hasKey(key);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 删除缓存     *     * @param key 可以传一个值 或多个     */    public void del(String... key) {        if (key != null && key.length > 0) {            redisTemplate.delete(key[0]);        } else {            redisTemplate.delete(CollectionUtils.arrayToList(key));        }    }    //==================================String====================================    /**     * 普通缓存获取     *     * @param key 键     * @return 值     */    public Object get(String key) {        return key == null ? null : redisTemplate.opsForValue().get(key);    }    /**     * 普通缓存放入     *     * @param key   键     * @param value 值     * @return true 成功 false 失败     */    public boolean set(String key, Object value) {        try {            redisTemplate.opsForValue().set(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 普通缓存放入并设置时间     *     * @param key   键     * @param value 值     * @param time  时间(秒) time > 0 若 time <= 0 将设置无限期     * @return true 成功 false 失败     */    public boolean set(String key, Object value, long time) {        try {            if (time > 0) {                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);            } else {                set(key, value);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 递增     *     * @param key   键     * @param delta 要增加几(大于0)     * @return     */    public long incr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("递增因子必须大于0");        }        return redisTemplate.opsForValue().increment(key, delta);    }    /**     * 递减     *     * @param key   键     * @param delta 要减少几(小于0)     * @return     */    public long decr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("递减因子必须大于0");        }        return redisTemplate.opsForValue().decrement(key, delta);    }    // ================================Map=================================    /**     * HashGet     *     * @param key  键 不能为null     * @param item 项 不能为null     */    public Object hget(String key, String item) {        return redisTemplate.opsForHash().get(key, item);    }    /**     * 获取hashKey对应的所有键值     *     * @param key 键     * @return 对应的多个键值     */    public Map hmget(String key) {        return redisTemplate.opsForHash().entries(key);    }    /**     * HashSet     *     * @param key 键     * @param map 对应多个键值     */    public boolean hmset(String key, Map map) {        try {            redisTemplate.opsForHash().putAll(key, map);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * HashSet 并设置时间     *     * @param key  键     * @param map  对应多个键值     * @param time 时间(秒)     * @return true成功 false失败     */    public boolean hmset(String key, Map map, long time) {        try {            redisTemplate.opsForHash().putAll(key, map);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 向一张hash表中放入数据,如果不存在将创建     *     * @param key   键     * @param item  项     * @param value 值     * @return true 成功 false失败     */    public boolean hset(String key, String item, Object value) {        try {            redisTemplate.opsForHash().put(key, item, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 向一张hash表中放入数据,如果不存在将创建     *     * @param key   键     * @param item  项     * @param value 值     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间     * @return true 成功 false失败     */    public 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) {            e.printStackTrace();            return false;        }    }    /**     * 删除hash表中的值     *     * @param key  键 不能为null     * @param item 项 可以使多个 不能为null     */    public void hdel(String key, Object... item) {        redisTemplate.opsForHash().delete(key, item);    }    /**     * 判断hash表中是否有该项的值     *     * @param key  键 不能为null     * @param item 项 不能为null     * @return true 存在 false不存在     */    public boolean hHasKey(String key, String item) {        return redisTemplate.opsForHash().hasKey(key, item);    }    /**     * hash递增 如果不存在,就会创建一个 并把新增后的值返回     *     * @param key  键     * @param item 项     * @param by   要增加几(大于0)     */    public double hincr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, by);    }    /**     * hash递减     *     * @param key  键     * @param item 项     * @param by   要减少记(小于0)     */    public double hdecr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, -by);    }    // ============================set=============================    /**     * 根据key获取Set中的所有值     *     * @param key 键     */    public Set sGet(String key) {        try {            return redisTemplate.opsForSet().members(key);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 根据value从一个set中查询,是否存在     *     * @param key   键     * @param value 值     * @return true 存在 false不存在     */    public boolean sHasKey(String key, Object value) {        try {            return redisTemplate.opsForSet().isMember(key, value);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 将数据放入set缓存     *     * @param key    键     * @param values 值 可以是多个     * @return 成功个数     */    public long sSet(String key, Object... values) {        try {            return redisTemplate.opsForSet().add(key, values);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 将set数据放入缓存     *     * @param key    键     * @param time   时间(秒)     * @param values 值 可以是多个     * @return 成功个数     */    public long sSetAndTime(String key, long time, Object... values) {        try {            Long count = redisTemplate.opsForSet().add(key, values);            if (time > 0) {                expire(key, time);            }            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 获取set缓存的长度     *     * @param key 键     */    public long sGetSetSize(String key) {        try {            return redisTemplate.opsForSet().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 移除值为value的     *     * @param key    键     * @param values 值 可以是多个     * @return 移除的个数     */    public long setRemove(String key, Object... values) {        try {            Long count = redisTemplate.opsForSet().remove(key, values);            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    // ===============================list=================================    /**     * 获取list缓存的内容     *     * @param key   键     * @param start 开始     * @param end   结束 0 到 -1代表所有值     */    public List lGet(String key, long start, long end) {        try {            return redisTemplate.opsForList().range(key, start, end);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 获取list缓存的长度     *     * @param key 键     */    public long lGetListSize(String key) {        try {            return redisTemplate.opsForList().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 通过索引 获取list中的值     *     * @param key   键     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推     */    public Object lGetIndex(String key, long index) {        try {            return redisTemplate.opsForList().index(key, index);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 将list放入缓存     *     * @param key   键     * @param value 值     */    public boolean lSet(String key, Object value) {        try {            redisTemplate.opsForList().rightPush(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @param time  时间(秒)     */    public boolean lSet(String key, Object value, long time) {        try {            redisTemplate.opsForList().rightPush(key, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @return     */    public boolean lSet(String key, List value) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @param time  时间(秒)     * @return     */    public boolean lSet(String key, List value, long time) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 根据索引修改list中的某条数据     *     * @param key   键     * @param index 索引     * @param value 值     * @return     */    public boolean lUpdateIndex(String key, long index, Object value) {        try {            redisTemplate.opsForList().set(key, index, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 移除N个值为value     *     * @param key   键     * @param count 移除多少个     * @param value 值     * @return 移除的个数     */    public long lRemove(String key, long count, Object value) {        try {            Long remove = redisTemplate.opsForList().remove(key, count, value);            return remove;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    // ===============================HyperLogLog=================================    public long pfadd(String key, String value) {        return redisTemplate.opsForHyperLogLog().add(key, value);    }    public long pfcount(String key) {        return redisTemplate.opsForHyperLogLog().size(key);    }    public void pfremove(String key) {        redisTemplate.opsForHyperLogLog().delete(key);    }    public void pfmerge(String key1, String key2) {        redisTemplate.opsForHyperLogLog().union(key1, key2);    }}


    • 我们真实的分发中,或者在你们的公司,一般都可以看到一个公司自己封装RedisUtil

  5. 转到测试类

    @SpringBootTestclass Redis02SpringbootApplicationTests {     @Autowired    // 指定我们自己定义的redis序列化配置    private RedisTemplate redisTemplate;     @Autowired    private RedisUtil redisUtil;    @Test    void test1() {        // 清空数据库        redisTemplate.getConnectionFactory().getConnection().flushDb();         User user = new User("zhangsha", 23);        redisUtil.set("user", user);        System.out.println(redisUtil.get("user"));    }}


    • 这时候注入的RedisTemplate需要导入的是我们的

  6. 结果就是输出前加了转译【不再是乱码】

    1. redis目录中的redis-cle.exe

    2. 执行结果

    关于"SpringBoot整合Redis案例分析"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"SpringBoot整合Redis案例分析"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

    序列 时间 配置 缓存 多个 数据 对象 方式 测试 成功 分析 整合 数据库 索引 案例 案例分析 个数 内容 线程 结果 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 软件开发项目管理注意什么 服务器存放客户端数据 燃火网络技术有限公司招聘 服务器安全内部测试申请 电子支付与网络安全说课 银川app软件开发哪家专业 重头开始软件开发 山西智慧人口gis系统软件开发 什么是多用户访问数据库 软件开发车载显示屏方向 数据库与收银系统区别 智能卡生成系统数据库 网络安全叠加数字货币股票 web服务器可以网站管理么 上位机怎样从数据库获取数据 北京中联加互联网科技 三级网络技术代码 深圳市丰田网络技术公司 公安局开展网络安全教育培训 eclipse安卓数据库 xtop是啥软件开发工程师 东营安卓软件开发解决方案 临沂企业党建软件开发系统 数据库添加冲突 旧手机怎样变成一台服务器 湖州旅游团软件开发 数据库完整性的类型有哪些 ibm服务器16核32g java数据库取64位图片 自然资源部门网络安全工作责任制
    0