Redis_整合SpringBoot

Redis_整合SpringBoot,第1张

概述SpringBoot整合Redis 1. 说明 在SpringBoot 2.X 之后, 原来的 Jedis 被替换为了 lettuce Jedis: 采用的是直连, 多个线程 *** 作的话, 是不安全的, SpringBoot整合Redis

目录SpringBoot整合Redis1. 说明2. 整合测试1. 导入依赖2. 配置连接3. 测试3. 自定义RedisTemplate1. 关于序列化2. 自定义RedisTemplate4. 编写Redis工具类1. 工具类2. 测试

1. 说明

在SpringBoot 2.X 之后,原来的 Jedis 被替换为了 lettuce

Jedis: 采用的是直连,多个线程 *** 作的话,是不安全的,如果想要避免不安全,使用 Jedis pool 连接池,更像BIO模式Lettuce: 采用 Netty,实例可以在多个线程中共享,不存在线程不安全的情况! 可以减少线程数据了,更像NIO模式

源码分析

RedisautoConfiguration

package org.springframework.boot.autoconfigure.data.redis;import java.net.UnkNownHostException;import org.springframework.boot.autoconfigure.EnableautoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.context.propertIEs.EnableConfigurationPropertIEs;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.import;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisOperations;import org.springframework.data.redis.core.Redistemplate;import org.springframework.data.redis.core.StringRedistemplate;@Configuration(proxyBeanMethods = false)@ConditionalOnClass(RedisOperations.class)@EnableConfigurationPropertIEs(RedisPropertIEs.class)@import({ LettuceConnectionConfiguration.class,JedisConnectionConfiguration.class })public class RedisautoConfiguration {   @Bean    //如果redistemplate存在,则默认的模板不生效 ==> 我们可以自己定义一个 来替换这个默认的   @ConditionalOnMissingBean(name = "redistemplate")   public Redistemplate<Object,Object> redistemplate(RedisConnectionFactory redisConnectionFactory)         throws UnkNownHostException {      //默认的 Redistemplate 没有过多的设置,redis 对象都是需要序列化      //两个泛型都是 Object,Object 的类型,我们使用都需要强制转换!      Redistemplate<Object,Object> template = new Redistemplate<>();      template.setConnectionFactory(redisConnectionFactory);      return template;   }   @Bean   @ConditionalOnMissingBean   //由于String是Redis中最常用的,所以单独提出来了一个Bean   public StringRedistemplate stringRedistemplate(RedisConnectionFactory redisConnectionFactory)         throws UnkNownHostException {      StringRedistemplate template = new StringRedistemplate();      template.setConnectionFactory(redisConnectionFactory);      return template;   }}
2. 整合测试1. 导入依赖
<dependency>   <groupID>org.springframework.boot</groupID>   <artifactID>spring-boot-starter-data-redis</artifactID></dependency>

如果要使用连接池,要导入如下依赖

<dependency>   <groupID>org.apache.commons</groupID>   <artifactID>commons-pool2</artifactID></dependency>
2. 配置连接
# 配置Redisspring.redis.host=127.0.0.1spring.redis.port=6379# SpringBoot 2.X 版本使用Lettuce,因此不要配置Jedis!spring.redis.lettuce.pool.max-active=8
3. 测试
package com.wang.redis02srPingboot;import org.junit.jupiter.API.Test;import org.springframework.beans.factory.annotation.autowired;import org.springframework.boot.test.context.SpringBoottest;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.Redistemplate;@SpringBoottestclass Redis02SrPingbootApplicationTests {   @autowired   private Redistemplate redistemplate;   @Test   voID contextLoads() {      // *** 作不同的数据类型      //opsForValue  *** 作字符串 类似 String,其中Bitmap也在这个方法下面,可以.setBit()方法      //opsForList List      //opsForSet set      //opsForHash hashmap      //opsForZset Zset      //opsForGeo geo      //opsForHyperLogLog hyperloglog      /*      redistemplate.opsForValue().setBit("sign",true);       */      //除了基本的 *** 作,我们常用的方法都可以直接通过Redistemplate来 *** 作,比如事务和基本的CRUD      //获取Redis的连接对象      /*      RedisConnection connection = redistemplate.getConnectionFactory().getConnection();      connection.flushAll();       */      redistemplate.opsForValue().set("myKey","我的RedisValue");      System.out.println(redistemplate.opsForValue().get("myKey"));   }}

这里有几点需要注意

String在opsForValue()下,同时,BitMap也被放在了这个方法下面!

用getConnectionFactory().getConnection()获得连接对象,可以对数据库进行清理或者关闭

要使用连接池,除了SpringBoot导入的几个依赖,我们还要导入 commons-pool2 这个依赖,因为Lettuce和Jedis都使用了这个技术进行连接池的实现!

默认的序列化方式是利用JDK进行序列化,会导致中文显示的问题,因此我们有必要自定义Redistemplate

3. 自定义Redistemplate1. 关于序列化

可以看出,没有序列化直接传递对象会报错

正确的写法为
@TestvoID test() throws JsonProcessingException {   //真实的开发一般使用JsON传递对象,这里用SpringBoot自带的Jackson   User user = new User("测试用户",3);   String JsonUser = new ObjectMapper().writeValueAsstring(user);   redistemplate.opsForValue().set("user",JsonUser);   System.out.println(redistemplate.opsForValue().get("user"));}

输出了JsON字符串

或者将实体类序列化,这样就可以输出JAVA对象了
package com.wang.redis02srPingboot.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.stereotype.Component;import java.io.Serializable;@Component@AllArgsConstructor@NoArgsConstructor@Data//在企业中,我们所有哦的pojo都会序列化public class User implements Serializable {    private String name;    private int age;}

2. 自定义Redistemplate

由于SpringBoot默认实现的Redistemplate使用的是JDK的序列化,我们想用自己的序列化方法就要自定义自己的Redistemplate

package com.wang.redis02srPingboot.config;import com.fasterxml.jackson.annotation.JsonautoDetect;import com.fasterxml.jackson.annotation.JsonTypeInfo;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.Jsontype.impl.LaissezFaireSubTypeValIDator;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.net.UnkNownHostException;//固定的模板@Configurationpublic class RedisConfig {    //编写我们自己的Redistemplate    @Bean    public Redistemplate<String,Object> redistemplate(RedisConnectionFactory factory) throws UnkNownHostException {        // 为了我们自己开发方便,一般直接使用 <String,Object>        Redistemplate<String,Object> template = new Redistemplate<>();        template.setConnectionFactory(factory);        // 序列化配置        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);        ObjectMapper objectMapper = new ObjectMapper();        //配置所有的成员变量无需注解就可以完成序列化,这里的 PropertyAccessor 和 Visibility 都是枚举类型        objectMapper.setVisibility(PropertyAccessor.ALL,JsonautoDetect.Visibility.ANY);        //指定序列化的类型,原来的enableDefaultTyPing方法过期了,这里主要指定第二个参数        //NON_FINAL ==> 整个类,除final外的的属性信息都需要被序列化和反序列化        objectMapper.activateDefaultTyPing(LaissezFaireSubTypeValIDator.instance,ObjectMapper.DefaultTyPing.NON_FINAL,JsonTypeInfo.As.WRAPPER_ARRAY);        //使配置的ObjectMapper生效        jackson2JsonRedisSerializer.setobjectMapper(objectMapper);        //配置具体的序列化方式        //String的序列化        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();        //key采用String的序列化方式        template.setKeySerializer(stringRedisSerializer);        //hash的key也采用String的序列化方式        template.setHashKeySerializer(stringRedisSerializer);        //value序列化方式采用jackson        template.setValueSerializer(jackson2JsonRedisSerializer);        //hash的value序列化方式采用jackson        template.setHashValueSerializer(jackson2JsonRedisSerializer);        //使设置的template生效        template.afterPropertIEsSet();        return template;    }}
4. 编写Redis工具类1. 工具类

为了简化 *** 作,我们封装工具类

注意,要把这个类托管到SpringBoot中!

package com.wang.redis02srPingboot.Utils;import org.springframework.beans.factory.annotation.autowired;import org.springframework.beans.factory.annotation.QualifIEr;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.DefaultTypedTuple;import org.springframework.data.redis.core.Redistemplate;import org.springframework.data.redis.core.ZSetoperations;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;@Componentpublic class RedisUtil {    @autowired    @QualifIEr("redistemplate")    private Redistemplate<String,Object> redistemplate;    // ===================== common =====================    /**     * 指定缓存失效的时间     * @param key  键     * @param time 时间(秒)     */    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 键     * @return true存在,false不存在     */    public boolean haskey(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) {            if (key.length == 1) {                redistemplate.delete(key[0]);            } else {                redistemplate.delete(CollectionUtils.arrayToList(key));            }        }    }    /**     * 清除当前数据库的缓存     */    public voID flushdb() {        redistemplate.getConnectionFactory()                .getConnection()                .flushDb();    }    /**     * 清空全部数据库     */    public voID flushall() {        redistemplate.getConnectionFactory()                .getConnection()                .flushAll();    }    /**     * 切换数据库     * @param dbindex   数据库的编号     */    public voID select(int dbindex) {        redistemplate.getConnectionFactory()                .getConnection()                .select(dbindex);    }    // ===================== 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成功,Object value,long time) {        try {            if (time > 0) {                redistemplate.opsForValue().set(key,value,TimeUnit.SECONDS);            } else {                set(key,value);            }            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 递增     * @param key   键     * @param delta 要增加几(大于0)     */    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)     */    public long decr(String key,long delta) {        if (delta < 0) {            throw new RuntimeException("递减因子必须大于0");        }        return redistemplate.opsForValue().increment(key,-delta);    }    // ================================Map=================================    /**     * HashGet     * @param key  键 不能为null     * @param item 项 不能为null     * @return 值     */    public Object hget(String key,String item) {        return redistemplate.opsForHash().get(key,item);    }    /**     * 获取hashKey对应的所有键值     * @param key 键     * @return 对应的多个键值     */    public Map<Object,Object> hmget(String key) {        return redistemplate.opsForHash().entrIEs(key);    }    /**     * HashSet 设置一个或者多个map     * @param key 键     * @param map 对应多个键值     * @return true 成功 false 失败     */    public boolean hmset(String key,Map<String,Object> map) {        try {            redistemplate.opsForHash().putAll(key,map);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * HashSet 设置一个或者多个map并设置时间     * @param key  键     * @param map  对应多个键值     * @param time 时间(秒)     * @return true成功 false失败     */    public boolean hmset(String key,Object> 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,long time) {        try {            redistemplate.opsForHash().put(key,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 hexists(String key,String item) {        return redistemplate.opsForHash().hasKey(key,item);    }    /**     * hash递增 如果不存在,就会创建一个 并把新增后的值返回     * @param key  键     * @param item 项     * @param by   要增加几(大于0)     * @return 274     */    public double hincr(String key,double by) {        return redistemplate.opsForHash().increment(key,by);    }    /**     * hash递减     * @param key  键     * @param item 项     * @param by   要减少记(小于0)     */    public double hdecr(String key,-by);    }    // ============================set=============================    /**     * 根据key获取Set中的所有值     * @param key 键     */    public Set<Object> 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 sexists(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 sadd(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 sadd(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 scard(String key) {        try {            return redistemplate.opsForSet().size(key);        } catch (Exception e) {            e.printstacktrace();            return 0;        }    }    /**     * 移除值为value的元素     * @param key    键     * @param values 值 可以是多个     * @return 移除的个数     */    public long srem(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<Object> lrange(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 llen(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 lindex(String key,long index) {        try {            return redistemplate.opsForList().index(key,index);        } catch (Exception e) {            e.printstacktrace();            return null;        }    }    /**     * rpush 将元素插入队尾     * @param key   键     * @param value 值     */    public boolean rpush(String key,Object value) {        try {            redistemplate.opsForList().rightPush(key,value);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 将元素插入队尾,并设定时间     * @param key   键     * @param value 值     * @param time  时间(秒)     */    public boolean rpush(String key,long time) {        try {            redistemplate.opsForList().rightPush(key,value);            if (time > 0)                expire(key,time);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 将元素插入队尾     * @param key   键     * @param value 值,List类型     */    public boolean rpush(String key,List<Object> value) {        try {            redistemplate.opsForList().rightPushAll(key,List<Object> value,long time) {        try {            redistemplate.opsForList().rightPushAll(key,time);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * lpush 将元素插入队头     * @param key   键     * @param value 值     */    public boolean lpush(String key,Object value) {        try {            redistemplate.opsForList().leftPush(key,value);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 将元素插入队头,并设定时     * @param key   键     * @param value 值     * @param time  时间(秒)     */    public boolean lpush(String key,long time) {        try {            redistemplate.opsForList().leftPush(key,time);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 将元素插入队头     * @param key   键     * @param value 值,List类型     */    public boolean lpush(String key,List<Object> value) {        try {            redistemplate.opsForList().leftPushAll(key,并设定时间     * @param key   键     * @param value 值     * @param time  时间(秒)     */    public boolean lpush(String key,long time) {        try {            redistemplate.opsForList().leftPushAll(key,time);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 根据索引修改List中的某条数据     * @param key   键     * @param index 索引     * @param value 值     */    public boolean lset(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 lrem(String key,long count,Object value) {        try {            Long remove = redistemplate.opsForList().remove(key,count,value);            return remove;        } catch (Exception e) {            e.printstacktrace();            return 0;        }    }    // ============================Zset=============================    /**     * 添加一个Zset     * @param key   键     * @param value 值     * @param score 编号     * @return      成功 true,失败false     */    public boolean zadd (String key,Double score) {        try {            redistemplate.opsForZSet().add(key,score);            return true;        } catch (Exception e) {            e.printstacktrace();            return false;        }    }    /**     * 批量添加Zset     * @param key   键     * @param map   value-score键值对     * @return      添加的个数     */    public long zadd (String key,Map<Object,Double> map) {        try {            Set<ZSetoperations.TypedTuple<Object>> set = new HashSet<>();            for (Map.Entry<Object,Double> entry : map.entrySet()) {                DefaultTypedTuple defaultTypedTuple = new DefaultTypedTuple(entry.getKey(),entry.getValue());                set.add(defaultTypedTuple);            }            Long count = redistemplate.opsForZSet().add(key,set);            return count;        } catch (Exception e) {            e.printstacktrace();            return 0;        }    }}
2. 测试
package com.wang.redis02srPingboot;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.wang.redis02srPingboot.Utils.RedisUtil;import com.wang.redis02srPingboot.pojo.User;import org.junit.jupiter.API.Test;import org.springframework.beans.factory.annotation.autowired;import org.springframework.beans.factory.annotation.QualifIEr;import org.springframework.boot.test.context.SpringBoottest;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.Redistemplate;@SpringBoottestclass Redis02SrPingbootApplicationTests {   @autowired   @QualifIEr("redistemplate")   private Redistemplate redistemplate;   @autowired   private RedisUtil redisUtil;   @Test   voID contextLoads() {      // *** 作不同的数据类型      //opsForValue  *** 作字符串 类似 String,"我的RedisValue");      System.out.println(redistemplate.opsForValue().get("myKey"));   }   @Test   voID test() throws JsonProcessingException {      //真实的开发一般使用JsON传递对象,这里用SpringBoot自带的Jackson      User user = new User("测试用户",3);      String JsonUser = new ObjectMapper().writeValueAsstring(user);      redistemplate.opsForValue().set("user",JsonUser);      System.out.println(redistemplate.opsForValue().get("user"));   }   //利用我们自己封装的工具类测试   @Test   voID test1() {      redisUtil.set("name","测试用户2");      System.out.println(redisUtil.get("name"));   }}
总结

以上是内存溢出为你收集整理的Redis_整合SpringBoot全部内容,希望文章能够帮你解决Redis_整合SpringBoot所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1216991.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存