本章给大家带来的是SpringBoot和缓存的学习。同时已经录制了非常详细的视频,如果看文档较为吃力,可以结合视频进行学习,帮你快速掌握SringBoot与缓存。
一、JSR107
Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。
•
CachingProvider
定义了创建、配置、获取、管理和控制多个
CacheManager
。一个应用可以在运行期访问多个
CachingProvider
。
•
CacheManager
定义了创建、配置、获取、管理和控制多个唯一命名的
Cache
,这些
Cache
存在于
CacheManager
的上下文中。一个
CacheManager
仅被一个
CachingProvider
所拥有。
•
Cache
是一个类似
Map
的数据结构并临时存储以
Key
为索引的值。一个
Cache
仅被一个
CacheManager
所拥有。
•
Entry
是一个存储在
Cache
中的
key-value
对。
•
Expiry
每一个存储在
Cache
中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过
ExpiryPolicy
设置。
二、Spring缓存抽象
Spring从3.1开始定义了org.springframework.cache.Cache
和org.springframework.cache.CacheManager接口来统一不同的缓存技术;
并支持使用JCache(JSR-107)注解简化我们的开发;
•
Cache
接口为缓存的组件规范定义,包含缓存的各种操作集合;
•
Cache
接口下
Spring
提供了各种
xxxCache
的实现;如
RedisCache
,
EhCacheCache , ConcurrentMapCache
等;
•
每次调用需要缓存功能的方法时,
Spring
会检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
•
使用
Spring
缓存抽象时我们需要关注以下两点;
1、确定方法需要被缓存以及它们的缓存策略
2、从缓存中读取之前缓存存储的数据
三、几个重要概念&缓存注解
四、缓存使用
•
1
、引入
spring-boot-starter-cache
模块
•
2
、
@
EnableCaching
开启缓存
•
3
、使用缓存注解
•
4
、切换为其他缓存
测试缓存对象:
五、整合redis实现缓存
1.
引入
spring-boot-starter-data-
redis
、
spring-data-
redis
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
3. 使用ReditTemplate操作redis
1.
redisTemplate.opsForValue
();//
操作字符串
2.
redisTemplate.opsForHash
();//
操作
hash
3.
redisTemplate.opsForList
();//
操作
list
4.
redisTemplate.opsForSet
();//
操作
set
5.
redisTemplate.opsForZSet
();//
操作有序
set
redisconfig实现:
@Configuration
public class RedisConfig {
//过期时间
private Duration timeToLive = Duration.ofDays(1);
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
.disableCachingNullValues();
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(configuration).transactionAware().build();
return redisCacheManager;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(keySerializer());
template.setHashKeySerializer(keySerializer());
template.setValueSerializer(valueSerializer());
template.setHashValueSerializer(valueSerializer());
return template;
}
private RedisSerializer<String> keySerializer(){
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer(){
return new GenericJackson2JsonRedisSerializer();
}
}
application.properties的配置:
spring.datasource.username=spring
spring.datasource.password=spring
#开启驼峰命名匹配规则
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.com.dahaiwuliang.cache.mapper=debug
#redis连接
spring.redis.host=192.168.0.108
六、整合一个实例
* Cacheable的运行流程
* 1、在方法运行之前,先去缓存按value查找Cache,第一次获取不到就会创建
* 2、去Cache中查找Entry,使用一个key,默认用方法的参数
* key是按某种规则创建的,默认是使用的SimpleKeyGenerator生成
* SimpleKeyGenerator的生成策略:
* 如果没有参数,key=new SimpleKey();
* 如果有一个参数,key=参数的值
* 如果有多个参数:key=new SimpleKey(params);
*
* 3、如果查到,直接返回;没有查到就调用目标方法
* 4、将目标方法返回的结果放到缓存里面
*
* cacheNames/value:
* 指定缓存组件(Cache)的名字,将方法的返回结果放到哪个缓存中,是数组的方式,可以指定多个缓存
*
* key:
* Entry里面的key,默认是使用的SimpleKeyGenerator生成;
* 也可以写SpEL表达式来生成 #a0 #p0 #root.args[0] #id
* keyGenerator:key的生成器,可以自定义一个
*
* cacheManager:指定缓存管理器
*
* condition:指定符合条件的情况下才缓存
*
* unless:否定缓存,和condition正好相反
*
* sync:是否使用异步模式
controller层:
@RestController
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@GetMapping("/getEmployee")
public Employee getEmployee(Integer id){
Employee employee = employeeService.getEmp(id);
return employee;
}
@GetMapping("/updateEmployee")
public Employee update(Employee employee){
Employee emp = employeeService.updateEmp(employee);
return emp;
}
@GetMapping("/deleteEmployee")
public String deleteEmp(Integer id){
employeeService.deleteEmp(id);
return "success";
}
@GetMapping("/emp/{lastName}")
public Employee getEmployeeByLastName(@PathVariable("lastName") String lastName){
return employeeService.getEmployeeByLastName(lastName);
}
}
service层:
public Employee getEmp(Integer id){
System.out.println("查询"+id+"员工");
Employee employee = employeeMapper.getEmpById(id);
Cache cache = cacheManager.getCache("emp");
cache.put("emp:"+id,employee);
return employee;
}
/**
* @CachePut:既调用方法,又更新缓存
* 修改了数据库的数据,并同时更新缓存
* 运行机制:
* 1、先调用目标方法;
* 2、将目标方法的结果缓存起来
*/
@CachePut(/*value = "emp",*/key="#result.id")
public Employee updateEmp(Employee employee){
System.out.println("update:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
/**
* @CacheEvict:清除缓存
* allEntries=true清空这个缓存中的所有数据
* beforeInvocation=true代表清空缓存操作是在方法执行前就执行了,无论方法是否出现异常,缓存都会被清除
*/
@CacheEvict(/*value = "emp",*/key = "#id"/*,allEntries = true*/,beforeInvocation = true)
public void deleteEmp(Integer id){
System.out.println("deletEmp:"+id);
//employeeMapper.deleteEmpById(id);
int a = 10/0;
}
/**
* @Caching 定义复杂的缓存规则
*/
@Caching(
cacheable = {
@Cacheable(/*value = "emp",*/key = "#lastName")
},
put = {
@CachePut(/*value = "emp",*/key = "#result.id")
}
)
public Employee getEmployeeByLastName(String lastName){
System.out.println("getEmployeeByLastName:"+lastName);
return employeeMapper.getEmpByLastName(lastName);
}
}
好了,讲解结束,小伙伴们点赞、收藏、评论,一键三连走起呀,下期见~~