Redis学习笔记(基础篇)

news2025/1/12 6:03:15

Redis基础

    • 1 Redis是什么?
      • 1.1 键值型
      • 1.2 NoSQL
        • 1.2.1 NoSQL与SQL的区别是什么
        • 1.2.2 总结
      • 1.3 Redis的特点是什么?
    • 2 Redis怎么用?
      • 2.1 Redis的基本命令
      • 2.2 Key的层级结构
      • 2.3 Redis的基本数据类型有哪些?
        • 2.1.1 String类型
        • 2.1.2 Hash类型
        • 2.1.3 List
        • 2.1.4 Set类型
        • 2.1.5 SortedSet类型
    • 3 Redis的java客户端有哪些?
      • 3.1 Jedis客户端
        • 3.1.1 快速入门
      • 3.2 SpringDataRedis客户端
        • 3.2.1 快速入门
        • 3.2.2 StringRedisTemplate

本文是参考黑马程序员Redis课程而做的笔记,根据本文可以快速了解什么是Redis以及Redis的几种基本数据类型和相关操作,在练习基础操作时,如果你还没有下载安装redis,可以在redis在线测试工具网站上操作。

1 Redis是什么?

Redis是一种键值型NoSQL数据库。

1.1 键值型

键值型指Redis中存储的数据都是以Key-Value键值对的形式存储,而value的形式多种多样,可以是字符串,数值甚至json

1.2 NoSQL

NoSQL是相对与传统关系型数据库而言,有很大差异的一种数据库。下面会详细对比。

1.2.1 NoSQL与SQL的区别是什么

1、结构化与非结构化

  • 传统关系型数据库结构化数据,每张表在创建时都有严格的约束条件,如字段名,字段数据类型,字段约束等。

  • NoSQL则对数据库格式没有约束,可以是键值型,也可以是文档型,甚至是图格式,总之是非结构化的。

2、关联与非关联

  • 传统数据库的表与表之间往往存在关联,例如外键约束。

  • 而非关系型数据库不存在关联关系,要维护关系的话要么靠代码中的业务逻辑,要么靠数据之间的耦合,比如要维护张三和两个手机订单的关系,就不得不冗余的将这两个商品保存在张三的订单的文档中,如下,不够简洁漂亮,所以建议使用业务逻辑来维护关联关系。

{
  id: 1,
  name: "张三",
  orders: [
    {
       id: 1,
       item: {
	 id: 10, title: "荣耀6", price: 4999
       }
    },
    {
       id: 2,
       item: {
	 id: 20, title: "小米11", price: 3999
       }
    }
  ]
}

3、查询方式

  • 传统关系型数据库会基于SQL语句做查询,语法有统一的标准
select id,age from tb_user where id = 1;
  • 而不同的非关系型数据库查询语法差异极大
Redis:  get user:1
MongoDB: db.user.find({_id: 1})
elasticsearch:  GET http://localhost:9200/users/1

4、事务

  • 传统关系型数据库满足事务的ACID原则(原子性、一致性、独立性及持久性)

  • 非关系型数据库往往不支持事务,只能实现基本的一致性

5、存储方式

  • 传统关系型数据库基于磁盘进行存储,会有大量的磁盘IO,对性能有一定的影响
  • 非关系型数据库的操作依赖于内存,内存的读写速度相对于磁盘非常快,性能更好

6、扩展性

  • 传统关系型数据库通常采用垂直扩展的方式,数据库集群一般是主从,主从数据一致,起到备份的作用。
  • 非关系型数据库通常采用水平扩展,它可以将数据拆封存储在不同的机器上,可以保存海量的数据,解决内存大小有限的问题。
1.2.2 总结
SQLNoSQL
数据结构结构化非结构化
数据关联关联的无关联
查询方式SQL查询非SQL
事务特性ADIDBASE
存储方式磁盘内存
扩展性垂直水平
使用场景1)数据结构固定 2)对一致性、安全性要求较高1)数据结构不稳定 2)相关业务对数据安全性、一致性要求不高 3)对性能有要求

1.3 Redis的特点是什么?

特征:

  • 键值型(Key-Value),Value支持多种不同的数据结构,功能丰富
  • 单线程,每个命令具有原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端

2 Redis怎么用?

要知道怎么用最好的方法肯定是到官网查看。

2.1 Redis的基本命令

命令描述
KEYs pattern查找所有符合给定模式(pattern)的key(不建议在生产环境用,因为Redis是单线程的,执行查询时会阻塞其他命令,当数据量很大的时候,效率很差)
EXISTs key检查给定的key是否存在(如果存在返回1,不存在返回0)
TYPE key返回key所存储的值的类型
TTL key返回给定key的剩余生存时间(TTL,time to live)以秒为单位(返回-1则说明这个数据永久有效)
DEL key该命令用于在key存在时删除key

2.2 Key的层级结构

我们已经知道Redis没有类似于MySQL中table的概念,那么我们应该如何区分不同类型的key呢?

如,我们现在有用户和商品,有个用户的id为1,同时有个商品的id也为1,如果它们都用id作为key,那么我们如何才能区分它们呢,直接存的话,都不说区分,会有覆盖的问题。所以我们是不是可以通过给key添加前缀来区分呢?

Redis的key其实时允许由多个单词形成层级结构的,多个单词使用:隔开,例如项目名:业务名:类型:id

当然这个格式并非固定的,可以按自己的需求来。这样我们就可以把不同类型的数据区分开了,从而避免key的冲突问题。

通过redis的图形界面,可以很直观的感受到层级结构:
在这里插入图片描述

2.3 Redis的基本数据类型有哪些?

2.1.1 String类型

String类型,也就是字符串类型,是Redis中最简单的存储类型,其value字符串,根据字符串的格式不同,可以分为3类:

  • String:普通字符串
  • int:整数类型,可以做自增、自减操作
  • float:浮点类型,也可以做自增自减操作,不过必须要指定自增自减的值
    不管是那种格式,底层都是以字节数组形式存储,只不过是编码方式不同,字符串类型的最大空间不能超过512M.

String常用命令

命令描述
SET添加一个String类型的键值对,如果原本存在则覆盖
GET根据key获取String类型的value
MSET批量的添加多个String类型的键值对
MGET根据多个key获取多个String类型的value
INCR让一个整形的key自增1
INCRBY让一个整形的key自增指定步长 incrby key 步长
INCRBYFLOAT让一个浮点类型的数字自增指定步长
SETNX添加一个String类型键值对,当前仅当这个key不存在时,否则不执行
SETEX添加一个String类型的键值对,并指定有效期
2.1.2 Hash类型

Hash类型,也叫散列,其中value是一个无序字典,类似于Java中HashMap结构(存储的内容是键值对映射)

当我们使用String类型去存一个数组的时候,我们需要将对象序列化为JSON字符串后存储,当我们要修改对象的某个属性值的时候会很不方便。这个时候用Hash类型就很合适了。Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD,并且在空间上更为节省,少了很多符号。
在这里插入图片描述
Hash常用命令

命令描述
HSET key field value添加或者修改hash类型key的field的值
HGET key field获取一个hash类型key的field的值
HMSET批量添加多个hash类型的key的field的值
HMGET批量获取hash类型多个key的field的值
HGETALL获取一个hash类型的key中所有的field和value
HKEYS获取一个hash类型key中所有field
HINCRBY让一个hash类型key的字段自增并指定步长
HSETNX添加一个hash类型的key的field的值,当且仅当这个field不存在,否则不执行
2.1.3 List

List类型与Java中的LinkedList类似,可以看作是一个双向链表结构,既可以支持正向检索也可以支持反向检索。

特征也与LinkedList类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般
    适合用来存储一些有序数据,例如:朋友圈点赞列表,评论列表等。

List常见命令

命令描述
LPUSH key element像列表左侧插入一个或多个元素
LPOP key移除并返回列表左侧的第一个元素,没有返回nil
RPUSH key像列表右侧插入一个或多个元素
RPOP key移除并返回列表右侧的第一个元素,没有返回nil
LRANGE key star返回一段角标范围内的所有元素
BLPOP和BRPOP与LPOP和RPOP类似,只不过在没有元素的时候会等待指定的时间,而不是直接返回nil
2.1.4 Set类型

Set类型与Java中的Hash类似,可以看作是一个value为null的HashMap(也可以看作数学上的集合),因为它也是一个hash表,因此具备和HashSet类似的特征:

  • 无序
  • 元素不可重复
  • 查找快
  • 支持交集、并集、差集等功能
    Set常见命令
命令描述
SADD key member向set中添加一个或多个元素
SREM key member移除set中指定元素
SCARD key返回set中元素的个数
SISMEMBER key menber判断一个元素是否存在于set中
SMEMBERS获取set中的所有元素
SINTER key1 key2求key1与key2的交集
SUNION key1 key2求key1与key2的并集
SDIFF key1 key2求key1与key2的差集

练习题
1、将下列数据用Redis的set集合来存储

  • 张三的好友有:李四、王五、赵六
  • 李四的好友有:王五、麻子、二狗

2、计算张三的好友有几人
3、计算张三和李四有哪些共同好友
4、查询哪些人是张三的好友却不是李四的好友
5、查询张三和李四的好友总共有哪些人
6、判断李四是否是张三的好友
7、判断张三是否是李四的好友
8、将李四从张三的好友列表中移除

2.1.5 SortedSet类型

SortedSet类型是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于scoer属性对元素排序,底层的实现是一个跳表(SkipList)加hash表。Sorted具备下列特性:

  • 可排序
  • 元素不重复
  • 查询速度快

SortedSet的value类似于一个排行榜,其中每个成员都有一个与之相关的分数,并且根据这个分数进行排序。

由于SortedSet的可排序特性,经常被用来实现排行榜这样的功能。

SortedSet常见命令

命令描述
ZADD key score member添加一个或多个元素到sorted set ,如果已经存在则更新其score值
ZREM key member删除sorted set中的一个指定元素
ZSCORE key member获取sorted set中的指定元素的score值
ZRANK key member获取sorted set 中的指定元素的排名
ZCARD key获取sorted set中的元素个数
ZCOUNT key min max统计score值在给定范围内的所有元素的个数
ZINCRBY key increment member让sorted set中的指定元素自增,步长为指定的increment值
ZRANGE key min max按照score排序后,获取指定排名范围内的元素
ZRANGEBYSCORE key min max按照score排序后,获取指定score范围内的元素
ZDIFF、ZINTER、ZUNION求差集、交集、并集

注意:
所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可,例如

  • 升序获取sortedset中指定元素的排名:ZRANK key member
  • 降序获取sortedset中指定元素的排名:ZREVRANK key member

练习题

1、将班级的下列学生得分存入Redis的SortedSet中:Jack 85, Lucy 89, Rose 82, Tom 95, Jerry 78, Amy 92, Miles 76
2、删除Tom同学
3、获取Amy同学的分数
4、获取Rose同学的排名
5、查询80分以下有几个学生
6、给Amy同学加2分
7、查出成绩前3名的同学(注意:默认升序)
8、查出成绩80分以下的所有同学

3 Redis的java客户端有哪些?

目前主流的Redis的Java客户端有三种:
- JedisLettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而SpringDataRedis又对这两种做了抽象和封装,因此我们后期会直接以SpringData来学习
- Redisson:在Redis基础上实现了分布式的可伸缩的java数据结构,例如Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。

3.1 Jedis客户端

3.1.1 快速入门
  1. 导入Jedis的maven坐标
<!--jedis-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>
<!--单元测试-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.0</version>
    <scope>test</scope>
</dependency>
  1. 建立连接
private Jedis jedis;

@BeforeEach
void setUp() {
    //1. 建立连接
    jedis = new Jedis("你的ip", 6379);
    //2. 设置密码
    jedis.auth("你的密码");
    //3. 选择库
    jedis.select(0);
}
  1. 测试
@Test
void testString(){
    jedis.set("name","Kyle");
    String name = jedis.get("name");
    System.out.println("name = " + name);
}

@Test
void testHash(){
    jedis.hset("reggie:user:1","name","Jack");
    jedis.hset("reggie:user:2","name","Rose");
    jedis.hset("reggie:user:1","age","21");
    jedis.hset("reggie:user:2","age","18");
    Map<String, String> map = jedis.hgetAll("reggie:user:1");
    System.out.println(map);
}
  1. 释放资源
@AfterEach
void tearDown(){
    if (jedis != null){
        jedis.close();
    }
}

连接池

由于Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损失,因此我们可以是使用Jedis连接池代替Jedis的直连方式,这种池化思想可以实现资源复用,提升性能等。

我们可以编写一个工具类,来使用连接池获取Jedis:

public class JedisConnectionFactory {

    private static JedisPool jedisPool;

    static {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxWaitMillis(1000);
        // 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码
        jedisPool = new JedisPool(poolConfig, "你的ip", 6379, 1000, "你的密码");
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

之后就可以这样获取jedis了

private Jedis jedis = JedisConnectionFactory.getJedis();

3.2 SpringDataRedis客户端

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫SpringDataRedis。它:

  • 提供了对Redis客户端的整合
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

API返回值类型说明
redisTemplate.opsForValue()ValueOperations操作String类型数据
redisTemplate.opsForHash()HashOperations操作Hash类型数据
redisTemplate.opsForList()ListOperations操作List类型数据
redisTemplate.opsForSet()SetOperations操作Set类型数据
redisTemplate.opsForzSet()ZSetOperations操作SortedSet类型数据
redisTemplate通用的命令
3.2.1 快速入门

这里看一下理解就好,重点是3.2.2。

  1. 导入依赖
<!--redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--common-pool-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<!--Jackson依赖-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 配置Redis
spring:
  redis:
    host: 你的服务器ip
    port: 6379
    password: 你的密码
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 100ms
  1. 注入RedisTemplate,因为有SpringBoot的自动装配,所以我们拿来就用就可以了
@Autowired
private RedisTemplate redisTemplate;
  1. 测试
@Test
void test(){
    redisTemplate.opsForValue().set("username","David");
    String username = (String) redisTemplate.opsForValue().get("username");
    System.out.println(username);
}
  • RedisTemplate可以接受任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果都类似于下面的形式

\xAC\xED\x00\x05t\x00\x06\xE5\xBC\xA0\xE4\xB8\x89

这样的话,可读性很差,而且内存占用较大

我们可以自定义RedisTemplate的序列化方式,这里采用了JSON序列化来代替默认的JDK序列化方式。如下:

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer =
                new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

我们编写一个实体类,并将他存入Redis看是什么效果

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
}
@Test
void test(){
    redisTemplate.opsForValue().set("userdata",new User("张三",18));
}

结果:

{
  "@class": "com.blog.entity.User",
  "name": "张三",
  "age": 18
}

这样可读性就好了很多,并且存的时候能将Java对象自动序列化成JSON字符串,并且查询时能自动把JSON字符串反序列化成Java对象。不过,为了实现这样的效果,必须在其中记录对应的class名称,这样就带来了额外的内存开销。

所以,为了节省内存,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。我们可以采用手动实现对象的序列化和反序列化的方式,这样class信息就不会被写入Redis了。

3.2.2 StringRedisTemplate

对此,SpringDataRedis就提供了RedisTemplate的子类StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

@Test
void stringTest() throws JsonProcessingException {
    //创建对象
    User user = new User("张三", 18);
    //手动序列化
    String json = mapper.writeValueAsString(user);
    //写入数据
    stringRedisTemplate.opsForValue().set("userdata", json);
    //获取数据
    String userdata = stringRedisTemplate.opsForValue().get("userdata");
    //手动反序列化
    User readValue = mapper.readValue(userdata, User.class);
    System.out.println(readValue);
}

结果:

{
  "name": "张三",
  "age": 18
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1524225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一维差分(模板)

差分是前缀和的逆运算&#xff0c;对于一个数组a&#xff0c;其差分数组b的每一项都是a [ i ]和前一项a [ i − 1 ]的差。 注意&#xff1a;差分数组和原数组必须分开存放&#xff01;&#xff01;&#xff01;&#xff01; #include <iostream> using namespace std;t…

【静夜思】为什么我们会如此喜欢夜晚呢

作为一名大学生&#xff0c;熬夜对我来说已是常态。每天都是近乎一点钟才有困意&#xff0c;觉得应该上床睡觉了&#xff0c;即使明天早八&#xff0c;即使明天有很多课。我也观察过身边的朋友&#xff0c;他们中大多数也和我一样&#xff0c;基本都是在12点过后才入睡。当今的…

《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)

1.简介 理想很丰满现实很骨感&#xff0c;在应用selenium实现web自动化时&#xff0c;经常会遇到处理日期控件点击问题&#xff0c;手工很简单&#xff0c;可以一个个点击日期控件选择需要的日期&#xff0c;但自动化执行过程中&#xff0c;完全复制手工这样的操作就有点难了。…

【系统架构师】-第4章-信息安全技术

1、基础知识 五要素&#xff1a; (1)机密性&#xff1a;确保信息不暴露给未授权的实体或进程。 (2)完整性&#xff1a;只有得到允许的人才能修改数据&#xff0c;并且能够判别出数据是否已被篡改。 (3)可用性&#xff1a;得到授权的实体在需要时可访问数据&#xff0c;即攻击…

04:HAL----串口通信UART

目录 前言 一:串口协议 1:通信接口 2:串口通信 3:硬件电路 4:电平标准 5:串口参数及其时序 二:USART介绍 1:简历 2:USART框图 3:USART的基本结构 4:数据帧 5: 波特率发生器 6:数据模式 三:HAL A:HAL库回调 B:配置步骤 四:案例 A:STM32发送数据 B:STM32接收…

mybatis-plus笔记1

mybatis-plus笔记1 mybatis-plus快速入门基于Mapper接口的crud增强基于service的crud分页查询分页添加到自定义方法queryWrapper简单使用使用细节 updateWrapperlambdaWrapper mybatis-plus快速入门 pom.xml文件中导入相关依赖 application.yaml配置文件 MainApplication.java…

2024HVV行动-进军蓝中研判(log4j2、fastjson、Struts2、Shiro)

1、log4j2 特征&#xff1a; 恶意请求中包含 JNDI 协议地址&#xff0c;如"ldap://"、"rmi://"等&#xff0c;被 log4j2 解析为 JNDI 查找。 原理&#xff1a; 在日志输出中&#xff0c;未对字符进行严格的过滤&#xff0c;执行了 JNDI 协议加载的远程恶…

五、保持长期高效的七个法则(二)Rules for Staying Productive Long-Term(1)

For instance - lets say youre a writer.You have a bunch of tasks on your plate for the day, but all of a sudden you get a really good idea for an essay. You should probably start writing now or youll lose your train of thought.What should you do? 举例来说…

7.JavaWebHTML:构建数字世界的语言和结构

目录 导语&#xff1a; 第一部分&#xff1a;Web概念与作用 1.1 Web的定义 1.2 Web的作用 1.3 JavaWeb 第二部分&#xff1a;HTML概念与内容 2.1 HTML的定义 2.2 HTML的内容 第三部分&#xff1a;HTML的作用 3.1 HTML的作用 3.2 HTML在现代Web开发中的角色 …

弗洛伊德-华沙算法求任意两点之间的最短路径算法

对于弗洛伊德-华沙算法首先是要假设研究的图中是不包含有负边的,对于所给的图中的任意亮点v1,vm,假设两点之间存在一条连通路径,对于该路径中去掉头和尾节点,也就是v1,vm,剩下的节点也就称之为这条路径的过渡节点。为图中每个节点进行编号,然后如果图中有n个节点,那么…

WSL的使用记录(1) - 第一次尝试

wsl2下载的话会直接把Ubantu也安装到位&#xff0c;因此我们直接打开Ubantu&#xff0c;在搜索框直接搜索Ubantu&#xff0c;就会出现这个。 我们直接打开就好了。 这时有可能会出现以下文字: wsl: 检测到 localhost 代理配置&#xff0c;但未镜像到 WSL。NAT 模式下的 WSL 不…

【优化算法综述】一行代码实现16种优化算法,常用寻优算法合集及MATLAB快速实现,写好1个就等于写好了16个~

欢迎来到动物园&#xff01; 在已有的众多的优化算法里&#xff0c;生物的行为是研究者们最常模仿的对象&#xff0c;所以你就会经常看到狼啊、麻雀啊、鲸鱼啊&#xff0c;甚至还有小龙虾。 当然这些算法的解决思路都很优秀&#xff0c;而对优化算法的应用和改进&#xff0c;…

搜维尔科技:使用SenseGlove Nova手套操纵其“CAVE”投影室中的虚拟对象

创造了一种基于 PC 的创新型多边沉浸式环境&#xff0c;让参与者完全被虚拟图像和声音包围。 需要解决的挑战&#xff1a; 传统的 VR 系统往往缺乏真实的触摸反馈&#xff0c;限制了用户的沉浸感。AVR Japan 旨在通过将触觉技术融入到他们的 CAVE 系统中来应对这一挑战&#x…

指挥航空公司架次与延误率占比

打开前端Vue项目kongguan_web&#xff0c;创建前端 src/components/Delay.vue 页面&#xff0c;并添加柱状图与折线图叠加&#xff0c;设置双Y轴。 页面div设计&#xff0c;代码如下&#xff1a; <template><div><div class"home"><div id&qu…

短剧小程序软件开发首页接口转发到Selectpage

工具&#xff1a;用的是uniapp开发 技术栈&#xff1a;vue、nide..js、云开发 用时&#xff1a;20工作天 软件&#xff1a;Hb、微信开发者工具 <?php namespace app\api\controller; use app\common\controller\Api; /** * 首页接口 */ class Index extends Api { …

关于PXIE3U18槽背板原理拓扑关系

如今IT行业日新月异&#xff0c;飞速发展&#xff0c;随之带来的是数据吞吐量的急剧升高。大数据&#xff0c;大存储将成为未来数据通信的主流&#xff0c;建立快速、大容量的数据传输通道将成为电子系统的关键。随着集成技术和互连技术的发展&#xff0c;新的串口技术&#xf…

MySQL数据库定时备份

小伙伴们好&#xff0c;欢迎关注&#xff0c;一起学习&#xff0c;无限进步 文章目录 MySQL 定时备份方式一&#xff1a;简单版方式二&#xff1a;复杂版方式三&#xff1a;doker定时备份&#xff0c;根据备份数量删除方式四&#xff1a;不是 docker 安装备份4、配置定时任务补…

科研绘图二:箱线图(抖动散点)

R语言绘图系列—箱线图抖动散点 &#xff08;二&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;抖动散点&#xff09; 文章目录 R语言绘图系列---箱线图抖动散点&#xff08;二&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;抖动散点&#xff09; 前言一、…

C++学习基础版(一)

目录 一、C入门 1、C和C的区别 2、解读C程序 3、命名空间 4、输入输出 &#xff08;1&#xff09;cout输出流 &#xff08;2&#xff09;endl操纵符 &#xff08;3&#xff09;cin输入流 二、C表达式和控制语句 1、数据机构 特别&#xff1a;布尔类型bool 2、算数运…

java框架 2 springboot 过滤器 拦截器 异常处理 事务管理 AOP

Filter 过滤器 对所有请求都可以过滤。 实现Filter接口&#xff0c;重写几个方法&#xff0c;加上WebFilter注解&#xff0c;表示拦截哪些路由&#xff0c;如上是所有请求都会拦截。 然后还需要在入口处加上SvlterComponentScan注解&#xff0c;因为Filter是javaweb三大组件之…