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在

 

 

 

posted @ 2020-08-16 20:22  小丑quan  阅读(830)  评论(0)    收藏  举报