IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 整合SpringCache简化缓存开发以及实例 -> 正文阅读

[大数据]整合SpringCache简化缓存开发以及实例

1.引入依赖

pom.xml增加依赖

        <!-- 引入redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>

        <!--引入springCache-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>
2.写配置文件

? a.引入后自动配置?

? CacheAutoConfiguration 会导入RedisCacheConfiguration 自动配置好了管理器 RedisCacheManager

? b. 初始化缓存配置

【思路】 最终配置文件在最后步骤

spring.cache.type=redis
spring.redis.host=192.168.31.125
spring.redis.password=
spring.redis.port=6379
3.测试使用缓存

【—>】@Cacheable :触发将数据保存到缓存的操作

【—>】@CacheEvict: 触发将数据从缓存删除的操作

【—>】@CachePut: 不影响方法执行更新缓存

【—>】@Caching: 组合操作缓存

【—>】@CacheConfig: 在类级别(相同的类)上共享缓存配置

? a.开启缓存 @EnableCaching

【思路】

@EnableCaching//后续不在这里
@SpringBootApplication
public class GulimallProductApplication {

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

}

? b.只需要注解就能开启缓存操作

【思路】@Cacheable :触发将数据保存到缓存的操作

【—>】@Cacheable({“category”})

调用数据 有缓存读取缓存并且方法不会被调用。 没有缓存就先写入缓存

保存一级菜单

    //缓存的数据 需要制定放到名字的缓存【缓存的分区 按照业务类型分区】
    @Cacheable({"category"}) //当前方法需要缓存 如果缓存中有 方法不用调用 如果方法中没有 调用方法并将方法结果放入缓存
    @Override
    public List<CategoryEntity> getLevel1Categorys() {
        System.out.println("调用方法查询一级分类了");
        return baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid",0));
    }

保存二级菜单

    /**
     * 用springCache替代 两个方法
     * @return
     */
    @Cacheable(value = {"category"},key="#root.methodName")
    @Override
    public Map<String, List<Catelog2Vo>>  getCatalogJson() {
        System.out.println("进入了查数据库逻辑");
        List<CategoryEntity> selectList = baseMapper.selectList(null);

        //1.查出所有1级分类
        List<CategoryEntity> level1Categorys = getParent_cid(selectList, 0L);
        //封装数据
        Map<String, List<Catelog2Vo>> collect = level1Categorys.stream().collect(Collectors.toMap(k -> {
            return k.getCatId().toString();
        }, v -> {
            //每一个的一级分类 查到这个一级分类的所有二级分类
            List<CategoryEntity> categoryEntities = getParent_cid(selectList, v.getCatId());
            List<Catelog2Vo> catelog2Vos = null;
            if (categoryEntities != null) {
                catelog2Vos = categoryEntities.stream().map(level2 -> {

                    //查处当前二级分类下的所有三级分类
                    List<CategoryEntity> levl3Catelog = getParent_cid(selectList, level2.getCatId());
                    List<Catelog2Vo.Catelog3Vo> catelog3VoList = null;
                    if (levl3Catelog != null) {
                        catelog3VoList = levl3Catelog.stream().map(level3 -> {
                            new Catelog2Vo.Catelog3Vo("", "", "");
                            Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(
                                    level2.getCatId().toString(),
                                    level3.getCatId().toString(),
                                    level3.getName()
                            );
                            return catelog3Vo;
                        }).collect(Collectors.toList());
                    }


                    Catelog2Vo catelog2Vo = new Catelog2Vo(
                            v.getCatId().toString(),
                            catelog3VoList,
                            level2.getCatId().toString(),
                            level2.getName()
                    );
                    return catelog2Vo;
                }).collect(Collectors.toList());
            }
            return catelog2Vos;
        }));
        return collect;
    }

默认行为:

? 缓存汇总有结果 这个备注接的方法就不会被调用了

缓存key自动生成 缓存名字: ::SimpleKey

? 缓存value值 默认使用jdk的序列化机制 将序列化后的数据存入redis

? 默认时间 -1 不过期

自定义:

1) 指定的生成缓存的key @Cacheable key接收的是表达式 key="‘someRedisKey’" 或者用方法名key="#root.method.name"

2) 指定缓存的过期时间 配置文件修改 spring.cache.redis.time-to-live=60000 单位ms

3) 数据保存为json格式

【思路】

修改配置方法:
@EnableCaching
@Configuration
public class MyCacheConfig {
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(){


        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // key value序列化机制
        System.out.println("执行Cache的配置类");
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return config;
    }
}


会导致配置文件失效 如下处理
原因如下代码展示: 注意那个return this.redisCacheConfiguration;

【思路】

if (this.redisCacheConfiguration != null) {
   		return this.redisCacheConfiguration;
   	}
   	Redis redisProperties = this.cacheProperties.getRedis();
   	org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
   			.defaultCacheConfig();
   	config = config.serializeValuesWith(SerializationPair
   			.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
   	if (redisProperties.getTimeToLive() != null) {
   		config = config.entryTtl(redisProperties.getTimeToLive());
   	}
   	if (redisProperties.getKeyPrefix() != null) {
   		config = config.prefixKeysWith(redisProperties.getKeyPrefix());
   	}
   	if (!redisProperties.isCacheNullValues()) {
   		config = config.disableCachingNullValues();
   	}
   	if (!redisProperties.isUseKeyPrefix()) {
   		config = config.disableKeyPrefix();
   	}
   	return config;

代码指出,如果走了配置类 那么底下的几个if 就没有进行 我们把下面的几个信息需要重新写进配置类

原先的配置类样子:

【思路】

@ConfigurationProperties(prefix = "spring.cache")
public class CacheProperties {
    ...

给配置类加入注解 修改配置类

最终配置类

@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
@Configuration
public class MyCacheConfig {

    /**
     *1. 配置文件中的内容没有读取:
     * @ConfigurationProperties(prefix = "spring.cache")
     * public class CacheProperties {
     * 2.让这个配置文件绑定生效 class注解导入:@EnableConfigurationProperties(CacheProperties.class)
     *     使用A:
     *     @Autowired
     *     CacheProperties cacheProperties;
     *     使用B:
     *     当做参数传给方法
     *
     * @return
     */


    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        //引用配置类 需要把配置文件都带过来
//        config = config.entryTtl(Duration.ofSeconds(90));
        // key value序列化机制
        System.out.println("执行Cache的配置类");
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        CacheProperties.Redis redisProperties = cacheProperties.getRedis();

        //将配置文件中的内容拿过来
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }


        return config;
    }
}
4.配置原理

? CacheAutoConfiguration

-> RedisCacheConfiguration

-> 自动配置 RedisCacheMannager

->初始化所有的缓存

-> 每个缓存决定配置【RedisCacheConfiguration 有:就有 无:用默认】

? 修改缓存配置 需要给容器 放置一个RedisCacheConfiguration

-> 应用当前RedisCacheMannager 管理的所有缓存分区

最终的配置文件

redis.properties

spring.cache.type=redis
spring.redis.host=192.168.31.125
spring.redis.password=
spring.redis.port=6379
spring.cache.redis.time-to-live=180000
#spring.cache.redis.key-prefix=CACHE_
#spring.cache.redis.use-key-prefix=true
#是否缓存控制 解决缓存穿透问题
spring.cache.redis.cache-null-values=true

验证注解的修改数据:

【思路】

【—>】 @CacheEvict(value = {“category”},key="‘getLevel1Categorys’")

更新数据时 调用清除缓存 (读取时候 发现缓存为空 为给与填充)

    //删除一级菜单
	@CacheEvict(value = {"category"},key="'getLevel1Categorys'")
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

【—>】@Caching: 组合操作演示

 	//删除一二级菜单
	@Caching(evict = {
            @CacheEvict(value = {"category"} ,key = "'getLevel1Categorys'"),
            @CacheEvict(value = {"category"} ,key = "'getCatalogJson'")
    })
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }
//删除整个分区的数据 一二级都在category分区
    @CacheEvict(value = {"category"},allEntries = true)
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

【—>】@CachePut: 不影响方法执行更新缓存

对比@CacheEvict 返回值的数据需要替换redis缓存内容 不需要在下次读数据发现没有再填入数据。它的要求是数据要有返回值。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-25 08:11:03  更:2021-11-25 08:11:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:12:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码