spring-boot -缓存注解
缓存:商品信息放到缓存中间件中,
验证码几秒钟有效也是放在缓存中间件。
缓存规范

交互流程:

如果需要使用jRS107需要导入包:
java.cache.cache-api
JSR107提供的是接口,如果需要用那些缓存的组件,就需要加入对应的实现,
如果没有对应的实现的话,是需要自己写的。
spring里面提供了缓存抽象,




CacheAutoConfiguration 加入的自动配置类

默认加入SimpleCacheConfiguration
@Configuration( proxyBeanMethods = false ) @ConditionalOnMissingBean({CacheManager.class}) @Conditional({CacheCondition.class}) class SimpleCacheConfiguration { SimpleCacheConfiguration() { } @Bean ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(); List<String> cacheNames = cacheProperties.getCacheNames(); if (!cacheNames.isEmpty()) { cacheManager.setCacheNames(cacheNames); } return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager); } }
使用缓存注解的前提是:
配置文件:
spring.datasource.url=jdbc:mysql://192.168.1.102:3306/mybatis spring.datasource.username=root spring.datasource.password=1997 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #开启驼峰命名 mybatis.configuration.map-underscore-to-camel-case=true logging.level.root=debug
开启debug模式可以查看更加细节的日志
加入依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
创建数据库表:
CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `lastName` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `gender` int(2) DEFAULT NULL, `d_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
实体类:
public class Employee { private Integer id; private String lastName; private Integer gender; private String email; private Integer dId; public Employee() { super(); } public Employee(Integer id, String lastName, Integer gender, String email, Integer dId) { super(); this.id = id; this.lastName = lastName; this.gender = gender; this.email = email; this.dId = dId; } public void setId(Integer id) { this.id = id; } public void setLastName(String lastName) { this.lastName = lastName; } public void setGender(Integer gender) { this.gender = gender; } public void setEmail(String email) { this.email = email; } public void setdId(Integer dId) { this.dId = dId; } public Integer getId() { return id; } public String getLastName() { return lastName; } public Integer getGender() { return gender; } public String getEmail() { return email; } public Integer getdId() { return dId; } @Override public String toString() { return "Employee{" + "id=" + id + ", lastName='" + lastName + '\'' + ", gender=" + gender + ", email='" + email + '\'' + ", dId=" + dId + '}'; } }
mapper接口
@Mapper public interface EmployeeMapper { @Select("select * from employee where id = #{id}") public Employee getEmpById(Integer id); @Update("update employee set lastName =#{lastName},email=#{email},gender=#{gender},d_id=#{dId}") public void updateEmp(Employee employee); @Delete("delete from employee where id =#{id}") public void deleteEmpById(Integer id); @Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{dId})") public void insertEmp(Employee employee); @Select("select * from employee where lastName = #{lastname}") Employee getEmpByLastName(String lastname); }
controller层:
@RestController public class EmplloyeeController { @Autowired EmployeeService employeeService; @RequestMapping("/emp/{id}") public Employee getEmployee(@PathVariable("id") Integer id){ return employeeService.getEmp(id); } @RequestMapping("/emp") public Employee update(Employee employee){ Employee employee1 =employeeService.updateEmp(employee); return employee1; } @RequestMapping("/delemp") public String deleteEMp(Integer id){ employeeService.deleteEmp(id); return "success"; } }
在服务层我们使用缓存注解:
先开启缓存注解@EnableCaching,,在启动类中
@Cacheable
@Cacheable(cacheNames = "emp",keyGenerator = "myKeyGenerator") public Employee getEmp(Integer id){ System.out.println("chanxun"+id+"员工"); Employee emp = employeeMapper.getEmpById(id); return emp; }
@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存
如果有就不需要执行函数
如果没有就执行函数
*/
@Cacheable运行流程:
运行的流程: 1方法运行之前,先去查询Cache组件,安装cacheNames指定的名字获取 (CacheManager先获取相应的缓存)第一次获取缓存,回自动创建出来,以后就能用了 2去Cache中查找缓存的内容弄给,使用一个key,默认是方法的参数 key是按照某个规则生成的,默认是keyGenerator生成,默认使用simplekeyGenerator simplekeyGenerator策略: 如果没有参数,key= new SimpleKey 如果一个:使用它 如果多个,SimpleKey(params) 3 没有查到缓存就调用目标方法 4将目标方法返回的结果,放进缓存中
@Cacheable的属性和作用:
/** * 将方法的允许结果进行缓存,以后如果要相同的数据,直接从缓存中获取,不用调用方法 *CacheManager 管理多个Cache组件,对缓存的真正CRUD操作是在Cache组件中, * 每一个缓存组件有自己的唯一名字 * 几个属性: * cacheNames/value:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,数组,可自定多个缓存 * key:缓存数据使用的key,可以用它来指定,默认是使用方法参数的值 1 * 可以使用SpEl格式 * keyGenerator:key的生成器,可以自己指定key的生成器组件id * key和keyGenerator二选一,!!可以自己指定 * CacheManager:指定缓存管理器 * condition,指定符合条件的情况菜缓存 condiction ="#id>0"id的值大于0才缓存 * unless :否定缓存,当unless指定的条件为true,返回值不会被缓存,可以获取到结果进行判断 * unless = ”#result == null“如果结果为null 不缓存 * sync:是否使用异步模式
@CachePut:
/** * @CachePut 既调用方法,又跟新缓存数据 * 场景:修改数据库的某个数据,同时跟新缓存 * 运行实际:1先调用目标方法 * 2将目标方法的结果缓存起来 测试: 1查询1好员工,,查到的结果回放到缓存当中 存储方式:key:1 value:员工信息 2以后查询还是之前的结果 3更新1号员工http://localhost:8080/emp?id=1&lastName=quanzhiqiang&gender=2 存储方式:key:传入的对象emloyee,value: 返回的employee对象 4查询1号员工?? 理论上查询的应该是更新后的员工信息 但是结果是之前的信息,原因可以看看上面的缓存存储的两种方式就知道了 解决方法, @CachePut(value = "emp" ,key = "#employee.id"),指定修改的key */

改进后:
@CachePut(value = "emp" ,key = "#result.id") public Employee updateEmp(Employee employee){ System.out.println("updateEmp"+employee); employeeMapper.updateEmp(employee); return employee; } }
//注意:你取缓存的key和我们更新缓存的key应该一致
@CacheEvict
/** * @CacheEvict 缓存请除 * key:通过key来指定清楚的数据 * allEntries = true:指定清除这个缓存中的所有的数据 * beforeInvocation = false:缓存的清楚是否在方法之前执行 * 默认代表方法执行之后执行,出现异常缓存不会清除。 */
@CacheEvict(value = "emp",key = "#id") public void deleteEmp(Integer id){ System.out.println("deleteEmp:"+id); employeeMapper.deleteEmpById(id); }
@Caching:
可以同时定义多个缓存注解:
@Caching( cacheable = { @Cacheable(value = "emp",key = "#lastname") }, put = { @CachePut(value = "emp",key = "#result.id"), @CachePut(value = "emp",key = "#result.lastName") } ) public Employee getEmpByLastName(String lastname){ return employeeMapper.getEmpByLastName(lastname); } }
@CacheConfig
/* 因为每个缓存注解都要写value =”emp" 所以我们可以通过@CacheConfig注解统一设置 */ @CacheConfig(cacheNames = "emp") 加在类上就可以了,里面的方法的缓存注解都不需要指定缓存组件名i在


浙公网安备 33010602011771号