(十九)Spring Boot 缓存【Redis 单机缓存】

      和Ehcache 一样,如果在 classpath 下存在 Redis 并且 Redis 己经配置好了,此时默认就会使用RedisCacheManager 作为缓存提供者。 Redis 单机使用步骤如下。

  1. 创建项目,添加缓存依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  1. 缓存配置
spring:
  cache:
    # redis 中的 key 都有一个前缀,默认前缀就是"缓存名::"
    cache-names: c1,c2
    redis:
      # 缓存有效期,redis 的 key 过期时间
      time-to-live: 1800s
  redis:
    database: 0 # Redis数据库索引(默认为0)
    host: localhost  #Redis服务器地址
    port: 6379 # Redis服务器连接端口
    password: # Redis服务器连接密码(默认为空)
    jedis:
      pool:
        max-active: 200 # 连接池最大连接数(使用负值表示没有限制)
        max-idle: 10 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
  1. 开启缓存
@SpringBootApplication
@EnableCaching
public class RedisCacheStandaloneApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisCacheStandaloneApplication.class, args);
    }
}
  1. 创建 实体类、BookDao
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String author;
	//省略get/set方法
}
@Repository
//指明使用的缓存的名字 这个配直可选,若不使用 @CacheConfig 注解,则直接在 @Cacheable 注解中指明缓存名字
@CacheConfig(cacheNames = {"book_cache" })
public class BookDao {

    @Cacheable
    public Book getBookById(Integer id) {
        System.out.println("getBookById");
        Book book = new Book();
        book.setId(id);
        book.setName("三国演义");
        book.setAuthor("罗贯中");
        return book;
    }

    @CachePut(key = "#book.id")
    public Book updateBookById(Book book) {
        System.out.println("updateBookById");
        book.setName("三国演义2");
        return book;
    }

    @CacheEvict(key = "#id")
    public void deleteBookById(Integer id) {
        System.out.println("deleteBookById");
    }
}
  • @Cacheable:表示对该方法进行缓存,默认情况 ,缓存的 key 是方法的参数,缓存的 value 是方法的返回值当开发者在其他类中调用该方法时,首先会根据调用参数查看缓存中是否有相关数据,若有,则直接使用缓存数据,该方法不会执行,否则执行该方法,执行成功后将返回值缓存起来,但若是在当前类中调用该方法,则缓存不会生效。
  • @Cacheable 注解中还有一个属性 condition 用来描述缓存的执行时机,例如
    @Cacheable(condition ="#id%2=0") 表示当 id 对2 取模为 0 时才进行缓存,否则不缓存。
  • 如果开发者不想使用默认的 key ,也可以像 @CachePut(key = "#book.id")@CacheEvict(key = "#id")一样自定义 key ,@CachePut(key = "#book.id")表示存的 key 为参数 book 对象中 id 的值,@CacheEvict(key = "#id")表示缓存 key 为参数 id。除了这种使用参数定义 key 的方式之外,Spring 还提供了 root 对象用来生成 key ,如表所示:
    在这里插入图片描述
  • 如果这些 key 不能够满足开发需求, 开发者也可以自定义缓存 key 的生成器 KeyGenerator。
@Component
public class MyKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object o, Method method, Object... objects) {
        return Arrays.toString(objects);
    }
}
@Repository
//指明使用的缓存的名字 这个配直可选,若不使用 @CacheConfig 注解,则直接在 @Cacheable 注解中指明缓存名字
@CacheConfig(cacheNames = {"book_cache" })
public class BookDao {

    @Autowired
    MyKeyGenerator myKeyGenerator;

    @Cacheable(keyGenerator = "myKeyGenerator")
    public Book getBookById(Integer id) {
        System.out.println("getBookById");
        Book book = new Book();
        book.setId(id);
        book.setName("三国演义");
        book.setAuthor("罗贯中");
        return book;
    }
}

自定义 MyKeyGenerator 实现 KeyGenerator 接口,然后实现该接口中的 generate 方法,该方法的三个参数分别是当前对象、当前请求的方法以及方法的参数,开发者可根据这些信息组成一个新的 key 返回,返回值就是缓存的 key ,然后在 @Cacheable 注解中引用 MyKeyGenerator 实例即可。

  • @CachePut 注解一般用于数据更新方法上,与@Cacheable 解不同,添加了@CachePut 注解的方法每次在执行时都不去检查缓存中是否有数据,而是直接执行方法,然后将方法的执行结果缓存起来,如果该 key 对应的数据已经被缓存起来了,就会覆盖之前的数据,这样可以避免再次加载数据时获取到脏数据,同时,@CachePut 具有和@Cacheable 似的属性。
  • @CacheEvict 注解一般用于删除方法上,表示移除一个key对应的缓存。@CacheEvict 注解有两个特殊的属性: allEntries 和 beforelnvocation ,其中 allEntries 表示是否将所有的缓存数据都移除, 默认为 false,beforelnvocation 表示是否在方法执行之前移除缓存中的数据,默认为 false ,即在方法执行之后移除缓存中的数据。
  1. 创建测试类
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class EhcacheApplicationTest {

    @Autowired
    BookDao bookDao;

    @Test
    public void contextLoads() {
        bookDao.getBookById(1);
        bookDao.getBookById(1);
        bookDao.deleteBookById(1);
        Book b3 = bookDao.getBookById(1);
        System.out.println("b3: " + b3);
        Book b = new Book();
        b.setName("三国演义");
        b.setAuthor("罗贯中");
        b.setId(1);
        bookDao.updateBookById(b);
        Book b4 = bookDao.getBookById(1);
        System.out.println("b4: " + b4);
    }
}

在这里插入图片描述
     一开始执行了两个查询,但是查询方法只打印了一次,因为第二次使用了缓存。接下来执行了删除方法,删除方法执行完之后再次执行查询, 询方法又被执行了,因为在删除方法中缓存己经被删除了 。再接下来执行更新方法,更新方法中不仅更新数据,也更新了缓存,所以在最后的查询方法中,查询方法的日志没打印,说明该方法没执行,而是使用了缓存中的数据,而缓存中的数据已经被更新了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值