马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、什么是缓存
企业级应用紧张作用是信息处置惩罚,当须要读取数据时,由于受限于数据库的访问服从,导致团体体系性能偏低。
为了改善上述征象,开发者通常会在应用步伐与数据库之间创建一种暂时的数据存储机制,该地区中的数据在内存中生存,读写速率较快,可以有效办理数据库访问服从低下的标题。这一块暂时存储数据的地区就是缓存。
利用缓存后,应用步伐与缓存打交道,缓存与数据库打交道,数据访问服从进步
缓存是什么?缓存是一种介于数据永世存储介质与应用步伐之间的数据暂时存储介质,利用缓存可以有效的镌汰低速数据读取过程的次数(比方磁盘IO),进步体系性能。别的缓存不光可以用于进步永世性存储介质的数据读取服从,还可以提供暂时的数据存储空间。而springboot提供了对市面上险些全部的缓存技能举行整合的方案,下面就一起开启springboot整合缓存之旅。
二、SpringBoot内置缓存办理方案
springboot技能提供有内置的缓存办理方案,可以资助开发者快速开启缓存技能,并利用缓存技能举行数据的快速操纵,比方读取缓存数据和写入数据到缓存。
步调①:导入springboot提供的缓存技能对应的starter
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-cache</artifactId>
- </dependency>
复制代码 步调②:启用缓存,在引导类上方标注注解@EnableCaching设置springboot步伐中可以利用缓存
- @SpringBootApplication
- //开启缓存功能
- @EnableCaching
- public class Springboot19CacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(Springboot19CacheApplication.class, args);
- }
- }
复制代码 步调③:设置操纵的数据是否利用缓存
- @Service
- public class BookServiceImpl implements BookService {
- @Autowired
- private BookDao bookDao;
- @Cacheable(value="cacheSpace",key="#id")
- public Book getById(Integer id) {
- return bookDao.selectById(id);
- }
- }
复制代码 在业务方法上面利用注解@Cacheable声明当火线法的返回值放入缓存中,此中要指定缓存的存储位置,以及缓存中生存当火线法返回值对应的名称。上例中value属性形貌缓存的存储位置,可以明白为是一个存储空间名,key属性形貌了缓存中生存数据的名称,利用#id读取形参中的id值作为缓存名称。
利用@Cacheable注解后,实行当前操纵,如果发现对应名称在缓存中没有数据,就正常读取数据,然后放入缓存;如果对应名称在缓存中有数据,就克制当前业务方法实行,直接返回缓存中的数据。
三、手机验证码案例(利用SpringBoot内置缓存)
为了便于下面演示各种各样的缓存技能,我们创建一个手机验证码的案例情况,模仿利用缓存生存手机验证码的过程。
手机验证码案例需求如下:
- 输入手机号获取验证码,构造文档以短信情势发送给用户(页面模仿)
- 输入手机号和验证码验证结果
为了形貌上述操纵,我们制作两个表现层接口,一个用来模仿发送短信的过程,着实就是根据用户提供的手机号天生一个验证码,然后放入缓存,另一个用来模仿验证码校验的过程,着实就是利用传入的手机号和验证码举行匹配,并返回终极匹配结果。下面直接制作本案例的模仿代码,先以上例中springboot提供的内置缓存技能来完成当前案例的制作。
步调①:导入springboot提供的缓存技能对应的starter
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-cache</artifactId>
- </dependency>
复制代码 步调②:启用缓存,在引导类上方标注注解@EnableCaching设置springboot步伐中可以利用缓存
- @SpringBootApplication
- //开启缓存功能
- @EnableCaching
- public class Springboot19CacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(Springboot19CacheApplication.class, args);
- }
- }
复制代码 步调③:界说验证码对应的实体类,封装手机号与验证码两个属性
- @Data
- public class SMSCode {
- private String tele;
- private String code;
- }
复制代码 步调④:界说验证码功能的业务层接口与实现类
- public interface SMSCodeService {
- public String sendCodeToSMS(String tele);
- public boolean checkCode(SMSCode smsCode);
- }
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
- @CachePut(value = "smsCode", key = "#tele")
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- //取出内存中的验证码与传递过来的验证码比对,如果相同,返回true
- String code = smsCode.getCode();
- String cacheCode = codeUtils.get(smsCode.getTele());
- return code.equals(cacheCode);
- }
- }
复制代码 获取验证码后,当验证码失效时必须重新获取验证码,因此在获取验证码的功能上不能利用@Cacheable注解,@Cacheable注解是缓存中没有值则放入值,缓存中有值则取值。此处的功能仅仅是天生验证码并放入缓存,并不具有从缓存中取值的功能,因此不能利用@Cacheable注解,应该利用仅具有向缓存中生存数据的功能,利用@CachePut注解即可。
对于校验验证码的功能发起放入工具类中举行。
步调⑤:界说验证码的天生计谋与根据手机号读取验证码的功能
- @Component
- public class CodeUtils {
- private String [] patch = {"000000","00000","0000","000","00","0",""};
- public String generator(String tele){
- int hash = tele.hashCode();
- int encryption = 20206666;
- long result = hash ^ encryption;
- long nowTime = System.currentTimeMillis();
- result = result ^ nowTime;
- long code = result % 1000000;
- code = code < 0 ? -code : code;
- String codeStr = code + "";
- int len = codeStr.length();
- return patch[len] + codeStr;
- }
- @Cacheable(value = "smsCode",key="#tele")
- public String get(String tele){
- return null;
- }
- }
复制代码 步调⑥:界说验证码功能的web层接口,一个方法用于提供手机号获取验证码,一个方法用于提供手机号和验证码举行校验
- @RestController
- @RequestMapping("/sms")
- public class SMSCodeController {
- @Autowired
- private SMSCodeService smsCodeService;
-
- @GetMapping
- public String getCode(String tele){
- String code = smsCodeService.sendCodeToSMS(tele);
- return code;
- }
-
- @PostMapping
- public boolean checkCode(SMSCode smsCode){
- return smsCodeService.checkCode(smsCode);
- }
- }
复制代码
四、SpringBoot整合Ehcache缓存
手机验证码的案例已经完成了,下面就开始springboot整合各种各样的缓存技能,第一个整合Ehcache技能。Ehcache是一种缓存技能,利用springboot整合Ehcache着实就是变动一下缓存技能的实现方式,话不多说,直接开整
步调①:导入Ehcache的坐标
- <dependency>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache</artifactId>
- </dependency>
复制代码 此处为什么不是导入Ehcache的starter,而是导入技能坐标呢?着实springboot整合缓存技能做的是通用格式,不管你整合哪种缓存技能,只是实现变革了,操纵方式一样。这也表现出springboot技能的优点,同一同类技能的整合方式。
步调②:设置缓存技能实现利用Ehcache
- spring:
- cache:
- type: ehcache
- ehcache:
- config: ehcache.xml
复制代码 设置缓存的范例type为ehcache,此处须要分析一下,当前springboot可以整合的缓存技能中包罗有ehcach,以是可以如许誊写。着实这个type不可以任意写的,不是任意写一个名称就可以整合的。
由于ehcache的设置有独立的设置文件格式,因此还须要指定ehcache的设置文件,以便于读取相应设置
- <?xml version="1.0" encoding="UTF-8"?>
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
- updateCheck="false">
- <diskStore path="D:\ehcache" />
- <!--默认缓存策略 -->
- <!-- external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为false-->
- <!-- diskPersistent:是否启用磁盘持久化-->
- <!-- maxElementsInMemory:最大缓存数量-->
- <!-- overflowToDisk:超过最大缓存数量是否持久化到磁盘-->
- <!-- timeToIdleSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码-->
- <!-- timeToLiveSeconds:最大存活时间-->
- <!-- memoryStoreEvictionPolicy:缓存清除策略-->
- <defaultCache
- eternal="false"
- diskPersistent="false"
- maxElementsInMemory="1000"
- overflowToDisk="false"
- timeToIdleSeconds="60"
- timeToLiveSeconds="60"
- memoryStoreEvictionPolicy="LRU" />
- <cache
- name="smsCode"
- eternal="false"
- diskPersistent="false"
- maxElementsInMemory="1000"
- overflowToDisk="false"
- timeToIdleSeconds="10"
- timeToLiveSeconds="10"
- memoryStoreEvictionPolicy="LRU" />
- </ehcache>
复制代码 留意前面的案例中,设置了数据生存的位置是smsCode
- @CachePut(value = "smsCode", key = "#tele")
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- return code;
- }
复制代码 这个设定须要保障ehcache中有一个缓存空间名称叫做smsCode的设置,前后要同一。在企业开发过程中,通过设置差异名称的cache来设定差异的缓存计谋,应用于差异的缓存数据。
到这里springboot整合Ehcache就做完了,可以发现一点,原始代码没有任何修改,仅仅是加了一组设置就可以变动缓存供应商了,这也是springboot提供了同一的缓存操纵接口的上风,变动实现并不影响原始代码的誊写。
总结
- springboot利用Ehcache作为缓存实现须要导入Ehcache的坐标
- 修改设置,设置缓存供应商为ehcache,并提供对应的缓存设置文件
五、SpringBoot整合Redis缓存
上节利用Ehcache更换了springboot内置的缓存技能,着实springboot支持的缓存技能还许多,下面利用redis技能作为缓存办理方案来实现手机验证码案例。
比对利用Ehcache的过程,加坐标,改缓存实现范例为ehcache,做Ehcache的设置。如果还成redis做缓存呢?千篇划一,加坐标,改缓存实现范例为redis,做redis的设置。差异之处只有一点,redis的设置可以在yml文件中直接举行设置,无需制作独立的设置文件。
步调①:导入redis的坐标
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
复制代码 步调②:设置缓存技能实现利用redis
- spring:
- redis:
- host: localhost
- port: 6379
- cache:
- type: redis
复制代码 如果须要对redis作为缓存举行设置,留意不是对原始的redis举行设置,而是设置redis作为缓存利用相干的设置,从属于spring.cache.redis节点下,留意不要写错位置了。
- spring:
- redis:
- host: localhost
- port: 6379
- cache:
- type: redis redis: use-key-prefix: false key-prefix: sms_ cache-null-values: false time-to-live: 10s
复制代码 总结
- springboot利用redis作为缓存实现须要导入redis的坐标
- 修改设置,设置缓存供应商为redis,并提供对应的缓存设置
六、SpringBoot整合Memcached缓存
现在我们已经把握了3种缓存办理方案的设置情势,分别是springboot内置缓存,ehcache和redis,本节研究一下国内比力盛行的一款缓存memcached。
按照之前的套路,着实变动缓存并不繁琐,但是springboot并没有支持利用memcached作为其缓存办理方案,也就是说在type属性中没有memcached的设置选项,这里就须要更变一下处置惩罚方式了。在整合之前先安装memcached。
安装
windows版安装包下载地点:Windows 下安装 Memcached | 菜鸟教程
下载的安装包是解压缩就能利用的zip文件,解压缩完毕后会得到如下文件
可实行文件只有一个memcached.exe,利用该文件可以将memcached作为体系服务启动,实行此文件时会出现报错信息,如下:
此处出现标题的缘故原由是注册体系服务时须要利用管理员权限,当前账号权限不敷导致安装服务失败,切换管理员账号权限启动下令行
然后再次实行安装服务的下令即可,如下:
服务安装完毕后可以利用下令启动和克礼服务,如下:
- memcached.exe -d start # 启动服务
- memcached.exe -d stop # 停止服务
复制代码 也可以在使命管理器中举行服务状态的切换
变动缓存为Memcached
由于memcached未被springboot收录为缓存办理方案,因此利用memcached须要通过手工硬编码的方式来利用,于是前面的套路都不实用了,须要本身写了。
memcached目条件供有三种客户端技能,分别是Memcached Client for Java、SpyMemcached和Xmemcached,此中性能指标各方面最好的客户端是Xmemcached,本次整合就利用这个作为客户端实现技能了。下面开始利用Xmemcached
步调①:导入xmemcached的坐标
- <dependency>
- <groupId>com.googlecode.xmemcached</groupId>
- <artifactId>xmemcached</artifactId>
- <version>2.4.7</version>
- </dependency>
复制代码 步调②:设置memcached,制作memcached的设置类
- @Configuration
- public class XMemcachedConfig {
- @Bean
- public MemcachedClient getMemcachedClient() throws IOException {
- MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
- MemcachedClient memcachedClient = memcachedClientBuilder.build();
- return memcachedClient;
- }
- }
复制代码 memcached默认对外服务端口11211。
步调③:利用xmemcached客户端操纵缓存,注入MemcachedClient对象
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
- @Autowired
- private MemcachedClient memcachedClient;
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- try {
- memcachedClient.set(tele,10,code);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- String code = null;
- try {
- code = memcachedClient.get(smsCode.getTele()).toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return smsCode.getCode().equals(code);
- }
- }
复制代码 设置值到缓存中利用set操纵,取值利用get操纵,着实更符合我们开发者的风俗。
上述代码中对于服务器的设置利用硬编码写死到了代码中,将此数据提取出来,做成独立的设置属性。
界说设置属性
以下过程采取前期学习的属性设置方式举行,当前操纵有助于明白原理篇中的许多知识。
- 界说设置类,加载须要的设置属性,读取设置文件中memcached节点信息
- @Component
- @ConfigurationProperties(prefix = "memcached")
- @Data
- public class XMemcachedProperties {
- private String servers;
- private int poolSize;
- private long opTimeout;
- }
复制代码 界说memcached节点信息
- memcached:
- servers: localhost:11211
- poolSize: 10
- opTimeout: 3000
复制代码
- @Configuration
- public class XMemcachedConfig {
- @Autowired
- private XMemcachedProperties props;
- @Bean
- public MemcachedClient getMemcachedClient() throws IOException {
- MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(props.getServers());
- memcachedClientBuilder.setConnectionPoolSize(props.getPoolSize());
- memcachedClientBuilder.setOpTimeout(props.getOpTimeout());
- MemcachedClient memcachedClient = memcachedClientBuilder.build();
- return memcachedClient;
- }
- }
复制代码 总结
- memcached安装后须要启动对应服务才可以对外提供缓存功能,安装memcached服务须要基于windows体系管理员权限
- 由于springboot没有提供对memcached的缓存整合方案,须要采取手工编码的情势创建xmemcached客户端操纵缓存
- 导入xmemcached坐标后,创建memcached设置类,注册MemcachedClient对应的bean,用于操纵缓存
- 初始化MemcachedClient对象所须要利用的属性可以通过自界说设置属性类的情势加载
思考
到这里已经完成了三种缓存的整合,此中redis和mongodb须要安装独立的服务器,毗连时须要输入对应的服务器地点,这种是远程缓存,Ehcache是一个典范的内存级缓存,由于它什么也不消安装,启动后导入jar包就有缓存功能了。这个时间就要问了,能不能这两种缓存一起用呢?咱们下节再说。
七、SpringBoot整合jetcache缓存
现在我们利用的缓存都是要么A要么B,能不能AB一起用呢?这一节就办理这个标题。springboot针对缓存的整合仅仅停顿在用缓存上面,如果缓存自身不支持同时支持AB一起用,springboot也没办法,以是要想办理AB缓存一起用的标题,就必须找一款缓存可以大概支持AB两种缓存一起用,有这种缓存吗?还真有,阿里出品,jetcache。
jetcache严格意义上来说,并不是一个缓存办理方案,只能说他算是一个缓存框架,然后把别的缓存放到jetcache中管理,如许就可以支持AB缓存一起用了。而且jetcache参考了springboot整合缓存的头脑,团体技能利用方式和springboot的缓存办理方案头脑非常雷同。下面咱们就先把jetcache用起来,然后再说它内里的一些小的功能。
做之前要先明确一下,jetcache并不是任意拿两个缓存都能拼到一起去的。现在jetcache支持的缓存方案本地缓存支持两种,远程缓存支持两种,分别如下:
着实也有人问我,为什么jetcache只支持2+2这么4款缓存呢?阿里研发这个技能着实紧张是为了满足自身的利用须要。最初肯定只有1+1种,渐渐变革成2+2种。下面就以LinkedHashMap+Redis的方案实现本地与远程缓存方案同时利用。
7.1纯远程方案
步调①:导入springboot整合jetcache对应的坐标starter,当前坐标默认利用的远程方案是redis
- <dependency>
- <groupId>com.alicp.jetcache</groupId>
- <artifactId>jetcache-starter-redis</artifactId>
- <version>2.6.2</version>
- </dependency>
复制代码 步调②:远程方案根本设置
- jetcache:
- remote:
- default:
- type: redis
- host: localhost
- port: 6379
- poolConfig:
- maxTotal: 50
复制代码 此中poolConfig是必配项,否则会报错
步调③:启用缓存,在引导类上方标注注解@EnableCreateCacheAnnotation设置springboot步伐中可以利用注解的情势创建缓存
- @SpringBootApplication
- //jetcache启用缓存的主开关
- @EnableCreateCacheAnnotation
- public class Springboot20JetCacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(Springboot20JetCacheApplication.class, args);
- }
- }
复制代码 步调④:创建缓存对象Cache,并利用注解@CreateCache标志当前缓存的信息,然后利用Cache对象的API操纵缓存,put写缓存,get读缓存。
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
-
- @CreateCache(name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
- private Cache<String ,String> jetCache;
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- jetCache.put(tele,code);
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- String code = jetCache.get(smsCode.getTele());
- return smsCode.getCode().equals(code);
- }
- }
复制代码 通过上述jetcache利用远程方案毗连redis可以看出,jetcache操纵缓存时的接口操纵更符合开发者风俗,利用缓存就先获取缓存对象Cache,放数据进去就是put,取数据出来就是get,更加简朴易懂。而且jetcache操纵缓存时,可以为某个缓存对象设置逾期时间,将同范例的数据放入缓存中,方便有效周期的管理。
上述方案中利用的是设置中界说的default缓存,着实这个default是个名字,可以任意写,也可以任意加。比方再添加一种缓存办理方案,参照如下设置举行:
- jetcache:
- remote:
- default:
- type: redis
- host: localhost
- port: 6379
- poolConfig:
- maxTotal: 50 sms: type: redis host: localhost port: 6379 poolConfig: maxTotal: 50
复制代码 如果想利用名称是sms的缓存,须要再创建缓存时指定参数area,声明利用对应缓存即可
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
-
- @CreateCache(area="sms",name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
- private Cache<String ,String> jetCache;
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- jetCache.put(tele,code);
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- String code = jetCache.get(smsCode.getTele());
- return smsCode.getCode().equals(code);
- }
- }
复制代码 7.2纯本地方案
远程方案中,设置中利用remote表现远程,换成local就是本地,只不外范例不一样而已。
步调①:导入springboot整合jetcache对应的坐标starte
- <dependency>
- <groupId>com.alicp.jetcache</groupId>
- <artifactId>jetcache-starter-redis</artifactId>
- <version>2.6.2</version>
- </dependency>
复制代码 步调②:本地缓存根本设置
- jetcache:
- local:
- default:
- type: linkedhashmap
- keyConvertor: fastjson
复制代码 为了加快数据获取时key的匹配速率,jetcache要求指定key的范例转换器。简朴说就是,如果你给了一个Object作为key的话,我先用key的范例转换器给转换成字符串,然后再生存。比及获取数据时,仍旧是先利用给定的Object转换成字符串,然后根据字符串匹配。由于jetcache是阿里的技能,这里保举key的范例转换器利用阿里的fastjson。
步调③:启用缓存
- @SpringBootApplication
- //jetcache启用缓存的主开关
- @EnableCreateCacheAnnotation
- public class Springboot20JetCacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(Springboot20JetCacheApplication.class, args);
- }
- }
复制代码 步调④:创建缓存对象Cache时,标注当前利用本地缓存
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
- private Cache<String ,String> jetCache;
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- jetCache.put(tele,code);
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- String code = jetCache.get(smsCode.getTele());
- return smsCode.getCode().equals(code);
- }
- }
复制代码 cacheType控制当前缓存利用本地缓存还是远程缓存,设置cacheType=CacheType.LOCAL即利用本地缓存。
7.3本地+远程方案
本地和远程方法都有了,两种方案一起利用怎样设置呢?着实就是将两种设置归并到一起就可以了。
- jetcache:
- local:
- default:
- type: linkedhashmap
- keyConvertor: fastjson remote: default: type: redis host: localhost port: 6379 poolConfig: maxTotal: 50 sms: type: redis host: localhost port: 6379 poolConfig: maxTotal: 50
复制代码 在创建缓存的时间,设置cacheType为BOTH即则本地缓存与远程缓存同时利用。
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.BOTH)
- private Cache<String ,String> jetCache;
- }
复制代码 cacheType如果不举行设置,默认值是REMOTE,即仅利用远程缓存方案。关于jetcache的设置,参考以下信息
属性默认值分析jetcache.statIntervalMinutes0统计隔断,0表现不统计jetcache.hiddenPackages无自动天生name时,埋伏指定的包名前缀jetcache.[local|remote].${area}.type无缓存范例,本地支持linkedhashmap、caffeine,远程支持redis、tairjetcache.[local|remote].${area}.keyConvertor无key转换器,当前仅支持fastjsonjetcache.[local|remote].${area}.valueEncoderjava仅remote范例的缓存须要指定,可选java和kryojetcache.[local|remote].${area}.valueDecoderjava仅remote范例的缓存须要指定,可选java和kryojetcache.[local|remote].${area}.limit100仅local范例的缓存须要指定,缓存实例最大元素数jetcache.[local|remote].${area}.expireAfterWriteInMillis无穷大默认逾期时间,毫秒单元jetcache.local.${area}.expireAfterAccessInMillis0仅local范例的缓存有效,毫秒单元,最大不活动隔断以上方案仅支持手工控制缓存,但是springcache方案中的方法缓存特殊好用,给一个方法添加一个注解,方法就会自动利用缓存。jetcache也提供了对应的功能,即方法缓存。
方法缓存
jetcache提供了方法缓存方案,只不外名称变动了而已。在对应的操纵接口上方利用注解@Cached即可
步调①:导入springboot整合jetcache对应的坐标starter
- <dependency>
- <groupId>com.alicp.jetcache</groupId>
- <artifactId>jetcache-starter-redis</artifactId>
- <version>2.6.2</version>
- </dependency>
复制代码 步调②:设置缓存
- jetcache:
- local:
- default:
- type: linkedhashmap
- keyConvertor: fastjson remote: default: type: redis host: localhost port: 6379 keyConvertor: fastjson valueEncode: java valueDecode: java poolConfig: maxTotal: 50 sms: type: redis host: localhost port: 6379 poolConfig: maxTotal: 50
复制代码 由于redis缓存中不支持生存对象,因此须要对redis设置当Object范例数据进入到redis中时怎样举行范例转换。须要设置keyConvertor表现key的范例转换方式,同时标注value的转换范例方式,值进入redis时是java范例,标注valueEncode为java,值从redis中读取时转换成java,标注valueDecode为java。
留意,为了实现Object范例的值收支redis,须要保障收支redis的Object范例的数据必须实现序列化接口。
- @Data
- public class Book implements Serializable {
- private Integer id;
- private String type;
- private String name;
- private String description;
- }
复制代码 步调③:启用缓存时开启方法缓存功能,并设置basePackages,分析在哪些包中开启方法缓存
- @SpringBootApplication
- //jetcache启用缓存的主开关
- @EnableCreateCacheAnnotation
- //开启方法注解缓存
- @EnableMethodCache(basePackages = "com.itheima")
- public class Springboot20JetCacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(Springboot20JetCacheApplication.class, args);
- }
- }
复制代码 步调④:利用注解@Cached标注当火线法利用缓存
- @Service
- public class BookServiceImpl implements BookService {
- @Autowired
- private BookDao bookDao;
-
- @Override
- @Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
- public Book getById(Integer id) {
- return bookDao.selectById(id);
- }
- }
复制代码 远程方案的数据同步
由于远程方案中redis生存的数据可以被多个客户端共享,这就存在了数据同步标题。jetcache提供了3个注解办理此标题,分别在更新、删除操纵时同步缓存数据,和读取缓存时定时革新数据
更新缓存
- @CacheUpdate(name="book_",key="#book.id",value="#book")
- public boolean update(Book book) {
- return bookDao.updateById(book) > 0;
- }
复制代码 删除缓存
- @CacheInvalidate(name="book_",key = "#id")
- public boolean delete(Integer id) {
- return bookDao.deleteById(id) > 0;
- }
复制代码 定时革新缓存
- @Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
- @CacheRefresh(refresh = 5)
- public Book getById(Integer id) {
- return bookDao.selectById(id);
- }
复制代码 数据报表
jetcache还提供有简朴的数据报表功能,资助开发者快速查察缓存掷中信息,只须要添加一个设置即可
- jetcache:
- statIntervalMinutes: 1
复制代码 设置后,每1分钟在控制台输出缓存数据掷中信息
- [DefaultExecutor] c.alicp.jetcache.support.StatInfoLogger : jetcache stat from 2022-02-28 09:32:15,892 to 2022-02-28 09:33:00,003
- cache | qps| rate| get| hit| fail| expire| avgLoadTime| maxLoadTime
- ---------+-------+-------+------+-------+-------+---------+--------------+--------------
- book_ | 0.66| 75.86%| 29| 22| 0| 0| 28.0| 188
- ---------+-------+-------+------+-------+-------+---------+--------------+--------------
复制代码 总结
- jetcache是一个雷同于springcache的缓存办理方案,自身不具有缓存功能,它提供有本地缓存与远程缓存多级共同利用的缓存办理方案
- jetcache提供的缓存办理方案受限于现在支持的方案,本地缓存支持两种,远程缓存支持两种
- 留意数据进入远程缓存时的范例转换标题
- jetcache提供方法缓存,并提供了对应的缓存更新与革新功能
- jetcache提供有简朴的缓存信息掷中报表方便开发者即时监控
缓存数据掷中情况
思考
jetcache办理了前期利用缓存方案单一的标题,但是仍旧不能机动的选择缓存举行搭配利用,是否存在一种技能可以机动的搭配各种各样的缓存利用呢?有,咱们下一节再讲。
八、SpringBoot整合j2cache缓存
jetcache可以在限定范围内构建多级缓存,但是机动性不敷,不能随意搭配缓存,本节先容一种可以随意搭配缓存办理方案的缓存整合框架,j2cache。下面就来讲授怎样利用这种缓存框架,以Ehcache与redis整合为例:
步调①:导入j2cache、redis、ehcache坐标
- <dependency> <groupId>net.oschina.j2cache</groupId> <artifactId>j2cache-core</artifactId> <version>2.8.4-release</version></dependency><dependency> <groupId>net.oschina.j2cache</groupId> <artifactId>j2cache-spring-boot2-starter</artifactId> <version>2.8.0-release</version></dependency><dependency>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache</artifactId>
- </dependency>
复制代码 j2cache的starter中默认包罗了redis坐标,官方保举利用redis作为二级缓存,因此此处无需导入redis坐标
步调②:设置一级与二级缓存,并设置一二级缓存间数据转达方式,设置誊写在名称为j2cache.properties的文件中。如果利用ehcache还须要单独添加ehcache的设置文件
- # 1级缓存
- j2cache.L1.provider_class = ehcache
- ehcache.configXml = ehcache.xml
- # 2级缓存
- j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
- j2cache.L2.config_section = redis
- redis.hosts = localhost:6379
- # 1级缓存中的数据如何到达二级缓存
- j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
复制代码 此处设置不能乱设置,须要参照官方给出的设置分析举行。比方1级供应商选择ehcache,供应商名称仅仅是一个ehcache,但是2级供应商选择redis时要写专用的Spring整合Redis的供应商类名SpringRedisProvider,而且这个名称并不是全部的redis包中能提供的,也不是spring包中提供的。因此设置j2cache必须参照官方文档设置,而且还要去找专用的整合包,导入对应坐标才可以利用。
一级与二级缓存最紧张的一个设置就是两者之间的数据沟通方式,此类设置也不是随意设置的,而且差异的缓存办理方案提供的数据沟通方式差异化很大,须要查询官方文档举行设置。
步调③:利用缓存
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
- @Autowired
- private CacheChannel cacheChannel;
- public String sendCodeToSMS(String tele) {
- String code = codeUtils.generator(tele);
- cacheChannel.set("sms",tele,code);
- return code;
- }
- public boolean checkCode(SMSCode smsCode) {
- String code = cacheChannel.get("sms",smsCode.getTele()).asString();
- return smsCode.getCode().equals(code);
- }
- }
复制代码 j2cache的利用和jetcache比力雷同,但是无需开启利用的开关,直接界说缓存对象即可利用,缓存对象名CacheChannel。
j2cache的利用不复杂,设置是j2cache的核心,毕竟是一个整合型的缓存框架。缓存相干的设置过多,可以查阅j2cache-core核心包中的j2cache.properties文件中的分析。如下:
- #J2Cache configuration
- #########################################
- # Cache Broadcast Method
- # values:
- # jgroups -> use jgroups's multicast
- # redis -> use redis publish/subscribe mechanism (using jedis)
- # lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend)
- # rabbitmq -> use RabbitMQ publisher/consumer mechanism
- # rocketmq -> use RocketMQ publisher/consumer mechanism
- # none -> don't notify the other nodes in cluster
- # xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy
- #########################################
- j2cache.broadcast = redis
- # jgroups properties
- jgroups.channel.name = j2cache
- jgroups.configXml = /network.xml
- # RabbitMQ properties
- rabbitmq.exchange = j2cache
- rabbitmq.host = localhost
- rabbitmq.port = 5672
- rabbitmq.username = guest
- rabbitmq.password = guest
- # RocketMQ properties
- rocketmq.name = j2cache
- rocketmq.topic = j2cache
- # use ; to split multi hosts
- rocketmq.hosts = 127.0.0.1:9876
- #########################################
- # Level 1&2 provider
- # values:
- # none -> disable this level cache
- # ehcache -> use ehcache2 as level 1 cache
- # ehcache3 -> use ehcache3 as level 1 cache
- # caffeine -> use caffeine as level 1 cache(only in memory)
- # redis -> use redis as level 2 cache (using jedis)
- # lettuce -> use redis as level 2 cache (using lettuce)
- # readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.
- # memcached -> use memcached as level 2 cache (xmemcached),
- # [classname] -> use custom provider
- #########################################
- j2cache.L1.provider_class = caffeine
- j2cache.L2.provider_class = redis
- # When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations
- # j2cache.L2.config_section = redis
- # Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
- # NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
- j2cache.sync_ttl_to_redis = true
- # Whether to cache null objects by default (default false)
- j2cache.default_cache_null_object = true
- #########################################
- # Cache Serialization Provider
- # values:
- # fst -> using fast-serialization (recommend)
- # kryo -> using kryo serialization
- # json -> using fst's json serialization (testing)
- # fastjson -> using fastjson serialization (embed non-static class not support)
- # java -> java standard
- # fse -> using fse serialization
- # [classname implements Serializer]
- #########################################
- j2cache.serialization = json
- #json.map.person = net.oschina.j2cache.demo.Person
- #########################################
- # Ehcache configuration
- #########################################
- # ehcache.configXml = /ehcache.xml
- # ehcache3.configXml = /ehcache3.xml
- # ehcache3.defaultHeapSize = 1000
- #########################################
- # Caffeine configuration
- # caffeine.region.[name] = size, xxxx[s|m|h|d]
- #
- #########################################
- caffeine.properties = /caffeine.properties
- #########################################
- # Redis connection configuration
- #########################################
- #########################################
- # Redis Cluster Mode
- #
- # single -> single redis server
- # sentinel -> master-slaves servers
- # cluster -> cluster servers (数据库配置无效,使用 database = 0)
- # sharded -> sharded servers (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:[email protected]:6379/0)
- #
- #########################################
- redis.mode = single
- #redis storage mode (generic|hash)
- redis.storage = generic
- ## redis pub/sub channel name
- redis.channel = j2cache
- ## redis pub/sub server (using redis.hosts when empty)
- redis.channel.host =
- #cluster name just for sharded
- redis.cluster_name = j2cache
- ## redis cache namespace optional, default[empty]
- redis.namespace =
- ## redis command scan parameter count, default[1000]
- #redis.scanCount = 1000
- ## connection
- # Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379
- redis.hosts = 127.0.0.1:6379
- redis.timeout = 2000
- redis.password =
- redis.database = 0
- redis.ssl = false
- ## redis pool properties
- redis.maxTotal = 100
- redis.maxIdle = 10
- redis.maxWaitMillis = 5000
- redis.minEvictableIdleTimeMillis = 60000
- redis.minIdle = 1
- redis.numTestsPerEvictionRun = 10
- redis.lifo = false
- redis.softMinEvictableIdleTimeMillis = 10
- redis.testOnBorrow = true
- redis.testOnReturn = false
- redis.testWhileIdle = true
- redis.timeBetweenEvictionRunsMillis = 300000
- redis.blockWhenExhausted = false
- redis.jmxEnabled = false
- #########################################
- # Lettuce scheme
- #
- # redis -> single redis server
- # rediss -> single redis server with ssl
- # redis-sentinel -> redis sentinel
- # redis-cluster -> cluster servers
- #
- #########################################
- #########################################
- # Lettuce Mode
- #
- # single -> single redis server
- # sentinel -> master-slaves servers
- # cluster -> cluster servers (数据库配置无效,使用 database = 0)
- # sharded -> sharded servers (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:[email protected]:6379/0)
- #
- #########################################
- ## redis command scan parameter count, default[1000]
- #lettuce.scanCount = 1000
- lettuce.mode = single
- lettuce.namespace =
- lettuce.storage = hash
- lettuce.channel = j2cache
- lettuce.scheme = redis
- lettuce.hosts = 127.0.0.1:6379
- lettuce.password =
- lettuce.database = 0
- lettuce.sentinelMasterId =
- lettuce.maxTotal = 100
- lettuce.maxIdle = 10
- lettuce.minIdle = 10
- # timeout in milliseconds
- lettuce.timeout = 10000
- # redis cluster topology refresh interval in milliseconds
- lettuce.clusterTopologyRefresh = 3000
- #########################################
- # memcached server configurations
- # refer to https://gitee.com/mirrors/XMemcached
- #########################################
- memcached.servers = 127.0.0.1:11211
- memcached.username =
- memcached.password =
- memcached.connectionPoolSize = 10
- memcached.connectTimeout = 1000
- memcached.failureMode = false
- memcached.healSessionInterval = 1000
- memcached.maxQueuedNoReplyOperations = 100
- memcached.opTimeout = 100
- memcached.sanitizeKeys = false
复制代码 总结
- j2cache是一个缓存框架,自身不具有缓存功能,它提供多种缓存整合在一起利用的方案
- j2cache须要通过复杂的设置设置各级缓存,以及缓存之间数据互换的方式
- j2cache操纵接口通过CacheChannel实现
|