Redis Connector API 使用指南
本文档介绍如何在你的 Halo 插件中使用 Redis Connector 提供的 API。
添加依赖
1. 配置 Gradle
在你的插件 build.gradle 中添加:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.acanyo:plugin-redis-connector:版本号'
}2. 声明插件依赖
在 plugin.yaml 中声明依赖:
spec:
pluginDependencies:
redis-connector: ">=1.0.0"
使用方式
方式一:静态 API(推荐)
使用 Redis 静态类,最简洁的调用方式:
import com.xhhao.redisconnector.api.Redis;
// 检查是否可用
if (Redis.isAvailable()) {
// 执行 Redis 操作
}
方式二:注入 RedisClient
如果需要更灵活的控制,可以注入 RedisClient 接口:
import com.xhhao.redisconnector.api.RedisClient;
@Component
@RequiredArgsConstructor
public class MyService {
private final RedisClient redisClient;
public Mono<String> getData(String key) {
if (!redisClient.isAvailable()) {
return Mono.empty();
}
return redisClient.get(key);
}
}
方式三:获取原始 JedisPool
当封装的 API 无法满足需求时,可以直接获取 JedisPool 进行操作:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;
import com.xhhao.redisconnector.api.Redis;
// 获取连接池
JedisPool pool = Redis.getJedisPool();
if (pool == null) {
// Redis 未初始化
return;
}
// ========== Pipeline 批量操作 ==========
try (Jedis jedis = pool.getResource()) {
Pipeline pipeline = jedis.pipelined();
for (int i = 0; i < 1000; i++) {
pipeline.set("key:" + i, "value:" + i);
}
pipeline.sync(); // 一次性发送所有命令
}
// ========== 事务操作 ==========
try (Jedis jedis = pool.getResource()) {
Transaction tx = jedis.multi();
tx.set("account:1:balance", "100");
tx.set("account:2:balance", "200");
tx.incr("transaction:count");
tx.exec(); // 原子执行
}
// ========== Lua 脚本 ==========
try (Jedis jedis = pool.getResource()) {
// 原子性的「获取并删除」操作
String script = "local val = redis.call('get', KEYS[1]); " +
"redis.call('del', KEYS[1]); " +
"return val";
Object result = jedis.eval(script, 1, "mykey");
}
// ========== 发布订阅 ==========
try (Jedis jedis = pool.getResource()) {
// 发布消息
jedis.publish("channel:notifications", "Hello World");
}
// ========== List 操作 ==========
try (Jedis jedis = pool.getResource()) {
jedis.lpush("queue:tasks", "task1", "task2", "task3");
String task = jedis.rpop("queue:tasks"); // 从右侧弹出
List<String> tasks = jedis.lrange("queue:tasks", 0, -1);
}
// ========== 分布式锁 ==========
try (Jedis jedis = pool.getResource()) {
String lockKey = "lock:order:123";
String lockValue = UUID.randomUUID().toString();
// 获取锁(NX=不存在才设置,EX=过期时间秒)
String result = jedis.set(lockKey, lockValue, SetParams.setParams().nx().ex(30));
if ("OK".equals(result)) {
try {
// 执行业务逻辑
} finally {
// 释放锁(Lua 脚本保证原子性)
String unlockScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) else return 0 end";
jedis.eval(unlockScript, 1, lockKey, lockValue);
}
}
}
// ========== Scan 遍历 ==========
try (Jedis jedis = pool.getResource()) {
String cursor = "0";
ScanParams params = new ScanParams().match("user:*").count(100);
do {
ScanResult<String> scanResult = jedis.scan(cursor, params);
List<String> keys = scanResult.getResult();
// 处理 keys
cursor = scanResult.getCursor();
} while (!"0".equals(cursor));
}INFO
⚠️ 注意事项
必须使用 try-with-resources 确保 Jedis 实例被正确归还到连接池
在响应式环境中执行阻塞操作时,建议包装在 Mono.fromCallable(...).subscribeOn(Schedulers.boundedElastic()) 中
API 详解
字符串操作
// 设置值
Redis.set("key", "value").subscribe();
// 获取值
Redis.get("key").subscribe(value -> {
System.out.println("Value: " + value);
});
// 设置值并指定过期时间(秒)
Redis.setEx("session:abc123", "user_data", 3600).subscribe();
// 删除键
Redis.del("key").subscribe(count -> {
System.out.println("Deleted: " + count);
});
计数器
// 自增 1
Redis.incr("page:views").subscribe(newValue -> {
System.out.println("Views: " + newValue);
});
// 自增指定值
Redis.incrBy("counter", 10).subscribe();
Hash 操作
适用于存储对象属性:
// 设置字段
Redis.hset("user:1001", "name", "张三").subscribe();
Redis.hset("user:1001", "email", "zhangsan@example.com").subscribe();
// 获取单个字段
Redis.hget("user:1001", "name").subscribe(name -> {
System.out.println("Name: " + name);
});
// 获取所有字段
Redis.hgetAll("user:1001").subscribe(user -> {
user.forEach((field, value) -> {
System.out.println(field + ": " + value);
});
});
Set 操作
适用于标签、去重等场景:
// 添加成员
Redis.sadd("post:1:tags", "java", "redis", "halo").subscribe();
// 获取所有成员
Redis.smembers("post:1:tags").subscribe(tags -> {
tags.forEach(System.out::println);
});
// 判断是否是成员
Redis.sismember("post:1:tags", "java").subscribe(isMember -> {
System.out.println("Is member: " + isMember);
});
Sorted Set 操作
适用于排行榜、优先级队列:
// 添加成员(带分数)
Redis.zadd("leaderboard", 1000, "player1").subscribe();
Redis.zadd("leaderboard", 2000, "player2").subscribe();
Redis.zadd("leaderboard", 1500, "player3").subscribe();
// 获取排行榜(按分数降序)
Redis.zrevrange("leaderboard", 0, 9).subscribe(top10 -> {
System.out.println("Top 10:");
top10.forEach(System.out::println);
});
// 增加分数
Redis.zincrby("leaderboard", 500, "player1").subscribe(newScore -> {
System.out.println("New score: " + newScore);
});
通用操作
// 判断键是否存在
Redis.exists("key").subscribe(exists -> {
System.out.println("Exists: " + exists);
});
// 设置过期时间(秒)
Redis.expire("key", 3600).subscribe();
// 获取剩余过期时间
Redis.ttl("key").subscribe(ttl -> {
if (ttl == -1) {
System.out.println("永不过期");
} else if (ttl == -2) {
System.out.println("键不存在");
} else {
System.out.println("剩余: " + ttl + " 秒");
}
});
API 方法列表
实际应用示例
文章浏览量统计
@Component
@RequiredArgsConstructor
public class PostViewService {
public Mono<Long> incrementView(String postName) {
if (!Redis.isAvailable()) {
return Mono.just(-1L);
}
return Redis.incr("post:views:" + postName);
}
public Mono<String> getViewCount(String postName) {
if (!Redis.isAvailable()) {
return Mono.just("0");
}
return Redis.get("post:views:" + postName)
.defaultIfEmpty("0");
}
}
用户会话缓存
@Component
public class SessionService {
private static final long SESSION_TTL = 7200; // 2小时
public Mono<String> createSession(String userId, String sessionData) {
String sessionId = UUID.randomUUID().toString();
return Redis.setEx("session:" + sessionId, sessionData, SESSION_TTL)
.thenReturn(sessionId);
}
public Mono<String> getSession(String sessionId) {
return Redis.get("session:" + sessionId);
}
public Mono<Long> destroySession(String sessionId) {
return Redis.del("session:" + sessionId);
}
}
热门文章排行榜
@Component
public class HotPostService {
public Mono<Long> recordView(String postName) {
return Redis.zincrby("hot:posts:daily", 1, postName)
.thenReturn(1L);
}
public Mono<List<String>> getHotPosts(int limit) {
return Redis.zrevrange("hot:posts:daily", 0, limit - 1);
}
}
注意事项
检查可用性:调用前建议先检查
Redis.isAvailable()响应式编程:所有方法返回
Mono,需要subscribe()或在响应式链中使用错误处理:操作失败时会返回默认值,不会抛出异常
键命名规范:建议使用
模块:类型:标识的格式,如post:views:123