首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring Boot 整合 Redis 實現快取機制:從零開始的完整指南

     編輯:Java 相關知識

技術棧與前置需求

  • Spring Boot 1.3.3+
  • Spring Data JPA
  • Redis Server(本地安裝啟動)
  • MySQL(或嵌入式 H2 測試)
  • Maven 專案結構

專案結構總覽

spring-boot-redis
├── pom.xml
├── src/main/java/com/kfit
│   ├── App.java                          # 啟動類
│   ├── config/RedisCacheConfig.java      # Redis 快取配置
│   ├── bean/DemoInfo.java                # 實體類
│   ├── repository/DemoInfoRepository.java # JPA Repository
│   ├── service/
│   │   ├── DemoInfoService.java          # 服務介面
│   │   └── impl/DemoInfoServiceImpl.java # 服務實作
│   └── controller/DemoInfoController.java # 控制器
└── src/main/resources/application.properties

1. Maven 依賴配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.3.RELEASE</version>
</parent>

<dependencies>
    <!-- Web + AOP -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- 快取支援 (EhCache, Redis 等) -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    
    <!-- Redis Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-redis</artifactId>
    </dependency>
    
    <!-- JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    <!-- MySQL 驅動 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    <!-- 測試 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2. 啟動類

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

3. application.properties 完整配置

# ===== MySQL 資料源 =====
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10

# ===== Redis 配置 =====
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
# spring.redis.password=  # 若有密碼取消註解
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1

# ===== JPA 配置 =====
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

4. Redis 快取核心配置類

基礎版(使用預設 KeyGenerator)

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 預設使用 JdkSerializationRedisSerializer,Key 會顯示為亂碼
        return template;
    }
}

進階版:自訂 KeyGenerator + 可讀 Key 序列化

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // Key 使用 String 序列化,人類可讀
        RedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        // Value 仍用 JDK 序列化支援任意物件
        return template;
    }

    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object param : params) {
                sb.append(param.toString());
            }
            String key = sb.toString();
            System.out.println("KeyGenerator: " + key);
            return key;
        };
    }
}

關鍵點:繼承 CachingConfigurerSupport 並覆寫 keyGenerator(),全域生效無需在 @Cacheable 指定。

5. 實體與 Repository

@Entity
public class DemoInfo implements Serializable {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private String pwd;
    // getter/setter/toString
}

public interface DemoInfoRepository extends CrudRepository { }

6. 服務層:快取註解實戰

@Service
public class DemoInfoServiceImpl implements DemoInfoService {

    @Autowired DemoInfoRepository repo;
    @Autowired RedisTemplate redisTemplate;

    @Override
    @Cacheable(value = "demoInfo")  // 使用自訂 KeyGenerator
    public DemoInfo findById(Long id) {
        System.err.println("DB 查詢: id=" + id);
        return repo.findOne(id);
    }

    @Override
    @CacheEvict(value = "demoInfo")
    public void deleteFromCache(Long id) {
        System.out.println("快取清除: id=" + id);
    }

    public void test() {
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set("mykey4", "random1=" + Math.random());
        System.out.println(ops.get("mykey4"));
    }
}

7. 控制器測試端點

@RestController
public class DemoInfoController {

    @Autowired DemoInfoService service;

    @GetMapping("/test")
    public String test() {
        DemoInfo d1 = service.findById(1L);  // 第1次:DB
        DemoInfo d2 = service.findById(1L);  // 第2次:快取
        DemoInfo d3 = service.findById(2L);  // DB
        return "ok";
    }

    @GetMapping("/delete")
    public String delete(@RequestParam Long id) {
        service.deleteFromCache(id);
        return "ok";
    }

    @GetMapping("/test1")
    public String test1() {
        service.test();  // 直接操作 RedisTemplate
        return "ok";
    }
}

8. 驗證快取效果

啟動應用,呼叫 GET /test

DB 查詢: id=1
loaded=DemoInfo[id=1, name=張三, pwd=123456]
cached=DemoInfo[id=1, name=張三, pwd=123456]   # 無 DB 日誌 = 命中快取
DB 查詢: id=2
loaded2=DemoInfo[id=2, name=張三, pwd=123456]

第二次呼叫 GET /test(全快取命中)

loaded=DemoInfo[id=1, name=張三, pwd=123456]
cached=DemoInfo[id=1, name=張三, pwd=123456]
loaded2=DemoInfo[id=2, name=張三, pwd=123456]

清除快取後 GET /delete?id=1 再呼叫 /test

快取清除: id=1
DB 查詢: id=1
loaded=DemoInfo[id=1, name=張三, pwd=123456]
cached=DemoInfo[id=1, name=張三, pwd=123456]
loaded2=DemoInfo[id=2, name=張三, pwd=123456]

Redis Client 查看 Key(自訂 KeyGenerator 後)

127.0.0.1:6379> KEYS *
1) "com.kfit.service.impl.DemoInfoServiceImplfindById1"
2) "com.kfit.service.impl.DemoInfoServiceImplfindById2"

9. 進階主題與最佳實踐

主題說明
@Cacheable 進階屬性 key 指定 SpEL 表達式、condition 條件快取、unless 結果過濾、sync 同步載入防穿透
@CacheEvict 進階 allEntries=true 清空整個 Cache、beforeInvocation=true 方法前清除
@CachePut 方法總是執行並更新快取,不阻擋方法執行
@Caching 組合多個快取操作
快取失效策略 TTL 過期、主動清除、CacheManager 配置預設過期時間
序列化選擇 StringRedisSerializer(Key)、GenericJackson2JsonRedisSerializer(Value,可讀+型別安全)
Redis Cluster 支援 Spring Boot 2.x+ 自動支援,配置 spring.redis.cluster.nodes

常見坑點避雷

  • 自訂 KeyGenerator 但未設 Key 序列化:Key 為 Object,預設 JDK 序列化 → Redis 顯示亂碼
  • Key 衝突:不同方法同參數產生相同 Key → 錯誤命中。解決:KeyGenerator 包含類名+方法名
  • 非 Spring Bean 類別使用註解無效:需由 Spring 管理(@Service/@Component)且透過注入使用,內部自調用不生效(AOP 代理限制)
  • 快取穿透/雪崩/擊穿:高併發場景需加互斥鎖、佈隆過濾器、隨機 TTL 等防護

總結

Spring Boot + Spring Cache + Redis 實現聲明式快取極其簡潔。核心步驟:引入 Starter → 配置連線 → @EnableCaching → 定義 CacheManager → 業務方法加 @Cacheable/@CacheEvict。掌握 KeyGenerator 客製化、序列化策略、失效模式,即可應對生產環境多數快取場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved