在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所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)