Spring Boot 3 【九】Redis 的五种数据结构深入浅出(String & List & Set & Hash & Zset)

Spring Boot 3 【九】Redis 的五种数据结构深入浅出(String & List & Set & Hash & Zset)
如果觉得本文能够帮到您,请关注🌟、点赞👍、收藏📚,让这份美好延续下去!

一、Redis 数据结构简介

在现代应用开发中,高效的数据存储和管理是构建强大系统的关键。Redis 作为一种高性能的内存数据库,以其丰富的数据结构和快速的操作能力而备受青睐。Spring Boot 3 作为流行的开发框架,为整合 Redis 提供了便捷的方式。

在本文中,我们将深入探讨 Spring Boot 3 如何与 Redis 进行整合,并详细介绍对 Redis 的五种主要数据结构 —— 字符串(String)、列表(List)、集合(Set)、哈希(Hash)和有序集合(Sorted Set)的操作。通过掌握这些操作,我们能够充分发挥 Redis 的优势,提升应用的性能和灵活性。

二、深入 Redis 的五种数据结构

(一)字符串

1. Redis String 简介

Redis 的字符串(String)是最基本的数据类型,由一个键和一个值组成,其中键和值都可以是字符串。其值的最大限制为512MB,这使得它能够存储相对较大的数据量。String 类型是 Redis 中最为常用的数据类型之一,因为它支持多种操作,非常灵活。

它支持简单的 GET 和 SET 操作,可以快速地获取和设置字符串的值。此外,还支持自增(INCR)和自减(DECR)操作,这使得它非常适合用于实现计数器功能,比如统计网站的访问量、点赞数等。同时,还可以进行字符串拼接等操作,进一步扩展了其应用场景。

典型的应用场景 包括缓存数据,比如存储用户登录状态、Token以及各种配置信息等。在这些场景中,String 类型可以快速地存储和读取数据,提高系统的响应速度。另外,结合 SETNX 命令,还可以用字符串来实现简单的分布式锁,保证在分布式环境下对共享资源的互斥访问。

底层原理方面,Redis 底层对字符串使用的是简单动态字符串(SDS)。SDS 不仅仅是对 C 字符串的简单封装,它还加入了长度属性,使得获取字符串长度的操作时间复杂度为 O (1)。同时,SDS 还采用了空间预留策略,当进行字符串拼接等操作时,可以减少内存分配的次数,提高性能。此外,SDS 支持二进制安全,可以存储文本和二进制数据,这使得它在存储各种类型的数据时更加灵活。

2. redisTemplate.opsForValue().set() 方法

publicvoidsetString(String key,String value){ redisTemplate.opsForValue().set(key, value);}

这个方法用于将一个字符串值存储到 Redis 中。通过redisTemplate.opsForValue()获取到针对字符串类型的操作对象,然后调用set方法,传入键和值,将指定的值存储到 Redis 中,与该键对应。如果键已经存在,会覆盖原有值。

3. redisTemplate.opsForValue().get() 方法

publicStringgetString(String key){return(String) redisTemplate.opsForValue().get(key);}

此方法用于从 Redis 中获取与给定键对应的值。同样通过redisTemplate.opsForValue()获取操作对象,然后调用get方法传入键,返回存储在 Redis 中的字符串值。如果键不存在,将返回 null。

在这里插入图片描述

(二)列表

1. Redis List 简介

Redis 的列表(List)是一个双向链表,可以从头部或尾部插入、删除元素。常用的命令包括 LPUSH(从头部插入元素)、RPUSH(从尾部插入元素)、LPOP(从头部弹出元素)、RPOP(从尾部弹出元素)等。

Redis 的列表还支持阻塞操作,如 BLPOP 和 BRPOP。当列表为空时,这些命令可以阻塞等待,直到有元素被插入到列表中。这种阻塞操作使得列表非常适合用于实现消息队列等场景。

典型的应用场景之一是作为消息队列。可以使用 LPUSH 将消息放入队列的头部,使用 RPOP 或 BRPOP 从队列的尾部弹出消息进行处理。这种方式实现的消息队列简单高效,适用于各种异步处理场景。另一个应用场景是任务调度,在异步任务分发系统中,可以将任务放入列表中,由多个消费者去消费任务,实现任务的并行处理。

列表采用双向链表(quicklist)实现。对于较短的列表,Redis 会使用压缩列表(ziplist)来节省内存。压缩列表是一种紧凑的内存数据结构,可以在一定程度上减少内存占用。但是,当列表长度增加时,为了保证操作的时间复杂度,Redis 会自动将其转换为真正的双向链表。这样可以在不同的场景下平衡内存使用和操作效率。

2. redisTemplate.opsForList().leftPush 方法

(1)以下方法将一个元素插入到指定列表的左侧。
使用redisTemplate.opsForList()获取针对列表类型的操作对象,调用leftPush方法,传入键和要插入的元素值。随着元素不断插入,列表的头部不断变化,最先插入的元素会逐渐移向列表的尾部。

publicvoidleftPush(String key,Object value){ redisTemplate.opsForList().leftPush(key, value);}

(2)依次向 list 中存入元素aaa,bbb,ccc,aaa,ddd:

@PostMapping("/leftPush")publicvoidleftPush(){String aaa ="aaa", bbb="bbb", ccc="ccc", ddd="ddd"; userService.leftPush(aaa); userService.leftPush(bbb); userService.leftPush(ccc); userService.leftPush(aaa); userService.leftPush(ddd);}

(3)可以看到 redis 中,先存储的在右侧(底部),后存储的在左侧(上部):

在这里插入图片描述

3. redisTemplate.opsForList().rightPush 方法

(1)该方法是从列表右侧插入元素:

publicvoidrightPush(String key,Object value){ redisTemplate.opsForList().rightPush(key, value);}
@PostMapping("/rightPush")publicvoidrightPush(){String eee ="eee", fff="fff"; userService.rightPush(eee); userService.rightPush(fff);}

(2)查看 redis中 的元素,eee和fff是从列表右侧插入:

在这里插入图片描述

4. 从列表左侧和右侧取出元素

(1)可以从列表左侧或者右侧取出(删除)一个元素。
即使用leftPop和rightPop方法,从列表的左侧或右侧移除并返回一个元素。如果列表为空,将返回 null。

/* * 从左侧取出一个元素 */publicObjectleftPop(String key){return redisTemplate.opsForList().leftPop(key);}/* * 从右侧取出一个元素 */publicObjectrightPop(String key){return redisTemplate.opsForList().rightPop(key);}

(2)从左侧取出了元素ddd, 从右侧取出了元素fff:

在这里插入图片描述

5. 获取列表长度

(1)redisTemplate.opsForList().size()方法:

// 获取列表长度publicLonglistLength(String key){return redisTemplate.opsForList().size(key);}

(2)请求结果为5:

在这里插入图片描述

6. 获取列表指定范围的元素

(1)以下方法的作用是获取指定键对应列表中从start索引到end索引范围内的元素。

它通过调用 redisTemplate.opsForList().range(key, start, end) 实现,可用于获取列表的一部分进行处理或展示,其中列表的第一个元素从 0 开始。

// 获取列表指定范围的元素publicList<Object>range(String key,long start,long end){return redisTemplate.opsForList().range(key, start, end);}

(2)Redis 列表的原数据如下图所示:

在这里插入图片描述

(3)比如获取列表从索引 1(第二个元素) 开始 至 索引 4:

/* * 获取列表指定范围元素 */@GetMapping("range")publicList<Object>range(String key){return userService.range(key,1,4);}

得出如下结果:

在这里插入图片描述


(4)获取整个列表
输入起始位置为 0,

/* * 获取列表指定元素 */@GetMapping("range")publicList<Object>range(String key){return userService.range(key,0,-1);}

(三)无序集合

1. Redis Set 简介

Redis 的集合(Set)是一个无序的、唯一的元素集合。这意味着集合中的元素是唯一的,不会有重复元素。集合提供了类似于数学集合的操作,支持交集(SINTER)、并集(SUNION)、差集(SDIFF)等。

常见的 Redis 操作 包括 SADD 用于向集合中添加元素、SREM 用于从集合中删除元素、SISMEMBER 用于判断一个元素是否在集合中、SMEMBERS 用于获取集合中的所有元素等。

典型的应用场景 之一是标签系统。可以将用户标签存储为集合,每个集合代表一个用户群体。通过集合的交集、并集和差集等操作,可以方便地找出同时拥有某几个标签的用户,或者找出具有特定标签组合的用户群体。另一个应用场景是去重功能。在某些场景下,比如热门搜索词、访问日志的去重等,可以通过集合的唯一性特性来避免重复数据的存储和处理。

集合在小集合时使用整数集合(intset)来存储元素。整数集合是一种紧凑的整数存储结构,可以节省内存。当集合中的元素数量增加或者元素类型不是整数时,会自动转换为哈希表(hashtable)实现。通过哈希表的快速查找特性,可以实现 O (1) 的时间复杂度来判断元素是否存在于集合中。

2. 代码示例

Redis Util 工具类的各个方法对应 Redis 集合的不同操作:

packagecom.jsglxx.redis;importjava.util.List;importjava.util.Set;importjava.util.concurrent.TimeUnit;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassCacheUtil{privatefinalRedisTemplate<String,Object> redisTemplate;publicCacheUtil(RedisTemplate<String,Object> redisTemplate){this.redisTemplate = redisTemplate;}// 向集合中添加元素publicvoidaddToSet(String key,Object value){ redisTemplate.opsForSet().add(key, value);}// 从集合中移除元素publicvoidremoveFromSet(String key,Object value){ redisTemplate.opsForSet().remove(key, value);}// 判断元素是否在集合中publicbooleanisMemberOfSet(String key,Object value){return redisTemplate.opsForSet().isMember(key, value);}// 获取集合中的所有元素publicSet<Object>getSetMembers(String key){return redisTemplate.opsForSet().members(key);}}
  • addToSet方法使用redisTemplate.opsForSet().add(key, value)向指定键对应的集合中添加元素。
  • removeFromSet方法使用redisTemplate.opsForSet().remove(key, value)从集合中移除指定元素。
  • isMemberOfSet方法使用redisTemplate.opsForSet().isMember(key, value)判断给定元素是否在集合中。
  • getSetMembers方法使用redisTemplate.opsForSet().members(key)获取集合中的所有元素。

3. 测试方法:

在以下测试方法中,首先向两个集合中添加元素,然后分别测试各个方法,输出结果以验证方法的正确性。

publicvoidtestSet(){String setKey1 ="set1";String setKey2 ="set2";// 向集合 1 添加元素 cacheUtil.addToSet(setKey1,"element1"); cacheUtil.addToSet(setKey1,"element2"); cacheUtil.addToSet(setKey1,"element3");// 向集合 2 添加元素 cacheUtil.addToSet(setKey2,"element2"); cacheUtil.addToSet(setKey2,"element3"); cacheUtil.addToSet(setKey2,"element4");// 判断元素是否在集合中boolean isMember = cacheUtil.isMemberOfSet(setKey1,"element2");System.out.println("【元素element2】在【集合set1】中吗? "+ isMember);// 获取集合中的所有元素Set<Object> setMembers1 = cacheUtil.getSetMembers(setKey1);System.out.println("【集合set1】中的所有元素: "+ setMembers1);Set<Object> setMembers2 = cacheUtil.getSetMembers(setKey2);System.out.println("【集合set2】中的所有元素: "+ setMembers2);}

4. 结果输出

【元素element2】在【集合set1】中吗?true 【集合set1】中的所有元素:[element1, element2, element3] 【集合set2】中的所有元素:[element2, element3, element4]

(四)Hash

1. Redis 哈希介绍

Redis 的哈希(Hash)是一个 =键值对集合,非常适合用于存储对象。每个键可以有多个字段,每个字段都对应一个值。这种结构使得可以将一个复杂的对象拆分成多个字段进行存储,方便进行管理和查询。

常用的 Redis 操作包括 HSET 用于设置字段的值、HGET 用于获取字段的值、HDEL 用于删除特定字段等。这些操作使得对哈希的管理非常方便,可以根据需要快速地添加、修改和删除字段。

典型的应用场景 之一是存储用户信息。可以将用户 ID 作为键,用户的各种属性(如姓名、年龄、性别等)作为字段,存储在哈希中。这样可以避免将整个用户对象序列化成字符串进行存储,在查询和更新用户信息时更加高效。另一个应用场景是配置项管理,将不同的配置项存储在哈希中,方便根据字段名快速访问和更新某个特定的配置。

哈希使用了两种底层数据结构。在小数据量时,使用压缩列表(ziplist)来存储哈希。压缩列表是一种紧凑的内存数据结构,可以节省内存空间。但是,随着哈希表的增长,当数据量达到一定程度时,会自动转换为哈希表(hashtable)。哈希表具有更高的查询效率,可以保证在大数据量时仍然能够快速地进行字段的查找和操作。

2. Redis 工具类代码示例

packagecom.jsglxx.redis;importjava.util.List;importjava.util.Map;importjava.util.Set;importjava.util.concurrent.TimeUnit;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassCacheUtil{privatefinalRedisTemplate<String,Object> redisTemplate;publicCacheUtil(RedisTemplate<String,Object> redisTemplate){this.redisTemplate = redisTemplate;}// 设置哈希字段的值publicvoidsetHashField(String key,String field,Object value){ redisTemplate.opsForHash().put(key, field, value);}// 获取哈希字段的值publicObjectgetHashField(String key,String field){return redisTemplate.opsForHash().get(key, field);}// 删除哈希字段publicvoiddeleteHashField(String key,String... fields){ redisTemplate.opsForHash().delete(key, fields);}// 获取哈希的所有字段名publicSet<Object>getHashKeys(String key){return redisTemplate.opsForHash().keys(key);}// 获取哈希的所有值publicList<Object>getHashValues(String key){return redisTemplate.opsForHash().values(key);}// 获取哈希的所有字段和值publicMap<Object,Object>getHashAll(String key){return redisTemplate.opsForHash().entries(key);}}
  • setHashField方法使用redisTemplate.opsForHash().put(key, field, value)将指定的值设置到哈希表中给定的字段。
  • getHashField方法使用redisTemplate.opsForHash().get(key, field)获取哈希表中指定字段的值。
  • deleteHashField方法使用redisTemplate.opsForHash().delete(key, fields)删除哈希表中的一个或多个字段。
  • getHashKeys方法使用redisTemplate.opsForHash().keys(key)获取哈希表中的所有字段名。
  • getHashValues方法使用redisTemplate.opsForHash().values(key)获取哈希表中的所有值。
  • getHashAll方法使用redisTemplate.opsForHash().entries(key)获取哈希表中的所有字段和值,以一个Map的形式返回。

3. 测试类代码

在测试类中,首先设置哈希表的字段值,然后分别测试各个方法,输出结果以验证方法的正确性。

publicvoidtestHash(){String hashKey ="myHash";// 设置哈希字段的值 cacheUtil.setHashField(hashKey,"field1","value1"); cacheUtil.setHashField(hashKey,"field2","value2"); cacheUtil.setHashField(hashKey,"field3","value3");// 获取哈希字段的值Object value = cacheUtil.getHashField(hashKey,"field2");System.out.println("field2 的值为: "+ value);// 删除哈希字段 cacheUtil.deleteHashField(hashKey,"field1");// 获取哈希的所有字段名Set<Object> keys = cacheUtil.getHashKeys(hashKey);System.out.println("Hash表中的所有键: "+ keys);// 获取哈希的所有值List<Object> values = cacheUtil.getHashValues(hashKey);System.out.println("Hash表中的所有值: "+ values);// 获取哈希的所有字段和值Map<Object,Object> allEntries = cacheUtil.getHashAll(hashKey);System.out.println("hash表中的所有键值对: "+ allEntries);}

4. 输出结果

field2 的值为: value2 Hash表中的所有键:[field2, field3]Hash表中的所有值:[value2, value3] hash表中的所有键值对:{field2=value2, field3=value3}

(五)有序集合

1. Redis Zset 简介

Redis 的有序集合是一种特殊的集合,其中每个元素都关联一个分数。集合中的元素会按照分数排序。支持的操作包括 ZADD 用于向有序集合中添加元素并指定分数、ZRANGE 和 ZREVRANGE 分别用于按照分数从小到大和从大到小获取元素、ZCOUNT 用于统计分数范围内的元素数量等。

典型的应用场景之一是排行榜。比如在游戏中,可以将玩家的分数作为有序集合的元素分数,玩家 ID 作为元素,通过 ZADD 添加玩家及其分数。然后可以使用 ZRANGE 或 ZREVRANGE 获取排名靠前的玩家。另一个应用场景是延迟任务。可以通过设置元素的分数为任务执行的时间,将任务存储在有序集合中。然后按照时间从集合中取出需要执行的任务进行处理。

有序集合底层使用的是跳表(Skiplist)和哈希表相结合的数据结构。跳表是一种高效的有序数据结构,它使有序集合支持快速的范围查询和插入操作,时间复杂度为 O (log n)。而哈希表则保证了元素的快速定位,使得可以在 O (1) 的时间复杂度内判断元素是否存在于有序集合中。这种结合的方式既保证了查询效率,又能够有效地管理元素的顺序。

2. Redis 工具类代码示例

packagecom.jsglxx.redis;importjava.util.List;importjava.util.Map;importjava.util.Set;importjava.util.concurrent.TimeUnit;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassCacheUtil{privatefinalRedisTemplate<String,Object> redisTemplate;publicCacheUtil(RedisTemplate<String,Object> redisTemplate){this.redisTemplate = redisTemplate;}// 添加成员到有序集合publicvoidaddToSortedSet(String key,double score,Object member){ redisTemplate.opsForZSet().add(key, member, score);}// 从有序集合中移除成员publicvoidremoveFromSortedSet(String key,Object... members){ redisTemplate.opsForZSet().remove(key, members);}// 获取成员的分值publicDoublegetScore(String key,Object member){return redisTemplate.opsForZSet().score(key, member);}// 获取有序集合指定范围的成员(从小到大排序)publicSet<Object>getRange(String key,long start,long end){return redisTemplate.opsForZSet().range(key, start, end);}// 获取有序集合指定范围的成员(从大到小排序)publicSet<Object>getReverseRange(String key,long start,long end){return redisTemplate.opsForZSet().reverseRange(key, start, end);}// 获取分值范围内的成员(从小到大排序)publicSet<Object>getRangeByScore(String key,double minScore,double maxScore){return redisTemplate.opsForZSet().rangeByScore(key, minScore, maxScore);}// 获取分值范围内的成员(从大到小排序)publicSet<Object>getReverseRangeByScore(String key,double maxScore,double minScore){return redisTemplate.opsForZSet().reverseRangeByScore(key, maxScore, minScore);}// 获取有序集合的成员数量publicLonggetCardinality(String key){return redisTemplate.opsForZSet().zCard(key);}// 获取分值范围内的成员数量publicLonggetCountByScore(String key,double minScore,double maxScore){return redisTemplate.opsForZSet().count(key, minScore, maxScore);}}
  • addToSortedSet方法使用redisTemplate.opsForZSet().add(key, member, score)向有序集合添加成员和分值。
  • removeFromSortedSet方法使用redisTemplate.opsForZSet().remove(key, members)从有序集合中移除指定成员。
  • getScore方法使用redisTemplate.opsForZSet().score(key, member)获取指定成员的分值。
  • getRange和getReverseRange方法分别用于获取有序集合指定范围的成员,按照分值从小到大和从大到小排序。
  • getRangeByScore和getReverseRangeByScore方法用于获取分值范围内的成员,同样。按照分值从小到大和从大到小排序。
  • getCardinality方法使用redisTemplate.opsForZSet().zCard(key)获取有序集合的成员数量。
  • getCountByScore方法使用redisTemplate.opsForZSet().count(key, minScore, maxScore)获取分值范围内的成员数量。

3. 测试类代码

在测试类中,首先向有序集合添加成员,然后分别测试各个方法,输出结果以验证方法的正确性。最后,从有序集合中移除一个成员。

publicvoidtestSortedSetOperations(){String sortedSetKey ="mySortedSet";// 添加成员到有序集合 cacheUtil.addToSortedSet(sortedSetKey,10.0,"member1"); cacheUtil.addToSortedSet(sortedSetKey,20.0,"member2"); cacheUtil.addToSortedSet(sortedSetKey,15.0,"member3");// 获取成员的分值Double score = cacheUtil.getScore(sortedSetKey,"member2");System.out.println("member2 的分值: "+ score);// 获取有序集合指定范围的成员(从小到大排序)Set<Object> range = cacheUtil.getRange(sortedSetKey,0,1);System.out.println("有序集合ascending(0-1)的成员从小到大排序: "+ range);// 获取有序集合指定范围的成员(从大到小排序)Set<Object> reverseRange = cacheUtil.getReverseRange(sortedSetKey,0,1);System.out.println("有序集合ascending(0-1)的成员从大到小排序: "+ reverseRange);// 获取分值范围内的成员(从小到大排序)Set<Object> rangeByScore = cacheUtil.getRangeByScore(sortedSetKey,12.0,18.0);System.out.println("ascending集合内分值在12.0 - 18.0之间的成员: "+ rangeByScore);// 获取分值范围内的成员(从大到小排序)Set<Object> reverseRangeByScore = cacheUtil.getReverseRangeByScore(sortedSetKey,12.0,18.0);System.out.println("分值12.0 - 18.0之间的成员从大到小排序: "+ reverseRangeByScore);// 获取有序集合的成员数量Long cardinality = cacheUtil.getCardinality(sortedSetKey);System.out.println("集合内成员数量: "+ cardinality);// 获取分值范围内的成员数量Long countByScore = cacheUtil.getCountByScore(sortedSetKey,10.0,20.0);System.out.println("10.0-20.0分值范围内的成员数量: "+ countByScore);// 从有序集合中移除成员 cacheUtil.removeFromSortedSet(sortedSetKey,"member1");}

4. 输出结果

member2 的分值:20.0 有序集合ascending(0-1)的成员从小到大排序:[member1, member3] 有序集合ascending(0-1)的成员从大到小排序:[member2, member3] ascending集合内分值在12.0-18.0之间的成员:[member3] 分值12.0-18.0之间的成员从大到小排序:[member3] 集合内成员数量:310.0-20.0分值范围内的成员数量:3

三、结尾

总之,Spring Boot 3 与 Redis 的整合为开发者提供了强大的数据存储和处理能力。通过对 Redis 的五种数据结构的熟练操作,我们可以根据不同的业务需求选择合适的数据结构,实现高效的数据管理和快速的访问。无论是缓存数据、构建消息队列、存储用户信息还是进行复杂的排序操作,Redis 都能在 Spring Boot 3 应用中发挥重要作用。不断探索和优化 Redis 的使用,将有助于我们构建更加健壮、高效的应用程序,满足不断变化的业务需求。

🌟 对技术管理感兴趣 请扫码关注下方 ⬇ 【 技术管理修行】

Read more

ubuntu 内网自建apt源(apt-mirror)

ubuntu 内网自建apt源(apt-mirror)

文章目录 * 1. 安装apt-mirror * 2. 更新apt镜像数据 * 3. 创建web服务(以nginx为例) * 4. 客户端使用 * 5. 添加一个新源(以docker为例) 1. 安装apt-mirror * 官网地址:https://apt-mirror.github.io/ * 安装 $ apt-getinstall apt-mirror * 配置文件 /etc/apt/mirror.list * 配置代理 * 修改存储位置 修改配置(非必要) set unlink 1set use_proxy on set http_proxy 10.10.xxx.xx:1111 set proxy_user user

By Ne0inhk
Flutter for OpenHarmony:Flutter 三方库 gsettings 操作底层兼容桌面/类 Linux 基座核心偏好设置桥梁(适配鸿蒙 HarmonyOS Next ohos)

Flutter for OpenHarmony:Flutter 三方库 gsettings 操作底层兼容桌面/类 Linux 基座核心偏好设置桥梁(适配鸿蒙 HarmonyOS Next ohos)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 当我们随着鸿蒙(OpenHarmony)生态圈的扩张,开发不再是仅仅局限于手机移动端!它开始被广泛地部署和编译于各类大屏智慧中枢、以及各种以带有 PC 桌面级交互的发行版核心系统。如果您想开发一个深层次融入类桌面系统甚至兼容诸如带有大桌面生态的控制管理器,去读取例如系统的深色模式开关、全局护眼温度、底座主题设置。通常我们需要极难搞的底层 C++ 互操作。 gsettings 打破了界限!它是一款极其实用的让 Flutter 跨越鸿蒙底座和带有类似 DBus/GSettings 特质管理器的中间沟通介质包装包!让您的前台业务不仅长得像系统的内部软件,而且能深层次地感应和调配下层的极其基础配置字典。 一、原理解析 / 概念介绍 1.1 基础概念 通常底层的这种系统设置就像是一颗极其巨大复杂的注册表树(或称之为配置管理字典大集合)。该库不制造文件存储,它直接用接口对向那些由大系统所保管起来的特定格式的 Key-Value 字典键值!让您的面板能随时读取并且

By Ne0inhk
OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,远程管理+SSH 双剑合璧

OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,远程管理+SSH 双剑合璧

OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,远程管理+SSH 双剑合璧 摘要:还在频繁切换窗口管理 OpenClaw?试试这款开源 VS Code 插件!通过 WebSocket 直连网关,侧边栏即可聊天交互,配合 VS Code SSH 远程开发,打造丝滑的远程 AI 工作流。 项目地址:https://github.com/MaoTouHU/openclaw-vscode 关键词:OpenClaw、VS Code 插件、WebSocket、远程开发、AI 网关 文章目录 * OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,

By Ne0inhk
【linux】高级IO,以ET模式运行的epoll版本的TCP服务器实现reactor反应堆

【linux】高级IO,以ET模式运行的epoll版本的TCP服务器实现reactor反应堆

小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 linux系统编程专栏<—请点击 linux网络编程专栏<—请点击 倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己! 目录 * 前言 * 一、前置知识 * 二、第一阶段,基本框架的实现 * Connection * Main.cc * TcpServer * 测试 * 三、第二阶段,引入业务协议 * TcpServer * Main.cc * TcpServer * 测试 * 四、拓展 * 五、写博客一年的总结 * 六、源代码 * ClientCal.cc * Comm.hpp * Epoller.hpp * Log.hpp * Main.

By Ne0inhk