springboot集成redis(緩存篇)


一 前言

公眾號:知識追尋者

知識追尋者(Inheriting the spirit of open source, Spreading technology knowledge;)

pring為我們提供的緩存注解Spring Cache。Spring支持多種緩存技術:RedisCacheManager,EhCacheCacheManager、GuavaCacheManager等,今天的內容是集成RedisCacheManager實現緩存技術;

二 Spring Cache

spring cache 常用注解如下

2.1@Cacheable

作用:查詢數據加入緩存

參數如下:

  • cacheNames 緩存名稱
  • key 緩存的key, SPEL表達式寫法
  • condition 緩存執行的條件,返回true時候執行

2.2@CachePut

作用:修改了數據庫的數據,同時更新緩存。

參數如下:

  • cacheNames 緩存名稱
  • key 緩存的key, SPEL表達式寫法
  • condition 緩存執行的條件,返回true時候執行

2.3@CacheEvict

作用:刪除數據,刪除緩存

參數如下:

  • allEntries boolean類型,表示是否需要清除緩存中的所有元素
  • key 需要刪除的緩存的key

三 集成配置

3.1 依賴

springboot 2.1.1

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
    </dependencies>

3.2 application.yml

主要是 redis 和 數據庫 鏈接配置;如果使用mysql 自行更好 數據庫鏈接驅動和依賴;

server:
  port: 9000

spring:
  redis:
    # Redis服務器地址
    host: localhost
    #Redis服務器連接端口
    port: 6379
    #password:
    # Redis數據庫索引(默認為0)
    database: 2
    # 連接超時時間(毫秒)
    timeout: 5000
    jedis:
      pool:
        #連接池最大連接數(使用負值表示沒有限制)
        max-active: 100
        # 連接池中的最小空閑連接
        max-idle: 10
        # 連接池最大阻塞等待時間(使用負值表示沒有限制)
        max-wait: 100000
  #數據庫配置
  datasource:
    driverClassName: org.postgresql.Driver
    url: jdbc:postgresql://127.0.0.1:5432/springboot
    username: postgres
    password: 123456

logging:
  level:
    com.zszxz.cach.mapper : debug

3.3 redis配置

主要是設置 CacheManagerredisTemplate; 並且支持默認key 過期時間,和亂碼問題解決;

/**
 * @Author lsc
 * <p> redis配置 </p>
 */
@Configuration
@EnableCaching
public class RedisConfig  extends CachingConfigurerSupport {



    /* *
     * @Author lsc
     * <p>自定義生成key的規則 </p>
     * @Param []
     * @Return KeyGenerator
     */
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                //格式化緩存key字符串
                StringBuilder sb = new StringBuilder();
                //追加類名
                sb.append(o.getClass().getName());
                //追加方法名
                sb.append(method.getName());
                //遍歷參數並且追加
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解決查詢緩存轉換異常的問題
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // 配置序列化(解決亂碼的問題),過期時間120秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(120))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 創建redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        // 使用Jackson2JsonRedisSerialize替換默認序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //set value serializer
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // value序列化方式采用jackson
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}

3.3 使用注解集成redis緩存

/* *
     * @Author lsc
     * <p>先從緩存中讀取,如果沒有再從DB獲取數據,然后把數據添加到緩存中
     * unless 表示條件表達式成立的話不放入緩存
     * 如果 設置 ,keyGenerator = "keyGenerator" 就不能設置 key
     *  </p>
     * @Param [user_id]
     * @Return com.zszxz.cach.entity.UserEntity
     */
    @Override
    @Cacheable(cacheNames = "UserEntity", key = "#user_id")
    public UserEntity getUser(Long user_id) {
        return userMapper.getUser(user_id);
    }


    /* *
     * @Author lsc
     * <p>修改了數據庫的數據,同時更新緩存。先調用目標方法,然后緩存方法結果 </p>
     * @Param [userEntity]
     * @Return int
     */
    @Override
    @CachePut(cacheNames = "UserEntity", key = "#result.user_id")
    public UserEntity updateUser(UserEntity userEntity) {
        userMapper.updateUser(userEntity);
        // 注意,會將緩存更新未參數userEntity里面的值
        return userEntity;
    }

    /* *
     * @Author lsc
     * <p>allEntries 是否清空所有緩存內容,缺省為 false,如果指定為 true,則方法調用后將立即清空所有緩存
     * 指定刪除一條緩存
     * </p>
     * @Param [user_id]
     * @Return int
     */
    @Override
    @CacheEvict(cacheNames = "UserEntity", key = "#user_id")
    public int delUser(Long user_id) {
        return userMapper.delUser(user_id);
    }

四 測試

4.1 查詢測試

測試代碼

    @Test
    public void testGet(){
        UserEntity user = userService.getUser(1L);
        System.out.println(user);
    }

第一次查詢控制台會打印SQL,第二次查詢不會打印SQL,直接從redis獲取

4.2 修改緩存測試

修改緩存的結果是方法的返回值,由於這邊式參數直接作為返回值,故參數用戶實體的屬性必須是全屬性,否則查詢緩存時會出現多個參數是null,而數據庫中有值;比如這邊的user_telephone字段;

    @Test
    public void testPUT(){
        UserEntity userEntity = new UserEntity();
        userEntity.setUser_id(1L);
        userEntity.setUser_name("知識追尋者");
        userEntity.setUser_gender("female");
        userService.updateUser(userEntity);
    }

4.3 刪除緩存測試

刪除緩存后直接刪除指定key的一條緩存;

    @Test
    public void testDel(){
        userService.delUser(1L);
    }

有關sping cahe 學習參照如下鏈接

https://blog.csdn.net/u012240455/article/details/80844361


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM