Redis Java集成与Spring环境实战指南
本文将详细阐述如何在纯Java环境以及Spring框架下高效操作Redis数据库,涵盖依赖配置、连接建立以及核心数据结构的操作示例。
Java环境集成
1. 项目初始化
首先创建一个Maven项目,并在 pom.xml 中添加Jedis依赖。Jedis是一个流行的Redis Java客户端,其API设计与Redis命令高度一致,便于理解和使用。
<!-- Redis客户端依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.2</version>
</dependency>
2. 端口转发配置
为安全起见,建议通过SSH隧道将云服务器的Redis端口(默认6379)转发到本地端口(如8888)。在Xshell等工具中配置隧道后,访问 localhost:8888 即等同于访问远端Redis服务。
3. 基本命令操作示例
以下代码演示了Jedis中 SET/GET、EXISTS/DEL、KEYS、EXPIRE/TTL 和 TYPE 等通用命令的使用。
public static void basicCommands(Jedis jedis) {
// 清空数据库
jedis.flushAll();
// SET/GET 示例
jedis.set("name", "John");
jedis.set("age", "25");
String name = jedis.get("name");
String age = jedis.get("age");
System.out.println("Name: " + name + ", Age: " + age);
// EXISTS/DEL 示例
boolean exists = jedis.exists("name");
System.out.println("Key 'name' exists: " + exists);
long deleted = jedis.del("name", "age");
System.out.println("Deleted " + deleted + " keys");
// KEYS 示例
jedis.set("city", "NYC");
jedis.set("country", "USA");
Set<String> allKeys = jedis.keys("*");
System.out.println("All keys: " + allKeys);
// EXPIRE/TTL 示例
jedis.set("tempKey", "expiring");
jedis.expire("tempKey", 10);
long ttl = jedis.ttl("tempKey");
System.out.println("TTL before sleep: " + ttl);
// 休眠5秒
try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
ttl = jedis.ttl("tempKey");
System.out.println("TTL after 5s sleep: " + ttl);
// TYPE 示例
jedis.set("str", "hello");
System.out.println("Type of 'str': " + jedis.type("str"));
jedis.lpush("lst", "a", "b", "c");
System.out.println("Type of 'lst': " + jedis.type("lst"));
jedis.sadd("set", "x", "y", "z");
System.out.println("Type of 'set': " + jedis.type("set"));
}
4. String类型操作
String类型是Redis最基础的数据结构,支持批量操作、范围截取和自增自减等特性。
public static void stringCommands(Jedis jedis) {
jedis.flushAll();
// MSET/MGET 批量操作
jedis.mset("k1", "val1", "k2", "val2", "k3", "val3");
List<String> values = jedis.mget("k1", "k2", "k3", "k4");
System.out.println("MGET result: " + values);
// GETRANGE/SETRANGE 范围操作
jedis.set("text", "HelloWorld");
String part = jedis.getrange("text", 0, 4);
System.out.println("GETRANGE [0,4]: " + part);
jedis.setrange("text", 0, "Hi");
System.out.println("After SETRANGE: " + jedis.get("text"));
// APPEND 追加
jedis.append("text", "!!!");
System.out.println("After APPEND: " + jedis.get("text"));
// INCR/DECR 原子增减
jedis.set("counter", "10");
long newVal = jedis.incr("counter");
System.out.println("After INCR: " + newVal);
newVal = jedis.decr("counter");
System.out.println("After DECR: " + newVal);
}
5. List类型操作
List支持双端插入和弹出,适合实现队列或栈结构。
public static void listCommands(Jedis jedis) {
jedis.flushAll();
// LPUSH/LRANGE
jedis.lpush("mylist", "A", "B", "C");
List<String> list = jedis.lrange("mylist", 0, -1);
System.out.println("LPUSH result: " + list);
// RPUSH/LPOP/RPOP
jedis.rpush("queue", "1", "2", "3");
System.out.println("Queue: " + jedis.lrange("queue", 0, -1));
String leftItem = jedis.lpop("queue");
String rightItem = jedis.rpop("queue");
System.out.println("LPOP: " + leftItem + ", RPOP: " + rightItem);
// LLEN 长度查询
long length = jedis.llen("queue");
System.out.println("Queue length: " + length);
}
6. Hash类型操作
Hash适用于存储对象或映射数据,支持字段级别的增删改查。
public static void hashCommands(Jedis jedis) {
jedis.flushAll();
// HSET/HGET 单字段操作
Map<String, String> fields = new HashMap<>();
fields.put("name", "Alice");
fields.put("age", "30");
fields.put("city", "London");
jedis.hset("user:1001", fields);
jedis.hset("user:1001", "email", "alice@example.com");
String name = jedis.hget("user:1001", "name");
System.out.println("Name: " + name);
// HEXISTS 字段存在检查
boolean hasEmail = jedis.hexists("user:1001", "email");
System.out.println("Has email: " + hasEmail);
// HKEYS/HVALS 获取所有字段或值
Set<String> allFields = jedis.hkeys("user:1001");
List<String> allValues = jedis.hvals("user:1001");
System.out.println("Fields: " + allFields + ", Values: " + allValues);
// HDEL 删除字段
jedis.hdel("user:1001", "email");
hasEmail = jedis.hexists("user:1001", "email");
System.out.println("After HDEL, has email: " + hasEmail);
// HMGET 批量获取
List<String> multiGet = jedis.hmget("user:1001", "name", "age", "nonExistent");
System.out.println("HMGET: " + multiGet);
}
7. Set类型操作
Set提供无序、不重复的元素集合,支持集合运算如交集、并集。
public static void setCommands(Jedis jedis) {
jedis.flushAll();
// SADD/SMEMBERS
jedis.sadd("fruits", "apple", "banana", "orange");
Set<String> fruits = jedis.smembers("fruits");
System.out.println("Fruits: " + fruits);
// SISMEMBER 成员检查
boolean exists = jedis.sismember("fruits", "apple");
System.out.println("Is 'apple' a member? " + exists);
// SCARD 基数(元素数量)
long count = jedis.scard("fruits");
System.out.println("Number of fruits: " + count);
// SPOP 随机移除并返回
String popped = jedis.spop("fruits");
System.out.println("Randomly removed: " + popped);
System.out.println("Remaining: " + jedis.smembers("fruits"));
// SINTER 交集计算与存储
jedis.sadd("setA", "1", "2", "3", "4");
jedis.sadd("setB", "3", "4", "5", "6");
Set<String> intersection = jedis.sinter("setA", "setB");
System.out.println("Intersection: " + intersection);
// 存储交集到新集合
long storedCount = jedis.sinterstore("setC", "setA", "setB");
System.out.println("Stored " + storedCount + " items to setC");
}
8. ZSet(有序集合)操作
ZSet是带分数的有序集合,适合排行榜、优先级队列等场景。
public static void zsetCommands(Jedis jedis) {
jedis.flushAll();
// ZADD/ZRANGE
jedis.zadd("scores", 85.0, "Alice");
Map<String, Double> moreScores = new HashMap<>();
moreScores.put("Bob", 92.0);
moreScores.put("Charlie", 78.0);
jedis.zadd("scores", moreScores);
List<String> members = jedis.zrange("scores", 0, -1);
System.out.println("Members in order: " + members);
// ZRANGEWITHSCORES 获取成员和分数
List<Tuple> rangeWithScores = jedis.zrangeWithScores("scores", 0, -1);
System.out.println("Members with scores: " + rangeWithScores);
// ZCARD 基数
long size = jedis.zcard("scores");
System.out.println("Number of members: " + size);
// ZSCORE 查询分数
Double aliceScore = jedis.zscore("scores", "Alice");
System.out.println("Alice's score: " + aliceScore);
// ZRANK 排名(从0开始)
Long aliceRank = jedis.zrank("scores", "Alice");
System.out.println("Alice's rank: " + aliceRank);
// ZREM 移除成员
jedis.zrem("scores", "Charlie");
size = jedis.zcard("scores");
System.out.println("After removal, size: " + size);
}
Spring环境下操作Redis
在Spring Boot项目中,通过引入 spring-boot-starter-data-redis 依赖即可自动配置Redis连接。核心操作类是 StringRedisTemplate,它封装了Jedis或Lettuce客户端,提供更简洁的模板方法。
1. 依赖与配置
创建Spring Boot项目时,在初始化器中勾选"Spring Data Redis"和"Spring Web"等必要依赖。默认配置下,Spring会连接本地的Redis服务器(localhost:6379)。
2. 注入与使用StringRedisTemplate
通过 @Autowired 注入 StringRedisTemplate 实例,即可调用其方法操作Redis。与Jedis不同,StringRedisTemplate的方法按照操作类型进行了分类,使用更加结构化。
@RestController
public class RedisController {
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping("/redis-test")
public String testRedis() {
// 使用 opsForValue() 操作String类型
redisTemplate.opsForValue().set("mykey", "Hello Spring Redis");
String value = redisTemplate.opsForValue().get("mykey");
// 使用 opsForList() 操作List类型
redisTemplate.opsForList().leftPush("mylist", "item1");
redisTemplate.opsForList().leftPush("mylist", "item2");
String listItem = redisTemplate.opsForList().leftPop("mylist");
// 使用 opsForHash() 操作Hash类型
redisTemplate.opsForHash().put("myhash", "field1", "value1");
Object hashValue = redisTemplate.opsForHash().get("myhash", "field1");
return "Value: " + value + ", ListItem: " + listItem + ", HashValue: " + hashValue;
}
}
StringRedisTemplate的子操作接口包括:
opsForValue()— 对应String命令opsForList()— 对应List命令opsForHash()— 对应Hash命令opsForSet()— 对应Set命令opsForZSet()— 对应ZSet命令
这些子操作接口的方法命名与Redis命令高度相似,保证了学习的平滑过渡。例如,opsForValue().set(key, value) 对应 SET key value,opsForList().leftPush(key, value) 对应 LPUSH key value。