缓存的作用
1)加速系统的访问,以及提升系统性能; 比如:
如果商品信息存在数据库中;
每次访问都要查询数据库,耗时;并且访问量大时,系统压力大;
可以将这类热点数据存入缓存;
当访问数据时,先从缓存中找,如果缓存中没有,就从数据库找到并放入缓存方便下次查找;
使用缓存可以提升性能,因为应用程序和缓存的交互相对较快;
2)保存临时数据 比如:
手机验证之类的临时信息,通常需要在几分钟之内删除;
如果存入数据库,不划算,影响系统性能;
可以将这类数据存入缓存;
Java Caching
- 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设置。
缓存应用流程
- 通过缓存提供者CachingProvider得到缓存管理器CacheManager;
- 缓存提供者可以管理多个缓存管理器;
- 每个缓存管理器管理特定类型的缓存;比如:CacheManager1管理redis缓存、CacheManager2管理memcache缓存;
- 缓存管理器用来管理缓存Cache;
- 一个缓存管理器管理多个缓存;比如:Cache1用来保存员工数据、Cache2用来缓存部门数据;
- 缓存中保存多条数据,每一条数据是一个键值对;
- Cache接口中提供了一些api,用来对数据进行增删改查操作;
spring缓存抽象
Spring也定义了类似JSR-107类似的缓存抽象和缓存注解;
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;
spirng缓存抽象的核心概念和注解:
- CacheManager 缓存管理器,可以指定多种缓存管理器,例如:redis、memcache、concurrentHashMap等等;
- Cache 缓存,一个缓存管理器可以管理多个缓存,缓存中以键值对存放数据;比如:Cache-1专门用来存放员工信息,Cache-2用来存放部门信息等待;
- @Cacheable 标记查询方法,将查询的结果放入缓存;查询时缓存中有数据就不查数据库了;
- @CacheEvit 标记删除方法,会在数据库中删除的同时也清除缓存;
- @CachePut 标记修改方法,会将修改后的数据也更新在缓存上;与@Cacheable不同的是该注解标记的方法即使缓存中有数据也会去查数据库;
注解参数:
注解参数中用到的el表达式:
使用spring缓存
1、配置application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql://localhost:3306/data?characterEncoding=utf8&useSSL=false
spring.datasource.username= root
spring.datasource.password= root
logging.level.top.cquke.springbootcache.mapper= debug
2、在启动配类上配置 启用缓存
@SpringBootApplication
@EnableCaching
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
3、创建实体类
@Data
@TableName("goods")
public class Goods {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private BigDecimal price;
private String commonName;
private String approvalCertificate;
private String productionEnterprise;
private String specifications;
private String url;
private String imgs;
private Integer fenlei3Id;
}
4、创建mapper
@Mapper
public interface GoodsMapper extends BaseMapper<Goods> {
}
5、使用缓存
@RestController
public class CacheDemoController {
@Autowired
private GoodsMapper goodsMapper;
@GetMapping("/getGoodsById")
@Cacheable(value = "goods", key = "#id")
public Object getGoodsById(Integer id) {
QueryWrapper<Goods> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(Goods::getId, id);
return goodsMapper.selectList(wrapper);
}
@GetMapping("/saveGoods")
@CachePut(value = "goods", key = "#goods.id")
public Object saveGoods(Goods goods){
goodsMapper.insert(goods);
return goods;
}
@GetMapping("/updateGoods")
@CachePut(value = "goods", key = "#goods.id")
public Object updateGoods(Goods goods){
goodsMapper.updateById(goods);
return goods;
}
@GetMapping("/deleteGoods")
@CacheEvict(value = "goods", key = "#id")
public Object deleteGoods(Integer id){
goodsMapper.deleteById(id);
return "删除成功";
}
}
结果如下:
初次添加一条数据:
清除日志后,获取该数据
可以看到并没有走数据库获取,而是获取的缓存中的数据。
更新数据
之后同样是没有走数据库
删除一条数据
我们再去获取数据,因为已经删除数据,且缓存数据已经被删除,因此会去数据库查询