当前位置: 首页 > news >正文

Java连接Redis和SpringBoot整合Redis

1. Java连接Redis

思考:我们之前操作redis都是通过命令行的客户端来操作。在开发时都是通过java项目操作redis

java提高连接redis的方式为jedis。我们需要遵循jedis协议。
java提供连接mysql的方式为jdbc。


1.1 单机模式

引入依赖

<!--引入java连接redis的驱动--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version></dependency>

若使用3.8.1的依赖,jedis中的setex方法会被划去

<dependency><groupId>repMaven.redis.clients</groupId><artifactId>jedis</artifactId><version>3.8.0</version>
</dependency>

编写代码

package com.zmq;import redis.clients.jedis.Jedis;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** @program: redis1* @description: java连接redis* @author: zmq**/
public class Test01 {public static void main(String[] args) {//连接redis的信息,默认连接本地的redis端口 端口号6379,所有关于redis操作的功能都在Jedis类中Jedis jedis=new Jedis("172.16.7.112",6379);//关于key的命令//获取所有key值Set<String> keys = jedis.keys("*");System.out.println("获取所有的keys:"+keys);//删除key的个数Long del = jedis.del("ll", "l1");System.out.println("删除key的个数"+del);//判定指定的key是否存在Boolean k4 = jedis.exists("k4");System.out.println("判断指定的k4是否存在"+k4);//给key指定过期时间jedis.expire("lll",100);//string类型//添加数据String set = jedis.set("k1", "v1");System.out.println("存入k1的值"+set);//获取指定的值String s = jedis.get("k1");System.out.println("获取指定k1的值"+s);//判断指定的值是否存在,若不存在,就创建Long k2 = jedis.setnx("k2", "v2");System.out.println("如果k2不存在,则设置k2的值:"+k2);jedis.setnx("k3","110");//值递增Long k3 = jedis.incr("k3");System.out.println("k3的值加1"+k3);//值递减Long k31 = jedis.decr("k3");System.out.println("k3的值减1"+k31);//创建key并指定过期时间String setex = jedis.setex("k4", 100, "v3");System.out.println(setex);//关于hash的命令//存值long hset = jedis.hset("h1", "name", "lay");System.out.println("存入h1的键值对:"+hset);//设置一个mapMap<String,String> map=new HashMap<>();map.put("name","章三");map.put("age","18");long h2 = jedis.hset("h2", map);System.out.println("存入h2的键值对"+h2);//取值String hget = jedis.hget("h2", "name");System.out.println("获取h2中name的值"+hget);//获取key中的素有键值对的值Map<String, String> h21 = jedis.hgetAll("h2");System.out.println("获取h2中所有键值对的值"+h21);//获取所有哈希表中的值List<String> h22 = jedis.hvals("h2");System.out.println(h22);//获取所有哈希表中所有的字段Set<String> h23 = jedis.hkeys("h2");System.out.println(h23);}
}
  • 关于连接redis的信息
  1. 连接redis的信息,默认连接本地的redis端口 端口号6379

所有关于redis操作的功能都在Jedis类中

Jedis jedis=new Jedis("172.16.8.110",6379);
  • 关于key的命令
  1. 获取所有key值——keys~~~~keys
 //获取所有key值Set<String> keys = jedis.keys("*");System.out.println("获取所有的keys:"+keys);
  1. 删除key的个数——del~~~~del
 //删除key的个数Long del = jedis.del("ll", "l1");System.out.println("删除key的个数"+del);
  1. 判定指定的可以是否存在——exists~~~~exists
   //判定指定的key是否存在Boolean k4 = jedis.exists("k4");System.out.println("判断指定的k4是否存在"+k4);
  1. 创建key并给key指定过期时间——expire~~~~expire
        //给key指定过期时间jedis.expire("lll",100);
  • 关于字符串String的命令
  1. 添加数据——set~~~~set
//添加数据String set = jedis.set("k1", "v1");System.out.println("存入k1的值"+set);
  1. 获取指定的值——get~~~~get
//获取指定的值String s = jedis.get("k1");System.out.println("获取指定k1的值"+s);
  1. 判断指定的值是否存在,若不存在,就创建——setnx~~~~setnx
        //判断指定的值是否存在,若不存在,就创建Long k2 = jedis.setnx("k2", "v2");System.out.println("如果k2不存在,则设置k2的值:"+k2);
  1. 值递增,每次加1——incr~~~~incr
        jedis.setnx("k3","110");//值递增Long k3 = jedis.incr("k3");System.out.println("k3的值加1"+k3);
  1. 值递减,每次减1——decr~~~~decr
        //值递减Long k31 = jedis.decr("k3");System.out.println("k3的值减1"+k31);
  1. 创建key并指定过期时间——setex~~~~setex
        //创建key并指定过期时间String setex = jedis.setex("k4", 100, "v3");System.out.println(setex);
  • 关于hash的命令
  1. 存值1——hset~~~~hset
//存值long hset = jedis.hset("h1", "name", "lay");System.out.println("存入h1的键值对:"+hset);
  1. 存值2,存入map——hset~~~~hset
        //设置一个mapMap<String,String> map=new HashMap<>();map.put("name","章三");map.put("age","18");long h2 = jedis.hset("h2", map);System.out.println("存入h2的键值对"+h2);
  1. 存值2,存入map

  2. 获取指定的key中指定的键值对的value值——hget~~~~hget

        //取值String hget = jedis.hget("h2", "name");System.out.println("获取h2中name的值"+hget);
  1. 获取key中所有键值对的值——hgetAll~~~~hgetAll
        //获取key中的素有键值对的值Map<String, String> h21 = jedis.hgetAll("h2");System.out.println("获取h2中所有键值对的值"+h21);
  1. 获取哈希表中所有的值——hvals~~~~hvals
        //获取所有哈希表中的值List<String> h22 = jedis.hvals("h2");System.out.println(h22);
  1. 获取哈希表中所有的字段——hkeys~~~~hkeys
        //获取所有哈希表中所有的字段Set<String> h23 = jedis.hkeys("h2");System.out.println(h23);

1.2 集群模式

  • 连接redis的信息
 public static void main(String[] args) {Set<HostAndPort> nodes=new HashSet<>();nodes.add(new HostAndPort("# 1. Java连接Redis> 思考:我们之前操作redis都是通过命令行的客户端来操作。在开发时都是通过java项目操作redisjava提高连接redis的方式jedis。我们需要遵循jedis协议。****## 1.1 单机模式**引入依赖**```xml
<!--引入java连接redis的驱动--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version></dependency>

若使用3.8.1的依赖,jedis中的setex方法会被划去

<dependency><groupId>repMaven.redis.clients</groupId><artifactId>jedis</artifactId><version>3.8.0</version>
</dependency>

编写代码

package com.zmq;import redis.clients.jedis.Jedis;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** @program: redis1* @description: java连接redis* @author: zmq**/
public class Test01 {public static void main(String[] args) {//连接redis的信息,默认连接本地的redis端口 端口号6379,所有关于redis操作的功能都在Jedis类中Jedis jedis=new Jedis("172.16.7.112",6379);//关于key的命令//获取所有key值Set<String> keys = jedis.keys("*");System.out.println("获取所有的keys:"+keys);//删除key的个数Long del = jedis.del("ll", "l1");System.out.println("删除key的个数"+del);//判定指定的key是否存在Boolean k4 = jedis.exists("k4");System.out.println("判断指定的k4是否存在"+k4);//给key指定过期时间jedis.expire("lll",100);//string类型//添加数据String set = jedis.set("k1", "v1");System.out.println("存入k1的值"+set);//获取指定的值String s = jedis.get("k1");System.out.println("获取指定k1的值"+s);//判断指定的值是否存在,若不存在,就创建Long k2 = jedis.setnx("k2", "v2");System.out.println("如果k2不存在,则设置k2的值:"+k2);jedis.setnx("k3","110");//值递增Long k3 = jedis.incr("k3");System.out.println("k3的值加1"+k3);//值递减Long k31 = jedis.decr("k3");System.out.println("k3的值减1"+k31);//创建key并指定过期时间String setex = jedis.setex("k4", 100, "v3");System.out.println(setex);//关于hash的命令//存值long hset = jedis.hset("h1", "name", "lay");System.out.println("存入h1的键值对:"+hset);//设置一个mapMap<String,String> map=new HashMap<>();map.put("name","章三");map.put("age","18");long h2 = jedis.hset("h2", map);System.out.println("存入h2的键值对"+h2);//取值String hget = jedis.hget("h2", "name");System.out.println("获取h2中name的值"+hget);//获取key中的素有键值对的值Map<String, String> h21 = jedis.hgetAll("h2");System.out.println("获取h2中所有键值对的值"+h21);//获取所有哈希表中的值List<String> h22 = jedis.hvals("h2");System.out.println(h22);//获取所有哈希表中所有的字段Set<String> h23 = jedis.hkeys("h2");System.out.println(h23);}
}
  • 关于连接redis的信息
  1. 连接redis的信息,默认连接本地的redis端口 端口号6379

所有关于redis操作的功能都在Jedis类中

Jedis jedis=new Jedis("172.16.8.110",6379);
  • 关于key的命令
  1. 获取所有key值——keys~~~~keys
 //获取所有key值Set<String> keys = jedis.keys("*");System.out.println("获取所有的keys:"+keys);
  1. 删除key的个数——del~~~~del
 //删除key的个数Long del = jedis.del("ll", "l1");System.out.println("删除key的个数"+del);
  1. 判定指定的可以是否存在——exists~~~~exists
   //判定指定的key是否存在Boolean k4 = jedis.exists("k4");System.out.println("判断指定的k4是否存在"+k4);
  1. 创建key并给key指定过期时间——expire~~~~expire
        //给key指定过期时间jedis.expire("lll",100);
  • 关于字符串String的命令
  1. 添加数据——set~~~~set
//添加数据String set = jedis.set("k1", "v1");System.out.println("存入k1的值"+set);
  1. 获取指定的值——get~~~~get
//获取指定的值String s = jedis.get("k1");System.out.println("获取指定k1的值"+s);
  1. 判断指定的值是否存在,若不存在,就创建——setnx~~~~setnx
        //判断指定的值是否存在,若不存在,就创建Long k2 = jedis.setnx("k2", "v2");System.out.println("如果k2不存在,则设置k2的值:"+k2);
  1. 值递增,每次加1——incr~~~~incr
        jedis.setnx("k3","110");//值递增Long k3 = jedis.incr("k3");System.out.println("k3的值加1"+k3);
  1. 值递减,每次减1——decr~~~~decr
        //值递减Long k31 = jedis.decr("k3");System.out.println("k3的值减1"+k31);
  1. 创建key并指定过期时间——setex~~~~setex
        //创建key并指定过期时间String setex = jedis.setex("k4", 100, "v3");System.out.println(setex);
  • 关于hash的命令
  1. 存值1——hset~~~~hset
//存值long hset = jedis.hset("h1", "name", "lay");System.out.println("存入h1的键值对:"+hset);
  1. 存值2,存入map——hset~~~~hset
        //设置一个mapMap<String,String> map=new HashMap<>();map.put("name","章三");map.put("age","18");long h2 = jedis.hset("h2", map);System.out.println("存入h2的键值对"+h2);
  1. 存值2,存入map

  2. 获取指定的key中指定的键值对的value值——hget~~~~hget

        //取值String hget = jedis.hget("h2", "name");System.out.println("获取h2中name的值"+hget);
  1. 获取key中所有键值对的值——hgetAll~~~~hgetAll
        //获取key中的素有键值对的值Map<String, String> h21 = jedis.hgetAll("h2");System.out.println("获取h2中所有键值对的值"+h21);
  1. 获取哈希表中所有的值——hvals~~~~hvals
        //获取所有哈希表中的值List<String> h22 = jedis.hvals("h2");System.out.println(h22);
  1. 获取哈希表中所有的字段——hkeys~~~~hkeys
        //获取所有哈希表中所有的字段Set<String> h23 = jedis.hkeys("h2");System.out.println(h23);

1.2 集群模式

  • 连接redis的信息
 public static void main(String[] args) {Set<HostAndPort> nodes=new HashSet<>();nodes.add(new HostAndPort("192.168.112.189",7001));nodes.add(new HostAndPort("192.168.112.189",7002));nodes.add(new HostAndPort("192.168.112.189",7003));nodes.add(new HostAndPort("192.168.112.189",7004));nodes.add(new HostAndPort("192.168.112.189",7005));nodes.add(new HostAndPort("192.168.112.189",7006));JedisCluster jedisCluster=new JedisCluster(nodes);jedisCluster.set("k5","666");System.out.println(jedisCluster.get("k5"));}

适合ssm项目

2. springboot整合redis

starter启动依赖——包含自动装配类,完成相应的装配功能

在这里插入图片描述

  • 有关依赖——spring-boot-starter-data-redis
<!--引入了redis整合springboot 的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
  • 修改配置文件
#单机模式的配置
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器地址
spring.redis.host=IP地址
#Redis数据库索引(默认为0)
spring.redis.database=1
#连接池最大连接数(使用负值表示没有限制)
#spring.redis.jedis.pool.max-active=100
#连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000ms
  • 使用

springboot整合redis时封装了两个工具类:StringRedisTemplate和RedisTemplate——springboot中用于操作redsi的类

StringRedisTemplate它是RedisTemplate的子类。StringRedisTemplate里面只能存放字符串的内容

2.1 StringRedisTemplate

在测试类中进行相关方法的测试

首先需要自动注入StringRedisTemplate类

StringRedisTemplate类:是RedisTemplate的子类,key和value均为字符串

在这里插入图片描述

RedisTemplate中定义了5中数据结构操作

stringRedisTemplate.opsForValue();//操作字符串stringRedisTemplate.opsForHash();//操作hashstringRedisTemplate.opsForList();//操作列表stringRedisTemplate.opsForSet();//操作无序集合stringRedisTemplate.opsForZSet();//操作有序集合——有序是score的有序
  • 关于key的操作
  1. 获取所有的key——keys
//获取所有的keySet<String> keys = stringRedisTemplate.keys("*");System.out.println("所有的key:"+keys);

返回值为Set集合,因为key唯一

  1. 是否删除指定的key,返回值为boolean——delete——释放锁
        //删除指定的key——返回值为booleanBoolean k1 = stringRedisTemplate.delete("k1");System.out.println("是否删除指定的k1:"+k1);

返回值为boolean

  1. 是否存在指定key——haskey
        //判断指定的key是否存在——返回值为booleanBoolean k11 = stringRedisTemplate.hasKey("k1");System.out.println("是否存在k1:"+k11);

返回值为boolean

  1. 是否设置过期时间——expire
        //设置过期时间——返回值为booleanBoolean k12 = stringRedisTemplate.expire("k1", 10, TimeUnit.HOURS);System.out.println("是否设置过期时间:"+k12);

返回值为boolean

  1. 根据key获取过期时间——getExpire
//根据key获取过期时间  stringRedisTemplate.getExpire("test");
  1. 根据key获取过期时间并换算成指定的单位——getExpire
//根据key获取过期时间并换算成指定单位 stringRedisTemplate.getExpire("test",TimeUnit.SECONDS); 

getExpire(“test”,TimeUnit.SECONDS)

//关于key的操作@Testvoid testKeys() {//获取所有的keySet<String> keys = stringRedisTemplate.keys("*");System.out.println("所有的key:"+keys);//删除指定的key——返回值为booleanBoolean k1 = stringRedisTemplate.delete("k1");System.out.println("是否删除指定的k1:"+k1);//判断指定的key是否存在——返回值为booleanBoolean k11 = stringRedisTemplate.hasKey("k1");System.out.println("是否存在k1:"+k11);//设置过期时间——返回值为booleanBoolean k12 = stringRedisTemplate.expire("k1", 10, TimeUnit.HOURS);System.out.println("是否设置过期时间:"+k12);}
  • 关于String的操作
  1. 得到操作字符串的类对象——opsForValue
//得到操作字符串的类对象ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
  1. 存放数据——set
        //存放数据---set(k,v)opsForValue.set("k1","v1");
  1. 存放数据,含有过期时间——set
 //存放数据--setex(k,second,v)opsForValue.set("k2","20",2,TimeUnit.MINUTES); 
  1. 存放数据,先判断是否已存在——setIfAbsent——分布式锁
//存放数据--setnx(k,v)Boolean aBoolean = opsForValue.setIfAbsent("k3", "v3", 2, TimeUnit.MINUTES);System.out.println("是否设置成功:"+aBoolean);  
  1. 根据key获取val——get
//获取指定的元素String k1 = opsForValue.get("k1");System.out.println("获取指定的元素:"+k1);
  1. 自增——incream
//自增Long k21 = opsForValue.increment("k2");System.out.println("自增1:"+k21);
  1. 自增指定长度——incream
        //自增指定长度Long k2 = opsForValue.increment("k2", 10);System.out.println("获取指定的元素:"+k2);
  1. 自减指定长度——incream,数值为负数即可
        //自减Long k22 = opsForValue.increment("k2", -1);System.out.println("获取指定的元素:"+k22);
  1. 重新赋值——getAndSet
        //重新赋值String andSet = opsForValue.getAndSet("k1", "vvvv");System.out.println("重新赋值:"+andSet);
 //关于String的操作: 在封装的StringRedisTemplate类对应每种数据类型的操作 对应相应的类来完成@Testvoid testString() {//得到操作字符串的类对象ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();//存放数据---set(k,v)opsForValue.set("k1","v1");//存放数据--setex(k,second,v)opsForValue.set("k2","20",2,TimeUnit.MINUTES);//存放数据--setnx(k,v)Boolean aBoolean = opsForValue.setIfAbsent("k3", "v3", 2, TimeUnit.MINUTES);System.out.println("是否设置成功:"+aBoolean);//获取指定的元素String k1 = opsForValue.get("k1");System.out.println("获取指定的元素:"+k1);//自增Long k21 = opsForValue.increment("k2");System.out.println("自增1:"+k21);//自增指定长度Long k2 = opsForValue.increment("k2", 10);System.out.println("获取指定的元素:"+k2);//自减Long k22 = opsForValue.increment("k2", -1);System.out.println("获取指定的元素:"+k22);//重新赋值String andSet = opsForValue.getAndSet("k1", "vvvv");System.out.println("重新赋值:"+andSet);}
  • 关于Hash的操作——适合存放对象,操作属性方便
  1. 获取操作字符串的类对象——opsForHash
//获取操作字符串的类对象HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
  1. 存放数据——put
        //存放数据  hset(key,field,value)forHash.put("user","name","ykq");
  1. 存放map集合——putAll
        //存放mapMap<String,String> map=new HashMap<>();map.put("age","18");map.put("adrress","北京");forHash.putAll("user",map);
  1. 获取指定的元素——get
        //获取指定的元素  hget(key,field)Object o = forHash.get("user", "name");System.out.println("获取指定的元素:"+o);
  1. 获取所有的元素——entries
        Map<Object, Object> user = forHash.entries("user");System.out.println("获取所有的元素:"+user);
  1. 获取所有的key——keys
        Set<Object> user1 = forHash.keys("user");System.out.println("获取所有的key:"+user1);
  1. 获取所有的value——values
        List<Object> user2 = forHash.values("user");System.out.println("获取所有的value:"+user2);
 //关于Hash的操作@Testpublic void testHash(){//获取操作字符串的类对象HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();//存放数据  hset(key,field,value)forHash.put("user","name","ykq");//存放mapMap<String,String> map=new HashMap<>();map.put("age","18");map.put("adrress","北京");forHash.putAll("user",map);//获取指定的元素  hget(key,field)Object o = forHash.get("user", "name");System.out.println("获取指定的元素:"+o);Map<Object, Object> user = forHash.entries("user");System.out.println("获取所有的元素:"+user);Set<Object> user1 = forHash.keys("user");System.out.println("获取所有的key:"+user1);List<Object> user2 = forHash.values("user");System.out.println("获取所有的value:"+user2);}

2.2 RedisTemplate

它属于StringRedisTemplate的父类,它的泛型默认都是Object。它可以直接存储任意类型的key和value

序列化

//自动注入StringRedisTemplate模板@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void test1(){ValueOperations valueOperations = redisTemplate.opsForValue();//第一次存值valueOperations.set("k111","v11");//此时出现乱码,且在RedisPlus图形化工具中,并不能点击该key,显示该key不存在System.out.println(valueOperations.get("k111"));//org.springframework.data.redis.serializer.SerializationException: 会出现序列化异常,需要实体类User实现序列化接口//第二次存值valueOperations.set("k12",new User("zxy",18));//把内存中的数据存入磁盘---序列化过程}

上述代码显示的问题:

  1. 第一次存值,可以成功运行,但出现乱码,且在RedisPlus图形化工具中,并不能点击该key,显示该key不存在
  2. 第二次存值,报错:序列化异常,需要实体类User实现序列化接口

分析key出现乱码

  1. key值为乱码:所以key需要序列化,而key默认的序列化方式为JDK序列化,为二进制

  2. StringRedisTemplate类并没有出现乱码——因为他有自己的序列化方式,没有实现JDK序列化

  3. 解决:设置key的序列化方式

//设置key的序列化方式redisTemplate.setKeySerializer(new StringRedisSerializer());

此时,解决key的乱码问题,图形化界面的key可以点击查看,发现value值为乱码:

  1. value值为乱码:value默认的序列化方式也为JDK序列化JDK序列化方式需要实现序列化接口

  2. StringRedisTemplate类并没有出现乱码——因为他有自己的序列化方式,没有实现JDK序列化

  3. 解决:设置value的序列化方式

        //2. 设置value的序列化方式redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));

使用Jackson2JsonRedisSerializer序列化的时候,如果实体类上没有set方法反序列化会报错。

  • 若使用FastJsonRedisSerializer序列化方式,需要引入fastjson依赖
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency>

如果使用RedisTemplate,每次都需要人为指定key和value的序列化,所以抽象出指定key和value序列化的工具类

  • 配置文件

    @Configuration
    public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(redisConnectionFactory);template.setKeySerializer(jackson2JsonRedisSerializer);template.setValueSerializer(jackson2JsonRedisSerializer);template.setHashKeySerializer(jackson2JsonRedisSerializer);template.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
    }
    

2.3 集群模式

修改配置文件即可

#集群模式
spring.redis.cluster.nodes=192.168.112.189:7006,192.168.112.189:7001,192.168.112.189:7002,192.168.112.189:7003,192.168.112.189:7004,192.168.112.189:7005

2.4 二者区别

  • StringRedisTemplate和RedisTemplate的区别
  • 前者集成后者
  • 数据不共通的。即StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据
  • SDR默认采用的序列化有两种。一种是String的序列化策略,一种是JDK的序列化策略;
  • StringRedisTemplate默认采用的是String 的序列化策略,保存的key和value都是采用的该策略序列化并保存的
  • RedisTemplate默认采用的是JDK的序列化策略,保存的 key和value都是采用此策略序列化并保存的

相关文章:

Java连接Redis和SpringBoot整合Redis

1. Java连接Redis 思考&#xff1a;我们之前操作redis都是通过命令行的客户端来操作。在开发时都是通过java项目操作redis java提高连接redis的方式为jedis。我们需要遵循jedis协议。 java提供连接mysql的方式为jdbc。 1.1 单机模式 引入依赖 <!--引入java连接redis的驱动…...

快速入门Jupyter notebook

快速入门 Jupyter notebook 一、前言&#xff08;一&#xff09;优点&#xff08;二&#xff09;特点&#xff08;三&#xff09;调用运行&#xff08;四&#xff09;新建 二、认识界面快捷键&#xff08;一&#xff09;三种模式&#xff08;1&#xff09;蓝色模式&#xff1a;…...

Java反射详细学习笔记

动态代理 特点 : 无侵入式的给代码增加额外的功能 ; 代理里面就是对象要被代理的方法 ; 通过接口保证,后面的对象和代理需要实现同一个接口 &#xff0c; 接口中就是被代理的所有方法 ; 如何为java对象创建一个代理 : java.lang.reflect.Proxy类 : 提供了为对象产生代理对象的…...

区块链在艺术市场中的创新:数字艺术品的溯源与版权保护

随着数字技术的迅猛发展&#xff0c;数字艺术品正逐渐成为艺术市场的重要组成部分。然而&#xff0c;数字艺术品的复制和版权问题日益突出&#xff0c;传统的版权管理方式面临挑战。区块链技术作为一种去中心化的分布式账本技术&#xff0c;为解决这些问题提供了新的可能性。本…...

智能编程,一触即发:使用AIGC优化CSS——提升前端开发效率与质量

文章目录 一、AIGC在CSS优化中的应用场景智能代码生成自动布局调整性能优化建议样式和色彩建议 二、使用AIGC优化CSS的具体步骤明确需求选择AIGC工具输入描述或设计稿审查和调整集成和测试 三、AIGC优化CSS的优势与挑战优势&#xff1a;挑战&#xff1a; 《CSS创意项目实践&…...

鸿蒙界面开发

界面开发 //构建 → 界面 build() {//行Row(){//列Column(){//文本 函数名(参数) 对象.方法名&#xff08;参数&#xff09; 枚举名.变量名Text(this.message).fontSize(40)//设置文本大小.fontWeight(FontWeight.Bold)//设置文本粗细.fontColor(#ff2152)//设置文本颜色}.widt…...

【JavaScript】use strict

“use strict” 声明时&#xff0c;代码将会在严格模式下执⾏。严格模式包含了⼀些额外的规则和限制。 使⽤ “use strict” 的主要作⽤包括&#xff1a; 变量必须声明后再使⽤&#xff0c;不能通过不使⽤关键字创建全局变量不能通过 delete 操作符删除变量&#xff08;包括对…...

Linux云计算 |【第一阶段】SERVICES-DAY3

主要内容&#xff1a; 分离解析介绍、NTP时间服务、基础邮件服务&#xff08;MX记录&#xff09;、部署postfix邮件服务器、自定义YUM仓库 实操提前准备&#xff1a; ① 设置SELinux、关闭防火墙服务&#xff08;两台主机&#xff09; [rootsvr7 ~]# getenforce Permissive …...

Java面试八股之Spring-boot-starter-parent的作用是什么

Spring-boot-starter-parent的作用是什么 spring-boot-starter-parent 是Spring Boot项目中的一个特殊POM&#xff08;Project Object Model&#xff09;&#xff0c;它主要的作用是提供一系列默认的配置和依赖管理&#xff0c;以便简化项目的构建过程。以下是spring-boot-sta…...

Python 和 Boto3 生成 Amazon S3 对象的 HTTPS URL

在使用 Amazon S3 存储服务时,我们经常需要获取存储桶中对象的 HTTPS URL。这篇博文将详细介绍如何使用 Python 和 Boto3 库来实现这一功能。 背景 Amazon S3(Simple Storage Service)是一种广泛使用的云存储服务。在许多场景中,我们需要获取 S3 存储桶中对象的公开访问 …...

V-bind动态绑定style的案例集合

目录 绑定对象 绑定数组 绑定函数 V-bind 动态绑定 Class 的案例集合-CSDN博客 绑定对象 示例代码如下: <!--html--> <p :style="{width:widthVal,height:heightVal,border:borderVal}">段落</p> <!--js--> data(){ ret…...

深度学习守护夜行安全:夜视行人检测系统详解

基于深度学习的夜视行人检测系统&#xff08;UI界面YOLOv8/v7/v6/v5代码训练数据集&#xff09; 引言 夜视行人检测在自动驾驶和智能监控中至关重要。然而&#xff0c;由于光线不足&#xff0c;夜间行人检测面临巨大挑战。深度学习技术&#xff0c;特别是YOLO&#xff08;You…...

亚信安慧AntDB亮相PostgreSQL中国技术大会,获“数据库最佳应用奖”并分享数据库应用实践

7月12日&#xff0c;第13届PostgreSQL中国技术大会在杭州顺利举办&#xff0c;亚信安慧AntDB数据库荣获“数据库最佳应用奖”。大会上&#xff0c;亚信安慧AntDB数据库同事带来《基于AntDB的CRM系统全域数据库替换实践》和《亚信安慧AntDB数据库运维之路》两场精彩演讲&#xf…...

如何减少白屏的时间

前端性能优化是前端开发中一个重要环节&#xff0c;它包括很多内容&#xff0c;其中页面的白屏时间是用户最初接触到的部分&#xff0c;白屏时间过长会显著影响用户的留存率和转换率。 我们以一个 APP 内嵌 Webview 打开页面作为例子&#xff0c;来分析页面打开过程以及可优化…...

科研成果 | 高精尖中心取得高性能区块链交易调度技术突破

近日&#xff0c;未来区块链与隐私计算高精尖创新中心研究团队在区块链交易效率方面取得突破性进展&#xff0c;最新成果“高性能区块链交易调度引擎”首次为长安链带来高并行度的交易调度&#xff0c;充分利用现有计算资源&#xff0c;显著提升长安链交易处理速度。 随着区块…...

go语言学习文档精简版

Go语言是一门开源的编程语言&#xff0c;目的在于降低构建简单、可靠、高效软件的门槛。Go平衡了底层系统语言的能力&#xff0c;以及在现代语言中所见到的高级特性。 你好&#xff0c;Go package main // 程序组织成包import "fmt" // fmt包用于格式化输出数据// …...

立元科技-Java面经

面试时间&#xff1a;2024年2月13日 面试地点&#xff1a;线下 面试流程&#xff1a;一轮面试 首先写了点笔试题&#xff0c;但是人家根本不看&#xff08;这个也就一面&#xff09; &#xff08;聊的还行&#xff0c;但是公司环境不是特别的好&#xff0c;一次面试&#x…...

OpenGL入门第六步:材质

目录 结果显示 材质介绍 函数解析 具体代码 结果显示 材质介绍 当描述一个表面时,我们可以分别为三个光照分量定义一个材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)。通过为每个分量指定一个颜色,…...

新版SpringSecurity5.x使用与配置

目录 一、了解SpringSecurity 1.1 什么是Spring Security&#xff1f; 1.2 Spring Security功能 1.3 Spring Security原理 1.4 RABC (Role-Based Access Control) 二、SpringSecurity简单案例 2.1 引入SpringSecurity依赖 2.2 创建一个简单的Controller 三、SpringSecu…...

JavaScript实战 - JavaScript 中实现线程锁

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有需要我的支持&#xff0c;请私信或评论留言&#xff01; 前言&#xff1a; …...

基于PaddleClas的人物年龄分类项目

目录 一、任务概述 二、算法研发 2.1 下载数据集 2.2 数据集预处理 2.3 安装PaddleClas套件 2.4 算法训练 2.5 静态图导出 2.6 静态图推理 三、小结 一、任务概述 最近遇到个需求&#xff0c;需要将图像中的人物区分为成人和小孩&#xff0c;这是一个典型的二分类问题…...

20240725java的Controller、DAO、DO、Mapper、Service层、反射、AOP注解等内容的学习

在Java开发中&#xff0c;‌controller、‌dao、‌do、‌mapper等概念通常与MVC&#xff08;‌Model-View-Controller&#xff09;‌架构和分层设计相关。‌这些概念各自承担着不同的职责&#xff0c;‌共同协作以构建和运行一个应用程序。‌以下是这些概念的解释&#xff1a;‌…...

dynslam的安装

1. 安装opencv 2.4.9 下载opencv2.4.9 apt-get install build-essential apt-get install libgtk2.0-dev libavcodec-dev libavformat-dev libtiff4-dev libswscale-dev libjasper-dev apt-get install cmake apt-get install pkg-config 进入安装包文件&#xff1a; m…...

stats 监控 macOS 系统

Stats 监控 macOS 系统 CPU 利用率GPU 利用率内存使用情况磁盘利用率网络使用情况电池电量 brew install stats参考 stats github...

后端面试题日常练-day05 【Java基础】

题目 希望这些选择题能够帮助您进行后端面试的准备&#xff0c;答案在文末 在Java中&#xff0c;以下哪个关键字用于表示方法重写&#xff08;Override&#xff09;&#xff1f; a) override b) overrule c) overwrite d) supercede Java中的HashMap和Hashtable有什么区别&am…...

mac|安装PostgreSQL

1、官网下载&#xff1a;EDB: Open-Source, Enterprise Postgres Database Management 选择需要的版本&#xff1a; 双击得到的.dmg文件 双击&#xff0c;弹窗选择打开&#xff0c;一路next&#xff0c;然后输入你要设置的密码&#xff0c;默认账号名字为&#xff1a;postgres…...

内网对抗-隧道技术篇防火墙组策略FRPNPSChiselSocks代理端口映射C2上线

知识点&#xff1a; 1、隧道技术篇-传输层-工具项目-Frp&Nps&Chisel 2、隧道技术篇-传输层-端口转发&Socks建立&C2上线Frp Frp是专注于内网穿透的高性能的反向代理应用&#xff0c;支持TCP、UDP、HTTP、HTTPS等多种协议。可以将内网服务以安全、便捷的方式通过…...

arinc664总线协议

AFDX总线协议简介 &#xff08;1&#xff09;AFDX的传输速率高&#xff1a;带宽100MHZ&#xff0c;远远高于其他的类型的航空总线。&#xff08;2&#xff09;AFDX网络的鲁棒性高&#xff1a;AFDX的双冗余备份网络可以在某一个网络出现故障时&#xff0c;仍能正常通讯。 其中…...

UNIX 域协议

1. UNIX域协议 利用socket编程接口实现本地进程间通信 UNIX域协议套接字&#xff1a;可以使用TCP&#xff0c;也可以使用UDP SOCK_STREAM -----> TCP 面向字节流 SOCK_DGRAM -----> UDP 面向数据报 UNIX域协议并不是一个实际的协议族&#xff0c;而是在单个主机上执…...

昇思25天学习打卡营第17天|LLM-基于MindSpore的GPT2文本摘要

打卡 目录 打卡 环境准备 准备阶段 数据加载与预处理 BertTokenizer 部分输出 模型构建 gpt2模型结构输出 训练流程 部分输出 部分输出2&#xff08;减少训练数据&#xff09; 推理流程 环境准备 pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspo…...

Clion开发STM32——移植FreeModbus

STM32型号 &#xff1a;STM32H743VIT6 FreeModbus版本 &#xff1a;1.6 使用工具&#xff1a;stm32cubeMX&#xff0c;Clion 使用STM32作从机&#xff0c;模式&#xff1a;RTU 网上用keil的比较多&#xff0c;用Clion的比较少&#xff0c;如果你也用Clion&#xff0c;那么希望…...

c++栈笔记

一种常见的数据结构&#xff0c;遵循后进先出&#xff0c;先进后出的原则。地址不连续&#xff0c;栈顶&#xff08;top&#xff09; 1.常见函数 stack<int> s;定义一个参数类型为int 的栈 名为ss.push()向栈中插入元素s.emplace()压栈&#xff0c;无返回值s.pop()删除…...

Oracle配置TCPS加密协议测试

文章目录 一、环境信息二、配置过程1.创建证书2.监听配置2.1.配置sqlnet.ora2.2.配置listener.ora文件2.3.配置tnsnames.ora文件2.4.重载监听 3.数据库本地测试3.1. tcps登录测试3.2.日志监控 一、环境信息 操作系统&#xff1a;Linux 版本信息&#xff1a;Oracle 19c 参考文档…...

Jetpack Compose 通过 OkHttp 发送 HTTP 请求的示例

下面是一个使用 Kotlin 和 Jetpack Compose 来演示通过 OkHttp 发送 HTTP 请求的示例。这个示例包括在 Jetpack Compose 中发送一个 GET 请求和一个 POST 请求&#xff0c;并显示结果。 添加okhttp依赖 首先&#xff0c;在你的 build.gradle.kts 文件中添加必要的依赖&#xf…...

Pytorch使用教学3-特殊张量的创建与类型转化

1 特殊张量的创建 与numpy类似&#xff0c;PyTorch中的张量也有很多特殊创建的形式。 zeros:全0张量 # 形状为2行3列 torch.zeros([2, 3]) # tensor([[0., 0., 0.], # [0., 0., 0.]])ones:全1张量 # 形状为2行3列 torch.ones([2, 3]) # tensor([[1., 1., 1.], # …...

【日记】办个护照不至于有这种刑事罪犯一样的待遇吧……(737 字)

正文 暴晒&#xff0c;中午出去骑共享单车&#xff0c;座垫都不敢坐。 至于为什么&#xff0c;中午觉都不睡跑出去&#xff0c;是因为今天他们办承兑汇票的业务&#xff0c;搞了一天&#xff0c;中午不休息&#xff0c;说可能还会用到我的指纹&#xff0c;让我 on call。我心想…...

【矩阵微分】在不涉及张量的前提下计算矩阵对向量的导数并写出二阶泰勒展开

本篇内容摘自CMU 16-745最优控制的第10讲 “Nonlinear Trajectory Optimization”。 如何在不涉及张量运算的前提下&#xff0c;计算矩阵对向量的导数并写出二阶泰勒展开 在多维微积分中&#xff0c;计算矩阵对向量的导数和二阶泰勒展开是一项重要的任务。本文将介绍如何在不涉…...

数据结构之判断平衡二叉树详解与示例(C,C++)

文章目录 AVL树定义节点定义计算高度获取平衡因子判断是否为平衡二叉树完整示例代码结论 在计算机科学中&#xff0c;二叉树是一种非常重要的数据结构。它们被广泛用于多种算法中&#xff0c;如排序、查找等。然而&#xff0c;普通的二叉树在极端情况下可能退化成链表&#xff…...

深入解析仓颉编程语言:函数式编程的核心特性

摘要 仓颉编程语言以其独特的语法和功能&#xff0c;为开发者提供了强大的编程工具。本文将深入探讨仓颉语言中的嵌套函数、Lambda 表达式和闭包等函数式编程的核心特性&#xff0c;帮助开发者更好地理解和利用这些工具。 引言 在现代编程语言中&#xff0c;函数式编程范式越…...

springboot惠农服务平台-计算机毕业设计源码50601

目录 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 惠农服务平台app 系统分析 2.1 可行性分析 2.2 系统功能分析 2.3 系统用例分析 2.4 系统流程分析 2.5本章小结 3 惠农服务平台app 总体设计 3.1 系统功能模块设计 3.2 数据库设计 表access_token (…...

Lua脚本简单理解

目录 1.安装 2.语法 2.1Lua数据类型 2.2变量 2.3lua循环 2.4流程控制 2.5函数 2.6运算符 2.7关系运算符 3.lua脚本在redis中的使用 3.1lua脚本再redis简单编写 3.2普通锁Lua脚本 3.3可重入锁lua脚本 1.安装 centos安装 安装指令&#xff1a; yum -y update yum i…...

AutoSAR自适应平台架构总览--AP的初认识

AutoSAR自适应平台架构总览:AP 基础设施层&#xff08;Foundation Layer&#xff09;核心操作系统&#xff08;Core OS&#xff09;通信管理&#xff08;Communication Management&#xff09; 服务层&#xff08;Services Layer&#xff09;诊断服务&#xff08;Diagnostics S…...

GPT-4o Mini:探索最具成本效益的小模型在软件开发中的应用

随着人工智能技术的迅猛发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域也取得了显著的进步。OpenAI 最新发布的 GPT-4o Mini 模型&#xff0c;以其卓越的性能和极具竞争力的价格&#xff0c;成为了广大开发者关注的焦点。作为一名长期关注人工智能及其在软件开发…...

{Spring Boot 原理篇} Spring Boot自动装配原理

SpringBootApplication 1&#xff0c;Spring Boot 应用启动&#xff0c;SpringBootApplication标注的类就是启动类&#xff0c;它去实现配置类中的Bean的自动装配 SpringBootApplication public class SpringbootRedis01Application {public static void main(String[] args)…...

QEMU源码全解析 —— CPU虚拟化(10)

接前一篇文章: 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社 《深度探索Linux系统虚拟化原理与实现》—— 王柏生 谢广军, 机械工业出版社 特此致谢! 二、x86架构CPU虚拟化 3. VMX 上一回讲解了支…...

46、PHP实现矩阵中的路径

题目&#xff1a; PHP实现矩阵中的路径 描述&#xff1a; 请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。 路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向…...

c++笔记2

目录 2.2 栈底&#xff08;bottom&#xff09; } 大数乘大数 节点&#xff1a;包含一个数据元素及若干指向子树分支的信息 。 节点的度&#xff1a;一个节点拥有子树的数目称为节点的度 。 叶子节点&#xff1a;也称为终端节点&#xff0c;没有子树的节点或者度为零的节点…...

通过Lua脚本手写redis分布式锁

1、手写 Redis 分布式锁&#xff0c;包括上锁、解锁、自动续期。 此功能实现采用 Lua脚本实现&#xff0c;Lua脚本可以保证原子性。 setnx可以实现分布式锁&#xff0c;但是无法实现可重入锁&#xff0c;所以用hset来代替setnx实现可重入的分布式锁。 -- lock if redis.call…...

解析银行个人征信系统

银行个人征信系统&#xff0c;也被称为个人信用信息基础数据库或金融信用信息基础数据库&#xff0c;是我国社会信用体系的重要基础设施。该系统由中国人民银行组织国内相关金融机构建立&#xff0c;旨在依法采集、整理、保存、加工自然人&#xff08;法人&#xff09;及其他组…...

AttributeError: ‘list‘ object has no attribute ‘text‘

AttributeError: ‘list‘ object has no attribute ‘text‘ 目录 AttributeError: ‘list‘ object has no attribute ‘text‘ 【常见模块错误】 【解决方案】 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英…...