最新版高性能网站建设指南,哪里专业做网站,网络营销模式有哪些类型,电商企业网页设计1.为什么需要缓存
前台请求#xff0c;后台先从缓存中取数据#xff0c;取到直接返回结果#xff0c;取不到时从数据库中取#xff0c;数据库取到更新缓存#xff0c;并返回结果#xff0c;数据库也没取到#xff0c;那直接返回空结果#xff1a; 使用缓存是一个很…1.为什么需要缓存
前台请求后台先从缓存中取数据取到直接返回结果取不到时从数据库中取数据库取到更新缓存并返回结果数据库也没取到那直接返回空结果 使用缓存是一个很“高性价比”的性能优化方式尤其是对于有大量重复查询的程序来说。通常来说在WEB后端应用程序来说
耗时比较大的往往有两个地方
1、查数据库
2、调用其它服务的API因为其它服务最终也要去做查数据库等耗时操作
重复查询也有两种
1、我们在应用程序中代码写得不好写的for循环可能每次循环都用重复的参数去查询了。
2、大量的相同或相似请求造成的。比如资讯网站首页的文章列表、电商网站首页的商品列表、微博等社交媒体热搜的文章等等当大量的用户都去请求同样的接口同样的数据如果每次都去查数据库那对数据库来说是一个不可承受的压力。所以我们通常会把高频的查询进行缓存我们称它为“热点”。
2.SpringCache概述
前面提到了缓存有诸多的好处于是大家就摩拳擦掌准备给自己的应用加上缓存的功能。但是网上一搜却发现缓存的框架太多了各有各的优势比如Redis[中央缓存-远程缓存]、Memcached、Guava、Caffeine[本地缓存]等等。
如果我们的程序想要使用缓存就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了利用面向对象的抽象和多态的特性做到业务代码与具体的框架分离。
但我们仍然需要显式地在代码中去调用与缓存有关的接口和方法在合适的时候插入数据到缓存里在合适的时候从缓存中读取数据。想一想**「AOP」**的适用场景这不就是天生就应该AOP去做的吗
自Spring 3.1起提供了类似于 Transactional 注解事务的注解Cache支持且提供了Cache抽象在此之前一般通过AOP实现。
使用Spring Cache的好处
提供基本的Cache抽象方便切换各种底层Cache通过注解Cache可以实现类似于事务一样缓存逻辑透明的应用到我们的业务代码上且只需要更少的代码就可以完成提供事务回滚时也自动回滚缓存支持比较复杂的缓存逻辑
2.1SpringCache概述及核心配置
Spring Cache就是一个缓存框架。它利用了AOP将缓存逻辑与服务逻辑解耦实现了基于注解的缓存功能声明式缓存并且进行了合理的抽象业务代码不用关心底层是使用了什么缓存框架只需要简单地加一个注解就能实现缓存功能了。而且Spring Cache也提供了很多默认的配置用户可以快速将缓存集成到项目中
接下来我们以一个很小的例子给大家讲解SpringCache的快速使用
2.2. SpringCache环境准备
导入:day12\SpringCache缓存专题\代码\springboot-cache项目代码
核心步骤如下
2.2.1 缓存依赖导入
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId
/dependency
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency2.2.2 环境配置
#数据库配置
spring:redis:host: 192.168.200.130 # Redis服务器地址database: 1 # Redis数据库索引默认为0port: 6379 # Redis服务器连接端口
# password: ld123456 # Redis服务器连接密码默认为空2.2.3 缓存配置类定义
SpringCache抽象出公共的缓存接口同时面向用户屏蔽了底层实现细节用户可通过配置缓存管理器来实现缓存方案的替换 我们当前以Redis作为SpringCache缓存底层实现为例展开讲解。
/*** author itheima* code 自定义redis序列化配置类*/
Configuration
public class RedisCacheConfig {/*** 配置 cacheManager 代替默认的cacheManager 缓存管理器* param factory RedisConnectionFactory* return CacheManager*/Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializerString redisSerializer new StringRedisSerializer();Jackson2JsonRedisSerializer serializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);//仅仅序列化对象的属性且属性不可为final修饰objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);serializer.setObjectMapper(objectMapper);// 配置key value序列化RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))//关闭控制存储.disableCachingNullValues()//修改前缀与key的间隔符号默认是::.computePrefixWith(cacheName-cacheName:);//设置特有的Redis配置MapString, RedisCacheConfiguration cacheConfigurations new HashMap();//定制化的Cache 设置过期时间 eg:以role开头的缓存存活时间为10scacheConfigurations.put(role,customRedisCacheConfiguration(config,Duration.ofSeconds(10)));cacheConfigurations.put(stock,customRedisCacheConfiguration(config,Duration.ofSeconds(3000)));cacheConfigurations.put(market,customRedisCacheConfiguration(config,Duration.ofSeconds(300)));//构建redis缓存管理器RedisCacheManager cacheManager RedisCacheManager.builder(factory)//Cache事务支持.transactionAware().withInitialCacheConfigurations(cacheConfigurations).cacheDefaults(config).build();//设置过期时间return cacheManager;}/*** 设置RedisConfiguration配置* param config* param ttl* return*/public RedisCacheConfiguration customRedisCacheConfiguration(RedisCacheConfiguration config, Duration ttl) {//设置缓存缺省超时时间return config.entryTtl(ttl);}
}2.3 SpringCache注解详解
2.3.1 Cacheable注解
如果缓存中没有查询数据库存储缓存返回结果
如果缓存中有直接返回结果
作用可以用来进行缓存的写入将结果存储在缓存中以便于在后续调用的时候可以直接返回缓存中的值而不必再执行实际的方法。 最简单的使用方式,注解名称缓存名称,使用例子如下: 示例代码
Service
CacheConfig(cacheNames role)//提取缓存的前缀配置
public class RoleServiceImpl implements IRoleService {Autowiredprivate RoleMapper roleMapper;/*** p* 几个属性* a)cacheNames/value指定缓存组件的名字* cacheNames {role}可以使用多个参数,是数组的形式可以指定多个缓存* b)key缓存数据使用的key可以用他来指定。默认是使用方法参数的值* 编写SpEl: #id #a0,#po,#argrs[0] 0代表参数的索引* #result 方法执行后的返回值* #root.methodName 方法名* key #root.methodName[#id]* e)condition指定符合缓存的条件* condition #id0 and #root.methodName eq aaa 可以多条件判断* f)unless: 否定缓存当unless的条件为true方法结果不会被缓存,可以获取结果进行判断* unless #resultnull结果为null就不缓存*/Override//Cacheable(cacheNames role, key #id,condition #id0,unless #resultnull)Cacheable(key #id,condition #id0,unless #resultnull)public Role findById(Integer id) {return roleMapper.selectByPrimaryKey(id);}Cacheable(key #root.method.getName())//直接引用mehtodname异常Overridepublic R findAllRole() {ListRole roleList roleMapper.findAll();return R.ok(roleList);}
}2.3.2 CacheEvict注解
CacheEvict删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntriestrue时可以对整个条目进行批量删除 示例代码 /*** .CacheEvict 缓存清除* key指定要清除的数据*/OverrideCacheEvict(key #id)public Integer delete(Integer id) {return roleMapper.deleteByPrimaryKey(id);}2.3.3 CachePut注解
CachePut当需要更新缓存而不干扰方法的运行时 可以使用该注解。也就是说始终执行该方法并将结果放入缓存
本质上说如果存在对应的缓存则更新覆盖不存在则添加 示例代码
/*** .CachePut既调用方法、又更新数据达到同步更新缓存* p* 运行时机* 1、先调用目标方法 ★★★* 2、将目标方法的结果缓存起来★★★* 条件存取Id的key要保持一致* key #role.id 传入员工的Id* key #result.id 使用返回员工的Id* 注意 Cacheable不能使用#result* 因为 Cacheable在目标方法执行之前需要得到这个key所以不能用#result*/
Override
CachePut(key #result.id)//更新或者添加缓存---》有则更新无则添加
public Role update(Role role) {roleMapper.updateByPrimaryKey(role);return role;
}2.3.4 Caching注释
在使用缓存的时候有可能会同时进行更新和删除会出现同时使用多个注解的情况.而Caching可以实现对于复杂的缓存策略我们可借助SpEL实现
Spring Cache提供了一些供我们使用的SpEL上下文数据下表直接摘自Spring官方文档 其它如果表达式想直接引用一个常量值那么需要 key“‘xxxx’”
示例代码 /*** .Caching 定义复杂缓存规则*/OverrideCaching(cacheable {Cacheable(key #role.rolename)},put {CachePut(key #role.id),CachePut(key #role.rolecode)},evict {CacheEvict(key 8)})public R add(Role role) {
// role.setId(null);try {roleMapper.insert(role);} catch (Exception e) {return R.error();}return R.ok(role.getId());}2.3.5 注解小结
对于缓存声明spring的缓存提供了一组java注解:
Cacheable 功能触发缓存写入如果缓存中没有查询数据库存储缓存返回结果如果缓存中有直接返回结果应用查询数据库方法且查询的数据时热点数据 CacheEvict 功能触发缓存清除应用删除或修改数据库方法 CachePut 功能缓存写入(不会影响到方法的运行)。有则更新无则添加应用新增到数据库方法 Caching 功能重新组合要应用于方法的多个缓存操作应用上面的注解的组合使用 CacheConfig(cacheNames “xxx”) 功能可以提取公共的缓存key的前缀一般是业务的前缀应用作用在类之上