springboot使用redisTemplate的方法,详细说明

发布于:2025-07-03 ⋅ 阅读:(21) ⋅ 点赞:(0)

1. 添加依赖

pom.xml中添加Spring Data Redis依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 说明:该依赖集成了Redis客户端(默认使用Lettuce)和RedisTemplate工具类。

2. 配置Redis连接信息

application.yml中配置Redis服务器信息:

spring:
  redis:
    host: localhost        # Redis服务器地址
    port: 6379             # Redis服务器端口
    password: yourpassword # Redis密码(如果有)
    database: 0            # 使用的数据库索引(0-15)
    timeout: 3000ms        # 连接超时时间
    lettuce:               # 使用Lettuce客户端(默认)
      pool:
        max-active: 8      # 最大连接数
        max-wait: -1ms     # 最大等待时间
        max-idle: 8        # 最大空闲连接
        min-idle: 0        # 最小空闲连接

3. 配置RedisTemplate

Spring Boot默认提供了StringRedisTemplate(键值对为字符串),但通常需要自定义RedisTemplate以支持对象序列化。

3.1 自定义RedisTemplate配置
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 设置Key的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        // 设置Value的序列化方式(JSON格式)
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        // 设置HashKey的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        // 设置HashValue的序列化方式
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        template.afterPropertiesSet();
        return template;
    }
}
  • 序列化说明
    • StringRedisSerializer:将键值序列化为字符串。
    • GenericJackson2JsonRedisSerializer:将对象序列化为JSON格式,支持泛型和复杂对象。

4. RedisTemplate常用操作

RedisTemplate提供了多种操作接口,对应Redis的不同数据结构。

4.1 操作字符串(String)
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void operateString() {
    // 存储值(永久有效)
    redisTemplate.opsForValue().set("name", "张三");
    
    // 存储值(带过期时间)
    redisTemplate.opsForValue().set("age", 20, 10, TimeUnit.SECONDS);
    
    // 获取值
    String name = (String) redisTemplate.opsForValue().get("name");
    Integer age = (Integer) redisTemplate.opsForValue().get("age");
    
    // 递增/递减(适用于数值类型)
    redisTemplate.opsForValue().increment("counter", 1);
}
4.2 操作哈希(Hash)
public void operateHash() {
    HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
    
    // 存储Hash
    hashOps.put("user:1", "name", "李四");
    hashOps.put("user:1", "age", 25);
    
    // 获取单个字段
    String username = (String) hashOps.get("user:1", "name");
    
    // 获取整个Hash
    Map<String, Object> user = hashOps.entries("user:1");
    
    // 获取所有字段名和值
    Set<String> keys = hashOps.keys("user:1");
    List<Object> values = hashOps.values("user:1");
}
4.3 操作列表(List)
public void operateList() {
    ListOperations<String, Object> listOps = redisTemplate.opsForList();
    
    // 左插入(栈结构)
    listOps.leftPush("tasks", "task1");
    listOps.leftPushAll("tasks", "task2", "task3");
    
    // 右插入(队列结构)
    listOps.rightPush("tasks", "task4");
    
    // 获取列表范围
    List<Object> tasks = listOps.range("tasks", 0, -1);
    
    // 弹出元素
    Object task = listOps.leftPop("tasks");
}
4.4 操作集合(Set)
public void operateSet() {
    SetOperations<String, Object> setOps = redisTemplate.opsForSet();
    
    // 添加元素
    setOps.add("fruits", "apple", "banana", "cherry");
    
    // 获取所有元素
    Set<Object> fruits = setOps.members("fruits");
    
    // 判断元素是否存在
    boolean exists = setOps.isMember("fruits", "apple");
    
    // 移除元素
    setOps.remove("fruits", "banana");
}
4.5 操作有序集合(ZSet)
public void operateZSet() {
    ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
    
    // 添加元素(带分数,用于排序)
    zSetOps.add("ranking", "player1", 100);
    zSetOps.add("ranking", "player2", 200);
    zSetOps.add("ranking", "player3", 150);
    
    // 获取排名(从小到大)
    Set<Object> ranking = zSetOps.range("ranking", 0, -1);
    
    // 获取分数
    Double score = zSetOps.score("ranking", "player2");
    
    // 增加分数
    zSetOps.incrementScore("ranking", "player1", 50);
}

5. 高级功能

5.1 事务操作
public void transactionExample() {
    redisTemplate.execute(new SessionCallback<Object>() {
        @Override
        public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
            operations.multi(); // 开启事务
            operations.opsForValue().set((K) "tx-key1", (V) "value1");
            operations.opsForValue().set((K) "tx-key2", (V) "value2");
            return operations.exec(); // 执行事务
        }
    });
}
5.2 管道操作(批量执行)
public void pipelineExample() {
    List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            StringRedisConnection stringConn = (StringRedisConnection) connection;
            for (int i = 0; i < 1000; i++) {
                stringConn.set("key:" + i, "value:" + i);
            }
            return null;
        }
    });
}
5.3 发布订阅
// 发布消息
public void publishMessage(String channel, String message) {
    redisTemplate.convertAndSend(channel, message);
}

// 订阅消息(需配置Listener)
@Component
public class RedisMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(message.getChannel());
        String content = new String(message.getBody());
        System.out.println("收到消息: " + content + " from channel: " + channel);
    }
}
5.4 分布式锁
public void distributedLockExample() {
    String lockKey = "resource-lock";
    Boolean locked = redisTemplate.opsForValue().setIfAbsent(
        lockKey, "locked", 30, TimeUnit.SECONDS); // 原子操作
    
    if (locked) {
        try {
            // 执行需要加锁的业务逻辑
        } finally {
            redisTemplate.delete(lockKey); // 释放锁
        }
    }
}

6. 对象序列化与反序列化

存储自定义对象时,确保对象实现Serializable接口,并使用JSON序列化:

6.1 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String id;
    private String name;
    private Integer age;
}
6.2 存储和读取对象
public void saveAndGetUser() {
    User user = new User("1", "王五", 30);
    
    // 存储对象
    redisTemplate.opsForValue().set("user:1", user);
    
    // 读取对象
    User result = (User) redisTemplate.opsForValue().get("user:1");
}

7. 常见问题与优化

7.1 序列化性能问题
  • JSON序列化比JDK原生序列化更高效,但需注意循环引用问题。
  • 对性能敏感的场景,可使用ProtostuffKryo替代JSON序列化。
7.2 连接池配置
spring:
  redis:
    lettuce:
      pool:
        max-active: 100  # 最大连接数
        max-wait: 1000ms # 获取连接的最大等待时间
        max-idle: 20     # 最大空闲连接
        min-idle: 5      # 最小空闲连接
7.3 异常处理
try {
    // Redis操作
} catch (RedisConnectionFailureException e) {
    // 处理连接失败
    log.error("Redis连接失败", e);
} catch (RedisSystemException e) {
    // 处理系统异常
    log.error("Redis系统异常", e);
}

8. 与缓存注解结合(@Cacheable)

Spring Cache抽象提供了@Cacheable@CacheEvict等注解,可与Redis集成:

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUser(String id) {
        // 从数据库查询
        return userRepository.findById(id);
    }

    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(String id) {
        // 删除用户
        userRepository.deleteById(id);
    }
}