第一步:配置redis
redis:
host: 127.0.0.1
port: 6379
password: uxsino@2016
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:postgresql://localhost:5432/simo_3_0_4
username: uxsino
password: Uxs!nO10
driverClassName: org.postgresql.Driver
jpa:
database: DEFAULT
show-sql: false
generate-ddl: true
hibernate:
naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
database-platform: com.uxsino.uxdb.JSONBPostgreSQLDialect
第二部:在启动类上添加 @EnableCaching注解
@SpringBootApplication(scanBasePackages = {"com.miaoshaproject"}) @MapperScan("com.miaoshaproject.dao") @EnableCaching public class App { public static void main( String[] args ) { ConfigurableApplicationContext run = SpringApplication.run(App.class, args); } }
第三步 : 在需要缓存的方法上添加@Cacheable注解
@Service @CacheConfig(cacheNames = {"itemService"}) public class ItemServiceImpl implements ItemService { @Override @Cacheable(value = {"item"},key ="#p0") public String getItemById(Integer id) { String name = "123"; return name; } }
第四步:说明Springboot缓存说明:
使用Springboot 缓存必须配置名字@CacheConfig(cacheNames={"itemService"}) 在类上配置该类公共的名字。也可以使用Cacheable(value="item")在方法上配置用于该方法的名字。
如果类上和方法上都有配置,以方法配置为准springboot会自动拼装缓存名,规则是:配置的名字+两个:+方法的实参。
@Cacheable(value="item") 这个注解的意思是,当调用这个方法时候,会从一个叫item的缓存中查询,如果没有,则执行实际的方法,也就是查询数据库,
@Cacheable
@Cacheable 当标记在类上,类中所有的方法都缓存
@Accheable 当标记在方法上是表示该方法时支持缓存的。对于一个缓存方法springboot 会在调用该方法后将器缓存。以保证下次童颜给的参数来执行该方法时可以从缓存中直接获取结果。而不在需要再次执行该方法。
@GetMapping("/info")
@Cacheable(cacheNames = "product", key = "123")
public ResultVO findOne(@Param("productId") String productId) {
log.info("Get from database ...");
// 从数据库获取数据, ProductInfo必须实现Serializable
ProductInfo productInfo = productService.findOne(productId);
return ResultVOUtil.success(productInfo);
}
CacheNames 缓存名称不能为空。
key可以为空
key可以收纳柜spEL表达式进行编写
@GetMapping("/info")
@Cacheable(cacheNames = "product", key = "#productId")
public ResultVO findOne(@Param("productId") String productId) {
log.info("Get from database ...");
ProductInfo productInfo = productService.findOne(productId);
return ResultVOUtil.success(productInfo);
}
这里的productid 如果缓存过才会从数据库中取,如果没有缓存过,会从数据库中取。
condition:缓存条件,可以为空,
@GetMapping("/info")
@Cacheable(cacheNames = "product", key = "#productId", condition="#productId >= 3 ")
public ResultVO findOne(@Param("productId") Integer productId) {
log.info("Get from database ... " + productId);
ProductInfo productInfo = productService.findOne(String.valueOf(productId));
return ResultVOUtil.success(productInfo);
}
这里设置了condition="productid">3 才会进行缓存
@CachePut
如果缓存需要更新,则可以使用@CachePut
@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
@PostMapping("/update")
@CachePut(cacheNames = "product", key = "#productForm.productId")
public ResultVO update(@RequestBody ProductForm productForm) {
ProductInfo productInfo = new ProductInfo();
BeanUtils.copyProperties(productForm, productInfo);
productService.save(productInfo);
return ResultVOUtil.success(productInfo);
}
这里先将数据存入数据库,然后还又对缓存中的内容进行更新操作。
@CacheEvict
@CacheEvict要求指定一个或多个缓存,使之都受影响。此外,还提供了一个额外的参数allEntries 。表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,将忽略指定的key。有的时候我们需要Cache一下清除所有的元素。
@CacheConfig
@CacheConfig是一个类级别的注解,允许共享缓存的名称(CacheName)、KeyGenerator、CacheManager 和CacheResolver。
什么时候使用缓存:
缓存不是架构设计的必选项,也不是开发中的必要功能点。只有在业务出现瓶颈才考虑用缓存来提升系统性能。也不是所有的场景都适合使用缓存。读多写少,时效性要求低的场景才用缓存。缓存加大了系统的维护成本。只有对缓存边界有一个深刻的认识,才可以更好的使用缓存。
图片,视频使用分布式,而不是缓存
高并发,大流量的业务引入缓存收益会更高
每一种缓存都有优缺点,以及使用的范围,内存效率,运维成本,甚至团队开发人员知识结构的了解,才能做好技术选型。
缓存需要考虑,缓存命中率。内存空间。value大小。读写策略,key值路由分配策略。
缓存的设计原则 将缓存数据放在力用户最近的地方。这就是多级缓存设计的核心思想。