springBoot+Redis
1. 启动类
/**
* 一. 快速体验注解
* 步骤:
* 1. 开启基于注解的缓存@EnableCacheing
* 2. 标注缓存注解即可
* @Cacheable 方法执行后结果放进缓存
* @CaCheEvict 方法执行删除数据后,同时删除缓存中的数据
* @CachePut 方法执行添加数据后,同时将数据放进缓存中
* 默认使用ConcurrentMapCacheManager缓存管理器;将数据保存在ConcurrentMap<Object,Object>中
* 开发中使用的缓存技术有:redis,memcache,ehcache
* 二. 整合redis作为缓存
* 1. 安装redis
* 2. 引入spring-boot-starter-data-redis
* 3. 配置redis
* 4. 测试
* 1. 当引入redis starter后,容器中会创建RedisCacheManager换存管理器
* 2. 如果创建RedisCacheManager,ConcurrentMapCacheManager缓存管理器不会再创建
* 3. 然后RedisCacheManager,创建RedisCache缓存管理组件
* 4. RedisCache组件操作Redis缓存数据
* 5.
*
*/
@SpringBootApplication
@MapperScan("cn.liyang.springredis.mapper")
@EnableCaching
public class SpringRedisApplication {
public static void main (String[] args) {
SpringApplication.run( SpringRedisApplication.class, args );
}
}
2. 配置文件
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/company
driver-class-name: com.mysql.jdbc.Driver
type: org.springframework.jdbc.datasource.DriverManagerDataSource
redis:
host: 127.0.0.1
port: 6379
mybatis:
#全局配置文件
config-location: classpath:mybatis/mybatis-config.xml
#mapper配置文件
mapper-locations: classpath:mybatis/mapper/*.xml
#设置mapper包的日志等级 debug
#logging:
# level:
# cn.liyang.springredis.mapper: debug
#debug: true
3. serviceImpl.java
package cn.liyang.springredis.service.impl;
import cn.liyang.springredis.mapper.EmployeeMapper;
import cn.liyang.springredis.pojo.Employee;
import cn.liyang.springredis.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author liyang
* @date 2019/9/6 15:21
* @description:
*/
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
/**
* 将方法的运行结果进行缓存;以后再取相同的数据,直接从缓存中取,不用再掉方法;
* CacheManager 缓存管理器,来管理缓存,缓存数据crud还是再Cache中进行,每个缓存有自己唯一的名字;
* Cache的几个属性:
* 1. cacheNames="" : 指定缓存的名字,可以指定多个缓存测名字,将值缓存在多个缓存中
* 2. key="" : 缓存数据指定的key,默认用参数名字 多个参数可以用 #root.args[0]/#p0 来指定哪一个
* key/keyGenerator:两个属性二选一
* key的默认生成策略是:SimpleKeyGenerator生成;
* 如果没有参数: key = new SimpleKey();
* 如果有一个参数: key = 参数的值;
* 如果有多个参数: key = new SimpleKey(params);
* 3. cacheManager="" : 指定缓存管理器
* 4. condition="" : 指定缓存的条件,比如id>3才会缓存
* 5. unless="" : 当unless的条件为true时,不会执行缓存,unless = "#result == null "(当方法结果为null不缓存)
*原理:
* 1. 自动配置类;CacheAutoConfiguration
* 2. 缓存的配置类有9个
* 3. 默认生效配置类:SimpleCacheConfiguration
* 当配置了:spring-boot-starter-data-redis后生效配置类是RedisCacheConfiguration
* 4. 给容器注册一个缓存管理器CacheManager: ConcurrentMapCacheManager;
* 5. 可以获取和创建ConcurrentMapCache类型的缓存组件;该组件的作用将数据保存在ConcurrentMap容器中;
* 1. 能根据缓存对象的名字获得缓存对象,这个键值对,存放在ConcurrentMap集合中
* 2. 如果名字不存在,就会创建一个
* 运行流程:
* 1. 业务方法运行之前,先获取方法上cacheNames的缓存对象的名字,先去查询Cache是否存在,
* 第一次没有cache,缓存管理器CacheManager会先创建一个缓存对象;
* 2. 取缓存cache中,根据key(默认方法参数名)获得数据;
* 3. 如果没有查到缓存就调用目标方法
* 4. 将目标方法结果放进缓存中 put进concurrentMap<K 方法参数,V 方法的返回值(这里的emp对象)>
*核心:
* 1. 使用CacheManager(如果没有配置默认:ConcurrentMapCacheManager)按照名字获得Cache(ConcurrentMapCache)组件
* 2. key使用keyGenerator生成的,默认使用SimpleKeyGenerator
* @param id
* @return
*/
@Override
@Cacheable(cacheNames = "emp",key = "#p0"/*keyGenerator = "myKeyGenerator",condition = "#root.args[0]>3"*/,unless = "#result == null ")
public Employee findById (Long id) {
System.out.println("根据"+id+"查询一个员工");
return employeeMapper.findById( id );
}
@Override
public List<Employee> findAll () {
System.out.println("查询所有employee");
return employeeMapper.findAll();
}
/**
* @CachePut注解的作用: 更新数据库,同步更新缓存
* 1. 即调用目标方法,又把结果放进cache缓存里
* 2. 放进缓存里的key要与,查询该对象的key一样
* 3. 放与取的key一样这样更新后放入缓存里的数据才能,覆盖掉原先该key的值(跟新与查询用的key一定要一样)
* 4. 覆盖掉原先内存里的值,才能保证从缓存里查出的结果准确性
*
* @param employee
* @return
*/
@Override
@CachePut(cacheNames = "emp",key = "#employee.id"/*key = "#result.id"*/)
public Employee update (Employee employee) {
employeeMapper.update( employee );
return employee;
}
/**
* @CacheEvict注解:
* 1. 删除数据库数据的同时,根据设置的缓存key,删除对应缓存中的值
* 2. 保证数据库删除后,从缓存中也是被删除的,保证查询的准确性
* beforeInvocation = true: 该属性设置是否在执行方法之前清除缓存
* true:当执行方法出错时,缓存已经查不到删除的对象了
* false: 当方法出错时,还能从缓存中查询出要删除的对象
* allEntries = true:作用
* 当执行这个目标方法时会删除掉所有缓存
* @param id
* @return
*/
@Override
@CacheEvict(cacheNames = "emp"/*,key = "#id"*/,beforeInvocation = true/*allEntries = true*/)
public int delete (Long id) {
System.out.println("删除id="+id+"的员工");
//int affectRows = employeeMapper.delete( id );
return 1;
}
}
总结:
通用cache配置及注解完成后,安装redis,引入spring-boot-starter-data-redis依赖
1. 当引入redis starter后,容器中会创建RedisCacheManager换存管理器
-
2. 如果创建RedisCacheManager,ConcurrentMapCacheManager缓存管理器不会再创建
-
3. 然后RedisCacheManager,创建RedisCache缓存管理组件
-
4. RedisCache组件操作Redis缓存数据