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

相关推荐
李慕婉学姐22 分钟前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
m0_7400437329 分钟前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
招风的黑耳2 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
Miss_Chenzr2 小时前
Springboot优卖电商系统s7zmj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
期待のcode2 小时前
Springboot核心构建插件
java·spring boot·后端
2501_921649492 小时前
如何获取美股实时行情:Python 量化交易指南
开发语言·后端·python·websocket·金融
serendipity_hky2 小时前
【SpringCloud | 第5篇】Seata分布式事务
分布式·后端·spring·spring cloud·seata·openfeign
五阿哥永琪3 小时前
Spring Boot 中自定义线程池的正确使用姿势:定义、注入与最佳实践
spring boot·后端·python
Victor3563 小时前
Netty(16)Netty的零拷贝机制是什么?它如何提高性能?
后端
Victor3563 小时前
Netty(15)Netty的线程模型是什么?它有哪些线程池类型?
后端