【仓颉三方库】 数据库驱动——redis-sdk

特性

  1. 支持RESP2和RESP3协议
  2. 接口设计兼容jedis接口语义
  3. 丰富的管理命令支持
  4. 支持单连接多线程模式
  5. 支持发布订阅模式
  6. 支持哨兵模式和集群模式
  7. 完备的单元测试覆盖
  8. 架构简洁,易于扩展

开发计划

  1. 2024.3.22 完成支持单机模式的RESP2和RESP3协议的客户端,提供Beta版本
  2. 2024.4.16 完成支持Sentinel集群模式的客户端,提供Beta版本
  3. 2024.5.31 完成支持Redis集群模式的客户端,提供Beta版本
  4. 2024.6.30 完成1.0.0 RC版本的发布

支持版本

Redis 7.x: 目前在Redis 7.0.0——Redis 7.2.4版本上完成兼容性测试
Redis 6.x: 目前在Redis 6.0.0——Redis 6.2.14版本上完成兼容性测试
其他版本的兼容性测试陆续完善中,敬请期待

工程目录结构

工程目录结构

|---samples  Redis客户端使用示例目录
|---src      Redis客户端源码目录  
|---test     Redis客户端单元测试目录
|     |---UT  通用命令的单元测试目录
      |---HLT 需要准备特殊环境的命令的单元测试
|---module.json
|---README.md

已经实现的命令

BitMap数据类型操作命令

BITCOUNT, BITFIELD, BITFIELD_RO, BITOP, GETBIT, SETBIT, BITPOS

地理空间坐标

GEOADD, GEODIST, GEOHASH, GEOENCODE, GEODECODE, GEOPOS, GEORADIUS, GEORADIUS_RO, GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO, GEOSEARCH, GEOSEARCHSTORE

Key命令

COPY, DEL, DUMP, EXISTS, EXPIRE, EXPIREAT, EXPIRETIME, MOVE, KEYS, MIGRATE, MEMORYUSAGE, OBJECTENCODING, OBJECTFREQ, OBJECTIDLETIME, OBJECTREFCOUNT, PERSIST, PEXPIRE, PEXPIREAT, PEXPIRETIME, PTTL, RANDOMKEY, RENAME,RENAMENX, RESTORE, SCAN, SORT, SORT_RO, TOUCH, TTL, TYPE, UNLINK

Hash数据类型操作命令

HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HMGET, HMSET, HRANDFIELD, HSCAN, HSET, HSETNX, HSTRLEN, HVALS

List数据类型操作命令

BLMOVE, BLMPOP, BLPOP, BRPOP, BRPOPLPUSH, LINDEX, LINSERT, LLEN, LMOVE, LMPOP, LPOP, LPOS, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, RPOP, RPOPLPUSH, RPUSH, RPUSHX

Set数据类型操作命令

SADD, SCARD, SDIFF, SDIFFSTORE, SINTER, SINTERCARD, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SPOP, SRANDMEMBER, SREM, SSCAN, SUNION, SUNIONSTORE

Stream数据类型操作命令

XACK, XADD, XAUTOCLAIM, XCLAIM, XDEL, XGROUP CREATE, XGROUP CREATECONSUMER, XGROUP DELCONSUMER, XGROUP DESTROY, XGROUP SETID, XINFO CONSUMERS, XINFO GROUPS, XINFO STREAM, XLEN, XPENDING, XRANGE, XREVRANGE, XREAD, XREADGROUP, XTRIM

String数据类型操作命令

APPEND, DECR, DECRBY, GET, GETDEL, GETEX, GETRANGE, GETSET, INCR, INCRBY, INCRBYFLOAT, MGET, MSET, MSETNX, PSETEX, SET, SETEX, SETNX, SETRANGE, STRLEN, SUBSTR

ZSet数据类型操作命令

BZMPOP, BZPOPMAX, ZADD, ZCARD, ZCOUNT, ZDIFF, ZDIFFSTORE, ZINCRBY, ZINTER, ZINTERCARD, ZINTERSTORE, ZLEXCOUNT, ZMSCORE, ZMPOP, ZPOPMIN, ZPOPMAX, ZRANDMEMBER, ZRANGE, ZRANGEBYSCORE, ZRANGESTORE, ZRANK, ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, ZREVRANGEBYSCORE, ZREVRANK, ZSCAN, ZSCORE, ZUNION, ZUNIONSTORE, ZREMRANGEBYLEX, ZRANGEBYLEX

HyperLogLog命令

PFADD, PFCOUNT, PFMERGE

Script和Function命令

EVAL, EVAL_RO, EVALSHA, EVALSHA_RO, SCRIPT EXISTS, SCRIPT FLUSH, SCRIPT KILL, SCRIPT LOAD

FCALL, FCALL_RO, FUNCTION DELETE, FUNCTION DUMP, FUNCTION FLUSH, FUNCTION KILL, FUNCTION LIST, FUNCTION LOAD, FUNCTION RESTORE, FUNCTION STATS

Connection Mangement命令

AUTH, ECHO, PING, RESET

DataBase 命令

DBSIZE, FLUSHDB, FLUSHALL, SELECT, SWAPDB

ACL命令

ACL CAT, ACL DELUSER, ACL DRYRUN, ACL GENPASS, ACL GETUSER, ACL LIST, ACL LOAD, ACL LOG, ACL SAVE, ACL SETUSER, ACL USERS, ACL WHOAMI

CLIENT命令

CLIENT GETNAME, CLIENT ID, CLIENT INFO, CLIENT KILL, CLIENT LIST, CLIENT NO-EVICT, CLIENT NO-TOUCH, CLIENT PAUSE, CLIENT SETINFO, CLIENT SETNAME, CLIENT UNBLOCK, CLIENT UNPAUSE

CONFIG命令

CONFIG GET, CONFIG RESETSTAT, CONFIG REWRITE, CONFIG SET

Server Mangement命令

BGREWRITEAOF, BGSAVE, INFO, LASTSAVE, LATENCYDOCTOR, LOLWUT, REPLICAOF, SAVE, SHUTDOWN, SLAVEOF

其他

MEMORY DOCTOR, MEMORY PURGE, MEMORY STATS, ROLE, WAIT, WAITAOF

1. 在工程中使用Redis仓颉语言客户端

1.1 通过源码方式引入Redis客户端依赖

仓颉0.53.4以上版本:在项目的cjpm.toml中添加dependencies引入redis_sdk依赖:

[dependencies]
  redis_sdk = {git = "https://gitcode.com/Cangjie-TPC/redis-sdk.git", branch = "master", version = "2.0.0"}

仓颉0.45.2和0.51.4版本,请参考 Branch_cj0.51.4 分支中的说明。

更新依赖,运行cjpm update会自动下载依赖redis_sdk项目到~/.cjpm目录下
$> cjpm update

1.2 编译Redis仓颉语言客户端并导入静态库依赖

编译Redis仓颉语言客户端请参考: 用户手册

引入编译好的静态库依赖和通过源码方式引入依赖,任意选取一种方式即可。 参考"1.1 通过源码方式引入Redis客户端依赖"。

仓颉0.53.4以上版本,需要先确定平台对应的target-name:

例如Windows X64平台执行cjc -v命令返回如下:

$cjc -v
Cangjie Compiler: 0.53.4 (cjnative)
Target: x86_64-w64-mingw32

例如Linux X64平台执行cjc -v命令返回如下:

$cjc -v
Cangjie Compiler: 0.53.4 (cjnative)
Target: x86_64-unknown-linux-gnu

仓颉0.53.4版本,在工程的cjpm.toml中添加平台对应的二进制依赖,以Linux X64为例:

[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
  "hyperion.buffer" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.buffer.cjo"
  "hyperion.logadapter" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.logadapter.cjo"
  "hyperion.objectpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.objectpool.cjo"
  "hyperion.threadpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.threadpool.cjo"
  "hyperion.transport" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.transport.cjo"
  "redis_sdk.client.api" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.api.cjo"
  "redis_sdk.client.commands" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.commands.cjo"
  "redis_sdk.client.commands.impl" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.commands.impl.cjo"
  "redis_sdk.client" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.cjo"

仓颉0.45.2和0.51.4版本,请参考 Branch_cj0.51.4 分支中的说明。

1.3 创建RedisClient用于执行Redis命令

import redis_sdk.client.api.*
import redis_sdk.client.commands.*
import redis_sdk.client.*

public func getRedisClient(): RedisClient {
    let redisClient = RedisClientBuilder.builder()
        .host("127.0.0.1")
        .port(6379)
        .readTimeout(Duration.second * 60)
        .writeTimeout(Duration.second * 30)
        .receiveBufferSize(32768)
        .sendBufferSize(32768)
        .build()
    return redisClient
}

1.4 使用RedisClient执行Redis命令操作

import redis_sdk.client.api.*
import redis_sdk.client.commands.*
import redis_sdk.client.*

main() {
    // 获取Redis客户端
    let client = getRedisClient()
    // 执行 SET testKey1 testValue1 XX命令
    let result = client.set("testKey1", "testValue1", SetParams().xx())
    if (let Some(result) <- result) {
        println(result)
    } else {
        println("nil")
    }

    // 执行 GET testKey1命令
    var getResult = client.get("testKey1")
    if (let Some(getResult) <- getResult) {
        println(getResult)
    } else {
        println("nil")
    }
}

2. 扩展Redis仓颉语言客户端

2.1 Redis命令处理模块的架构

Redis命令处理的架构图如下:

RedisCommand类

Redis命令的实现类
包含以下成员:
commandType: Redis命令的名称
commandArgs: Redis命令的参数列表
response: Redis命令的响应消息,类型为RedisMessage
exception: 执行Redis命令发生的异常

CommandArg类

封装Redis命令的基本类型参数,包括Array、String、Integer、Double

CommandArgs类

Redis命令的参数列表,包含CommandArg的列表

CompositeArgs类

封装Redis命令参数列表中存在关联关系的多个参数
调用buildArgs(CommandArgs)方法将多个存在关联的参数添加到CommandArgs的参数列表中

RedisMessage类

封装Redis命令的响应消息
RESP2协议对应的RedisMessage:
SIMPLE_STRINGS: StringRedisMessage
SIMPLE_ERRORS: ErrorRedisMessage
INTEGERS: IntegerRedisMessage
BULK_STRINGS: BulkStringRedisMessage
ARRAYS: ArraysRedisMessage

RESP3协议对应的RedisMessage:
NULLS:NullArraysRedisMessage
BOOLEANS:BooleanRedisMessage
DOUBLES:DoubleRedisMessage
BIG_NUMBERS:BigNumberRedisMessage
BULK_ERRORS:BulkErrorRedisMessage
VERBATIM_STRINGS:VerbatimRedisMessage
MAPS:MapRedisMessage
SETS:SetRedisMessage
PUSHES:PushesRedisMessage

ResponseBuilder类

将RedisMessage转换为命令执行的结果

基本数据类型的RepsonseBuilder实现:
StringResponseBuilder
IntegerResponseBuilder
DoubleResponseBuilder
BoolResponseBuilder
NillableStringResponseBuilder

集合类型的RepsonseBuilder实现:
ListResponseBuilder
SetOfResponseBuilder
PrimitiveMapResponseBuilder<String, T>
ListOfAnyResponseBuilder
MapOfAnyResponseBuilder

ParameterizedRedisCommand类

RedisCommand的子类,支持将Redis命令的响应构建为类型T,包含成员RepsonseBuilder用于处理响应
注意: 需要返回响应的命令,可以使用RedisCommand类, 也可以使用ParameterizedRedisCommand类;
不需要返回响应的命令,只能使用RedisCommand类

2.2 Redis编解码模块的架构

Redis编解码处理的架构图如下:

MessageCompletedHandler接口

解码二进制报文时,判断二进制报文是否包含完整的消息报文

ByteToRedisMessageDecoder类

RESP协议解码器实现,将RESP协议的二进制报文转换为RedisMessage
该类实现了MessageCompletedHandler接口

RedisCommandToByteEncoder类

RESP协议编码器实现,将RedisCommand编码为RESP协议的二进制报文

RedisCodec类

实现了Hyperion TCP框架的IOFilter接口,处理Redis命令和Redis响应的编解码

RedisCommandHandler类

实现了Hyperion TCP框架的IOFilter接口,处理RedisMessage和RedisCommand的关联

RedisSubscriberHandler类

实现了Hyperion TCP框架的IOFilter接口,处理RedisMessage和Redis订阅者的关联
在未切换成订阅模式之前,处理方式和RedisCommandHandler类一致(处理认证和握手相关命令)
切换成订阅模式之后,只能执行以下命令:
SUBSCRIBE channel [channel …]
PSUBSCRIBE pattern [pattern …]
UNSUBSCRIBE channel [channel …]
PUNSUBSCRIBE pattern [pattern …]
UNSUBSCRIBE
PUNSUBSCRIBE
PING
PING message

RedisClientConfig

记录Redis客户端的参数配置

RedisClientBuilder类

用于创建RedisClient对象,RedisClient可以执行Redis命令

RedisClient类

执行Redis命令,并返回命令执行的结果

RedisSubscriberBuilder类

用于创建RedisSubscriber对象,RedisSubscriber可以订阅消息

RedisSubscriber类

订阅Redis频道的消息

2.3 编写Redis命令的实现

对于一个特定的数据类型,例如String类型,需要提供以下2个接口:
StringCommands接口:定义String类型的操作命令对应的接口
StringCommansBuidldler接口:构建Sting类型相关命令对应的ParameterizedRedisCommand对象
需要实现以上2个接口:
StringCommandsImpl类:提供String类型的操作命令对应的实现
StringCommansBuidlerImpl类:构建Sting类型相关命令对应的ParameterizedRedisCommand对象

RedisClient类需要实现StringCommands接口,并将String类型的相关方法委托给StringCommandsImpl类

String类型,支持超时参数的SET命令按如下方式构建(参考StringCommansBuidlerImpl类):

    public func set(key: String, value: String, params: SetParams): ParameterizedRedisCommand<?String> {
        let commandArgs = CommandArgs().add(StringArg(key)).add(StringArg(value))
        let command = ParameterizedRedisCommand<?String>(
            CommandType.SET,
            commandArgs,
            params,
            ResponseBuilderFactory.nillableStringBuilder
        )
        return command
    }

String类型,支持超时参数的SET命令的实现如下:

    public func set(key: String, value: String, params: SetParams): ?String {
        let redisCommand = RedisCommandBuilder.set(key, value, params)
        return executeCommand<String>(redisCommand)
    }

调用String类型,支持超时参数的SET命令:

    let client = RedisClientBuilder.builder()
       .host(servHost)
       .port(servPort)
       .password(servPass)
       .build()
    // 500秒后超时
    let result = client.set(myKey, myValue, 
       SetParams().exAt(DateTime.now().addSeconds(500).toUnixTimeStamp().toSeconds())

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)全栈开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页)+《OpenHarmony 嵌入式开发学习手册》,希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

《OpenHarmony 嵌入式开发学习手册》:https://qr18.cn/F781PH

在这里插入图片描述

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用ViewPager实现轮播图的步骤如下: 1. 在布局文件中添加ViewPager控件和指示器(可选)。 ```xml <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="200dp" /> <LinearLayout android:id="@+id/indicator_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" /> ``` 2. 创建一个PagerAdapter,设置数据源和页面布局。 ```java public class MyPagerAdapter extends PagerAdapter { private List<Integer> mData; private LayoutInflater mInflater; public MyPagerAdapter(Context context, List<Integer> data) { mData = data; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { View view = mInflater.inflate(R.layout.item_pager, container, false); ImageView imageView = view.findViewById(R.id.image_view); imageView.setImageResource(mData.get(position)); container.addView(view); return view; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((View) object); } } ``` 3. 绑定PagerAdapterViewPager,并设置ViewPager的滑动监听,以便更新指示器。 ```java ViewPager viewPager = findViewById(R.id.view_pager); MyPagerAdapter adapter = new MyPagerAdapter(this, mData); viewPager.setAdapter(adapter); LinearLayout indicatorLayout = findViewById(R.id.indicator_layout); for (int i = 0; i < mData.size(); i++) { View indicator = new View(this); int size = getResources().getDimensionPixelSize(R.dimen.indicator_size); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size); lp.leftMargin = i == 0 ? 0 : getResources().getDimensionPixelSize(R.dimen.indicator_margin); indicator.setLayoutParams(lp); indicator.setBackgroundResource(R.drawable.indicator_bg); indicatorLayout.addView(indicator); } viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); for (int i = 0; i < mData.size(); i++) { View indicator = indicatorLayout.getChildAt(i); indicator.setSelected(i == position); } } }); ``` 其中,item_pager布局文件中只包含一个ImageView控件,用于显示图片。indicator_bg是指示器的背景,可以自定义。 以上就是使用ViewPager实现轮播图的主要步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值