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使用需求,并提供了良好的扩展性和维护性。

相关推荐
BingoGo1 小时前
使用 PHP 和 Raylib 也可以开发贪吃蛇游戏
后端·php
codercwh2 小时前
3 分钟上手 Claude Code!API 中转站让 AI 编程效率翻倍
后端
SimonKing2 小时前
OCR告别付费!分享两款可部署的开源工具
后端
爱叫啥叫啥2 小时前
STM32从零实战:深入理解RCC时钟与按键控制LED的底层原理
后端
火山引擎开发者社区2 小时前
火山引擎 MongoDB 进化史:从扛住抖音流量洪峰到 AI 数据底座
后端
星星电灯猴2 小时前
API接口调试全攻略 Fiddler抓包工具、HTTPS配置与代理设置实战指南
后端
程序员爱钓鱼3 小时前
Python 编程实战:环境管理与依赖管理(venv / Poetry)
后端·python·trae
w***48823 小时前
Spring Boot3.x集成Flowable7.x(一)Spring Boot集成与设计、部署、发起、完成简单流程
java·spring boot·后端
程序员爱钓鱼3 小时前
Python 编程实战 :打包与发布(PyInstaller / pip 包发布)
后端·python·trae