Spring Boot如何整合Redis

1. 项目依赖配置

Maven依赖

xml 复制代码
<dependencies>
    <!-- Redis Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    <!-- 连接池依赖(可选但推荐) -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
</dependencies>

2. Redis基础配置

application.yml配置

yaml 复制代码
spring:
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

Redis配置类

java 复制代码
@Configuration
@EnableCaching
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用Jackson2JsonRedisSerializer序列化value
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LazyCollectionResolver.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        
        template.setValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        
        return template;
    }
}

3. 基础操作示例

RedisTemplate基本操作

java 复制代码
@Service
public class RedisService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 设置字符串值
     */
    public void setString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }
    
    /**
     * 获取字符串值
     */
    public String getString(String key) {
        Object result = redisTemplate.opsForValue().get(key);
        return result != null ? result.toString() : null;
    }
    
    /**
     * 设置带过期时间的键值对
     */
    public void setStringWithExpire(String key, String value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }
    
    /**
     * 删除键
     */
    public Boolean deleteKey(String key) {
        return redisTemplate.delete(key);
    }
    
    /**
     * 批量删除键
     */
    public Long deleteKeys(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }
    
    /**
     * 判断键是否存在
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }
    
    /**
     * 设置过期时间
     */
    public Boolean expire(String key, long timeout, TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }
}

Hash操作示例

java 复制代码
@Service
public class RedisHashService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 向Hash中添加字段
     */
    public void putHashField(String key, String field, Object value) {
        redisTemplate.opsForHash().put(key, field, value);
    }
    
    /**
     * 获取Hash中的字段值
     */
    public Object getHashField(String key, String field) {
        return redisTemplate.opsForHash().get(key, field);
    }
    
    /**
     * 获取整个Hash
     */
    public Map<Object, Object> getHashAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    
    /**
     * 删除Hash中的字段
     */
    public Long deleteHashFields(String key, Object... fields) {
        return redisTemplate.opsForHash().delete(key, fields);
    }
}

4. 缓存注解使用

启用缓存

java 复制代码
@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Service层缓存应用

java 复制代码
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    /**
     * 查询用户 - 使用缓存
     * @Cacheable: 先查缓存,没有则执行方法并将结果放入缓存
     */
    @Cacheable(value = "users", key = "#id")
    public User findById(Long id) {
        System.out.println("从数据库查询用户: " + id);
        return userRepository.findById(id).orElse(null);
    }
    
    /**
     * 更新用户 - 清除缓存
     * @CacheEvict: 清除指定缓存
     */
    @CacheEvict(value = "users", key = "#user.id")
    public User updateUser(User user) {
        System.out.println("更新用户: " + user.getId());
        return userRepository.save(user);
    }
    
    /**
     * 删除用户 - 清除缓存
     */
    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        System.out.println("删除用户: " + id);
        userRepository.deleteById(id);
    }
    
    /**
     * 清除所有用户缓存
     * @CacheEvict(allEntries = true): 清除所有缓存
     */
    @CacheEvict(value = "users", allEntries = true)
    public void clearAllUserCache() {
        System.out.println("清除所有用户缓存");
    }
}

自定义缓存Key生成策略

java 复制代码
@Component
public class CustomKeyGenerator implements KeyGenerator {
    
    @Override
    public Object generate(Object target, Method method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getSimpleName());
        sb.append("_");
        sb.append(method.getName());
        for (Object obj : params) {
            sb.append("_");
            sb.append(obj.toString());
        }
        return sb.toString();
    }
}

// 使用自定义Key生成器
@Cacheable(value = "users", keyGenerator = "customKeyGenerator")
public List<User> findAllUsers() {
    return userRepository.findAll();
}

5. Session共享配置

Session配置

java 复制代码
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
    
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        serializer.setCookiePath("/");
        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
        return serializer;
    }
}

6. 分布式锁实现

Redis分布式锁工具类

java 复制代码
@Component
public class RedisDistributedLock {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final String LOCK_PREFIX = "lock:";
    private static final int DEFAULT_EXPIRE_TIME = 30; // 默认过期时间(秒)
    
    /**
     * 获取分布式锁
     */
    public boolean lock(String key, String value, int expireTime) {
        String lockKey = LOCK_PREFIX + key;
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, value, expireTime, TimeUnit.SECONDS);
        return result != null && result;
    }
    
    /**
     * 释放分布式锁
     */
    public boolean unlock(String key, String value) {
        String lockKey = LOCK_PREFIX + key;
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Boolean result = redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), 
                                              Collections.singletonList(lockKey), value);
        return result != null && result;
    }
}

7. 性能监控配置

Redis监控配置

java 复制代码
@Configuration
public class RedisMonitorConfig {
    
    @Bean
    public RedisTemplate<String, Object> monitoredRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        return template;
    }
    
    @EventListener
    public void handleRedisMessage(RedisMessageEvent event) {
        // 监控Redis消息事件
        System.out.println("Redis事件: " + event.getMessage());
    }
}

8. 最佳实践建议

配置优化要点:

  • 连接池配置:合理设置最大连接数和空闲连接数
  • 序列化方式:推荐使用JSON序列化替代默认的JDK序列化
  • 超时设置:设置合适的连接和读取超时时间
  • 缓存失效策略:根据业务场景设置合理的过期时间和淘汰策略

注意事项:

  • 缓存穿透:对于查询不到的数据也要缓存空值
  • 缓存雪崩:避免大量缓存在同一时间失效
  • 缓存击穿:热点数据使用互斥锁保护
  • 内存管理:定期清理无用缓存,防止内存溢出

这样的整合方案能够满足大部分Spring Boot项目的Redis使用需求,并提供了良好的扩展性和维护性。

相关推荐
阿丰资源11 分钟前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
IT_陈寒13 分钟前
SpringBoot自动配置的坑差点让我加班到天亮
前端·人工智能·后端
消失的旧时光-19431 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
追风筝的人er2 小时前
SpringBoot+Vue3 企业考勤如何处理法定假期?节假日方案、调休补班与工作日判断链路拆解
前端·vue.js·后端
金銀銅鐵3 小时前
[git] 如何丢弃对一个文件的改动?
git·后端
橘子海全栈攻城狮3 小时前
【最新源码】养老院系统管理A013
java·spring boot·后端·web安全·微信小程序
smallyoung4 小时前
具有反思能力的 Agentic RAG 实战:用 LangChain4j 实现 CRAG 纠错检索
人工智能·后端
EthanYuan4 小时前
💡RAG实践:从云知识库迁移到PostgreSQL ,并使用PGVector实现向量存储
后端
直奔標竿4 小时前
Java开发者AI转型第二十六课!Spring AI 个人知识库实战(五)——联网搜索增强实战
java·开发语言·人工智能·spring boot·后端·spring
等风来_shy4 小时前
如何写好一个 Skill
后端