SpringBoot篇(缓存层)

目录

前言

缓存是什么?

一、SpringBoot内置缓存解决方案

1. 简介

2. 手机验证码案例

二、SpringBoot整合Ehcache缓存

1. 简介

2. 总结

三、SpringBoot整合Redis缓存

1. 简介

2. 总结

四、SpringBoot整合Memcached缓存

1. 简介

2. 安装

3. 变更缓存为Memcached

4. 定义配置属性

5. 总结

6. 思考

7. 代码

五、SpringBoot整合jetcache缓存

1. 简介

2. jetcache 支持的缓存方案

2.1. 本地缓存(Local)

2.2. 远程缓存(Remote)

2.3. 为什么jetcache只支持2+2这么4款缓存呢?

3. 纯远程方案

4. 纯本地方案

5. 本地+远程方案

方法缓存

6. 远程方案的数据同步

更新缓存

删除缓存

定时刷新缓存

7. 数据报表

8. 总结

9. 思考

10. 代码

六、SpringBoot整合j2cache缓存

1. 简介

2. 总结

3. 代码


前言

企业级应用主要作用是信息处理,当需要读取数据时,由于受限于数据库的访问效率,导致整体系统性能偏低。

应用程序直接与数据库打交道,访问效率低

为了改善上述现象,开发者通常会在应用程序与数据库之间建立一种临时的数据存储机制,

该区域中的数据在内存中保存,读写速度较快,可以有效解决数据库访问效率低下的问题。

这一块临时存储数据的区域就是缓存。

使用缓存后,应用程序与缓存打交道,缓存与数据库打交道,数据访问效率提高

缓存是什么?

缓存是一种介于数据永久存储介质与应用程序之间的数据临时存储介质,使用缓存可以有效的减少低速数据读取

过程的次数(例如磁盘IO),提高系统性能。

此外缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间。

而springboot提供了对市面上几乎所有的缓存技术进行整合的方案,下面就一起开启springboot整合缓存之旅。

一、SpringBoot内置缓存解决方案

1. 简介

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 {@Autowiredprivate BookDao bookDao;@Cacheable(value="cacheSpace",key="#id")public Book getById(Integer id) {return bookDao.selectById(id);}
}

在业务方法上面使用注解@Cacheable声明当前方法的返回值放入缓存中,其中要指定缓存的存储位置,以及缓存

中保存当前方法返回值对应的名称。

上例中value属性描述缓存的存储位置,可以理解为是一个存储空间名,key属性描述了缓存中保存数据的名称,

使用#id读取形参中的id值作为缓存名称。

使用@Cacheable注解后,执行当前操作,如果发现对应名称在缓存中没有数据,就正常读取数据,然后放入缓

存;如果对应名称在缓存中有数据,就终止当前业务方法执行,直接返回缓存中的数据。

2. 手机验证码案例

为了便于下面演示各种各样的缓存技术,我们创建一个手机验证码的案例环境,模拟使用缓存保存手机验证码的过程。

手机验证码案例需求如下:

  1. 输入手机号获取验证码,组织文档以短信形式发送给用户(页面模拟)
  2. 输入手机号和验证码验证结果

为了描述上述操作,我们制作两个表现层接口,一个用来模拟发送短信的过程,其实就是根据用户提供的手机号生成一个验证码,

然后放入缓存,另一个用来模拟验证码校验的过程,其实就是使用传入的手机号和验证码进行匹配,并返回最终匹配结果。

下面直接制作本案例的模拟代码,先以上例中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 {@Autowiredprivate CodeUtils codeUtils;@CachePut(value = "smsCode", key = "#tele")public String sendCodeToSMS(String tele) {String code = codeUtils.generator(tele);return code;}public boolean checkCode(SMSCode smsCode) {//取出内存中的验证码与传递过来的验证码比对,如果相同,返回trueString 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 {@Autowiredprivate SMSCodeService smsCodeService;@GetMappingpublic String getCode(String tele){String code = smsCodeService.sendCodeToSMS(tele);return code;}@PostMappingpublic boolean checkCode(SMSCode smsCode){return smsCodeService.checkCode(smsCode);}
}

二、SpringBoot整合Ehcache缓存

1. 简介

手机验证码的案例已经完成了,下面就开始springboot整合各种各样的缓存技术,第一个整合Ehcache技术。

Ehcache是一种缓存技术,使用springboot整合Ehcache其实就是变更一下缓存技术的实现方式,话不多说,直

接开整

步骤一:导入Ehcache的坐标

<dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency>

此处为什么不是导入Ehcache的starter,而是导入技术坐标呢?

其实springboot整合缓存技术做的是通用格式,不管你整合哪种缓存技术,只是实现变化了,操作方式一样。

这也体现出springboot技术的优点,统一同类技术的整合方式。

步骤二:配置缓存技术实现使用Ehcache

spring:cache:type: ehcacheehcache: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:缓存清除策略--><defaultCacheeternal="false"diskPersistent="false"maxElementsInMemory="1000"overflowToDisk="false"timeToIdleSeconds="60"timeToLiveSeconds="60"memoryStoreEvictionPolicy="LRU" /><cachename="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提供了统一的缓存操作接口的优势,

变更实现并不影响原始代码的书写。

2. 总结

  1. springboot使用Ehcache作为缓存实现需要导入Ehcache的坐标
  2. 修改设置,配置缓存供应商为ehcache,并提供对应的缓存配置文件

三、SpringBoot整合Redis缓存

1. 简介

上小节使用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: localhostport: 6379cache:type: redis

如果需要对redis作为缓存进行配置,注意不是对原始的redis进行配置,而是配置redis作为缓存使用相关的配置,

隶属于spring.cache.redis节点下,注意不要写错位置了。

spring:redis:host: localhostport: 6379cache:type: redisredis:use-key-prefix: falsekey-prefix: sms_cache-null-values: falsetime-to-live: 10s

2. 总结

  1. springboot使用redis作为缓存实现需要导入redis的坐标
  2. 修改设置,配置缓存供应商为redis,并提供对应的缓存配置

四、SpringBoot整合Memcached缓存

1. 简介

目前我们已经掌握了3种缓存解决方案的配置形式,分别是springboot内置缓存,ehcache和redis,

本节研究一下国内比较流行的一款缓存memcached。

按照之前的套路,其实变更缓存并不繁琐,但是springboot并没有支持使用memcached作为其缓存解决方案,

也就是说在type属性中没有memcached的配置选项,这里就需要更变一下处理方式了。

在整合之前先安装memcached。

2. 安装

windows版安装包下载地址:Windows 下安装 Memcached | 菜鸟教程

下载的安装包是解压缩就能使用的zip文件,解压缩完毕后会得到如下文件

可执行文件只有一个memcached.exe,使用该文件可以将memcached作为系统服务启动,

执行此文件时会出现报错信息,如下:

此处出现问题的原因是注册系统服务时需要使用管理员权限,当前账号权限不足导致安装服务失败,切换管理员

账号权限启动命令行

然后再次执行安装服务的命令即可,如下:

memcached.exe -d install

服务安装完毕后可以使用命令启动和停止服务,如下:

memcached.exe -d start		# 启动服务
memcached.exe -d stop		# 停止服务

也可以在任务管理器中进行服务状态的切换

3. 变更缓存为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 {@Beanpublic 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 {@Autowiredprivate CodeUtils codeUtils;@Autowiredprivate 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操作,其实更符合我们开发者的习惯。

上述代码中对于服务器的配置使用硬编码写死到了代码中,将此数据提取出来,做成独立的配置属性。

4. 定义配置属性

定义配置类,加载必要的配置属性,读取配置文件中memcached节点信息

@Component
@ConfigurationProperties(prefix = "memcached")
@Data
public class XMemcachedProperties {private String servers;private int poolSize;private long opTimeout;
}

定义memcached节点信息

memcached:servers: localhost:11211poolSize: 10opTimeout: 3000

在memcached配置类中加载信息

@Configuration
public class XMemcachedConfig {@Autowiredprivate XMemcachedProperties props;@Beanpublic MemcachedClient getMemcachedClient() throws IOException {MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(props.getServers());memcachedClientBuilder.setConnectionPoolSize(props.getPoolSize());memcachedClientBuilder.setOpTimeout(props.getOpTimeout());MemcachedClient memcachedClient = memcachedClientBuilder.build();return memcachedClient;}
}

5. 总结

  1. memcached安装后需要启动对应服务才可以对外提供缓存功能,安装memcached服务需要基于windows系统管理员权限
  2. 由于springboot没有提供对memcached的缓存整合方案,需要采用手工编码的形式创建xmemcached客户端操作缓存
  3. 导入xmemcached坐标后,创建memcached配置类,注册MemcachedClient对应的bean,用于操作缓存
  4. 初始化MemcachedClient对象所需要使用的属性可以通过自定义配置属性类的形式加载

6. 思考

到这里已经完成了三种缓存的整合,其中redis和mongodb需要安装独立的服务器,连接时需要输入对应的服务

器地址,这种是远程缓存,Ehcache是一个典型的内存级缓存,因为它什么也不用安装,启动后导入jar包就有缓

存功能了。

这个时候就要问了,能不能这两种缓存一起用呢?

当然可以

7. 代码

五、SpringBoot整合jetcache缓存

1. 简介

目前我们使用的缓存都是要么A要么B,能不能AB一起用呢?这一节就解决这个问题。

springboot针对缓存的整合仅仅停留在用缓存上面,如果缓存自身不支持同时支持AB一起用,springboot也没办

法,所以要想解决AB缓存一起用的问题,就必须找一款缓存能够支持AB两种缓存一起用,有这种缓存吗?还真

有,阿里出品,jetcache。

jetcache严格意义上来说,并不是一个缓存解决方案,只能说他算是一个缓存框架,然后把别的缓存放到jetcache

中管理,这样就可以支持AB缓存一起用了。

并且jetcache参考了springboot整合缓存的思想,整体技术使用方式和springboot的缓存解决方案思想非常类

似。下面咱们就先把jetcache用起来,然后再说它里面的一些小的功能。

做之前要先明确一下,jetcache并不是随便拿两个缓存都能拼到一起去的。

目前jetcache支持的缓存方案本地缓存支持两种,远程缓存支持两种,分别如下:

2. jetcache 支持的缓存方案

2.1. 本地缓存(Local)

  • LinkedHashMap
  • Caffeine

2.2. 远程缓存(Remote)

  • Redis
  • Tair

2.3. 为什么jetcache只支持2+2这么4款缓存呢?

阿里研发这个技术其实主要是为了满足自身的使用需要。

最初肯定只有1+1种,逐步变化成2+2种。

下面就以LinkedHashMap+Redis的方案实现本地与远程缓存方案同时使用。

3. 纯远程方案

步骤一:导入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: redishost: localhostport: 6379poolConfig: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 {@Autowiredprivate 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: redishost: localhostport: 6379poolConfig:maxTotal: 50sms:type: redishost: localhostport: 6379poolConfig:maxTotal: 50

如果想使用名称是sms的缓存,需要再创建缓存时指定参数area,声明使用对应缓存即可

@Service
public class SMSCodeServiceImpl implements SMSCodeService {@Autowiredprivate 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);}
}

4. 纯本地方案

远程方案中,配置中使用remote表示远程,换成local就是本地,只不过类型不一样而已。

步骤一:导入springboot整合jetcache对应的坐标starter

<dependency><groupId>com.alicp.jetcache</groupId><artifactId>jetcache-starter-redis</artifactId><version>2.6.2</version></dependency>

步骤二:本地缓存基本配置

jetcache:local:default:type: linkedhashmapkeyConvertor: 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即使用本地缓存。

5. 本地+远程方案

本地和远程方法都有了,两种方案一起使用如何配置呢?其实就是将两种配置合并到一起就可以了。

jetcache:local:default:type: linkedhashmapkeyConvertor: fastjsonremote:default:type: redishost: localhostport: 6379poolConfig:maxTotal: 50sms:type: redishost: localhostport: 6379poolConfig: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.statIntervalMinutes

0

统计间隔,0表示不统计

jetcache.hiddenPackages

自动生成name时,隐藏指定的包名前缀

jetcache.[local|remote].${area}.type

缓存类型,本地支持linkedhashmap、caffeine,远程支持redis、tair

jetcache.[local|remote].${area}.keyConvertor

key转换器,当前仅支持fastjson

jetcache.[local|remote].${area}.valueEncoder

java

仅remote类型的缓存需要指定,可选java和kryo

jetcache.[local|remote].${area}.valueDecoder

java

仅remote类型的缓存需要指定,可选java和kryo

jetcache.[local|remote].${area}.limit

100

仅local类型的缓存需要指定,缓存实例最大元素数

jetcache.[local|remote].${area}.expireAfterWriteInMillis

无穷大

默认过期时间,毫秒单位

jetcache.local.${area}.expireAfterAccessInMillis

0

仅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: linkedhashmapkeyConvertor: fastjsonremote:default:type: redishost: localhostport: 6379keyConvertor: fastjsonvalueEncode: javavalueDecode: javapoolConfig:maxTotal: 50sms:type: redishost: localhostport: 6379poolConfig: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.yj.nz")
public class Springboot20JetCacheApplication {public static void main(String[] args) {SpringApplication.run(Springboot20JetCacheApplication.class, args);}
}

步骤四:使用注解@Cached标注当前方法使用缓存

@Service
public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;@Override@Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)public Book getById(Integer id) {return bookDao.selectById(id);}
}

6. 远程方案的数据同步

由于远程方案中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);
}

7. 数据报表

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
---------+-------+-------+------+-------+-------+---------+--------------+--------------

8. 总结

  1. jetcache是一个类似于springcache的缓存解决方案,自身不具有缓存功能,它提供有本地缓存与远程缓存多级共同使用的缓存解决方案
  2. jetcache提供的缓存解决方案受限于目前支持的方案,本地缓存支持两种,远程缓存支持两种
  3. 注意数据进入远程缓存时的类型转换问题
  4. jetcache提供方法缓存,并提供了对应的缓存更新与刷新功能
  5. jetcache提供有简单的缓存信息命中报表方便开发者即时监控缓存数据命中情况

9. 思考

jetcache解决了前期使用缓存方案单一的问题,但是仍然不能灵活的选择缓存进行搭配使用,

是否存在一种技术可以灵活的搭配各种各样的缓存使用呢?有

10. 代码

六、SpringBoot整合j2cache缓存

1. 简介

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 {@Autowiredprivate CodeUtils codeUtils;@Autowiredprivate 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:password@127.0.0.1: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:6379redis.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:password@127.0.0.1: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

2. 总结

  1. j2cache是一个缓存框架,自身不具有缓存功能,它提供多种缓存整合在一起使用的方案
  2. j2cache需要通过复杂的配置设置各级缓存,以及缓存之间数据交换的方式
  3. j2cache操作接口通过CacheChannel实现

3. 代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/57683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5G 现网信令参数学习(1) - MIB

MIB消息中的参数 systemFrameNumber 000101B, subCarrierSpacingCommon scs30or120, ssb-SubcarrierOffset 6, dmrs-TypeA-Position pos2, pdcch-ConfigSIB1 { controlResourceSetZero 10, searchSpaceZero 4 }, cellBarred notBarred, intraFreqReselection allowed, sp…

1024程序员节特惠题解!

#题外话&#xff1a;/ #先看题目 题目传送门https://www.luogu.com.cn/problem/P1035#思路&#xff1a;直接模拟&#xff08;Shift1&#xff09; #代码&#xff1a; #include <bits/stdc.h> using namespace std; int main(){double cnt0,k,sum0,x;cin>>k;while…

2.1 > Shell 是什么、如何更熟练的使用 Bash Shell

Shell 基础知识 Shell是计算机操作系统中的一个命令行解释器&#xff0c;由C语言编写&#xff0c;用于用户与操作系统之间进行交互。用户可以通过Shell输入命令&#xff0c;操作系统接收到这些命令后执行相应的操作。Shell一般还提供了编程语言的基本功能&#xff0c;允许用户…

【Mac 上将 MOV 格式转换为 MP4 格式的简易指南】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

R语言笔记(四):函数

文章目录 一、Function basics1、Creating your own function2、Function structure3、Using your created function4、Multiple inputs5、Default inputs 二、Return values and side effects1、Returning more than one thing2、Side effectsExample of side effect: plot 三…

从零开始学python必看,最强“Python编程三剑客(pdf)”

目录 三剑客PDF传送门&#xff1a;三剑客 第一本&#xff1a;《Python编程&#xff1a;从入门到实践》 1.1《Python编程&#xff1a;从入门到实践》第一部分&#xff1a;基础知识 1.2《Python编程&#xff1a;从入门到实践》第二部分&#xff1a;项目 第二本&#xff1a;《…

Metasploit渗透测试之模块学习与开发

# 概述 Metasploit 框架采用模块化架构&#xff0c;即所有漏洞利用、有效载荷、编码器等都以模块形式存在。模块化架构使框架功能的扩展更加容易。任何程序员都可以开发自己的模块&#xff0c;并将其轻松移植到框架中。 # 1、使用辅助模块 在之前的"信息收集和扫描 &qu…

【设计模式-原型】

**原型模式&#xff08;Prototype Pattern&#xff09;**是一种创建型设计模式&#xff0c;旨在通过复制现有对象的方式来创建新对象&#xff0c;而不是通过实例化类来创建对象。该模式允许对象通过克隆&#xff08;复制&#xff09;来创建新的实例&#xff0c;因此避免了重新创…

QT-使用QSS美化UI界面

一、QSS简介&#xff1a; Qt Style Sheet&#xff1a;Qt样式表&#xff0c;用来自定义控件外观的一种机制&#xff0c;可以把他类比成CSS&#xff08;CSS主要功能与最终目的都是能使界面的表现与界面的元素分离&#xff09;。QSS机制使应用程序也能像web界面那样随意地改变外观…

构建后端为etcd的CoreDNS的容器集群(二)、下载最新的etcd容器镜像

在尝试获取etcd的容器的最新版本镜像时&#xff0c;使用latest作为tag取到的并非最新版本&#xff0c;本文尝试用实际最新版本的版本号进行pull&#xff0c;从而取到想的最新版etcd容器镜像。 一、用latest作为tag尝试下载最新etcd的镜像 1、下载镜像 [rootlocalhost opt]# …

基于vue框架的的高校消防设施管理系统06y99(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;设备分类,设备信息,维修人员,报修信息,维修进度,院系,消防知识,培训记录,培训信息,备件信息,备件申请,派发信息,采购信息 开题报告内容 基于Vue框架的高校消防设施管理系统开题报告 一、项目背景与意义 随着高校规模的不断扩大和校园建…

OpenCV和HALCON

OpenCV和HALCON是两种广泛用于图像处理和计算机视觉的开发库&#xff0c;它们各有优缺点&#xff0c;适合不同的应用场景。以下是两者的比较&#xff1a; 1. 开发背景与定位 OpenCV (Open Source Computer Vision Library)&#xff1a; 开源库&#xff0c;最初由Intel开发&…

【EmbeddedGUI】PFB设计说明

PFB设计说明 背景介绍 一般来说&#xff0c;要实现屏幕显示&#xff0c;就是向特定像素点写入颜色值&#xff0c;最简单的办法就是直接通过SPI接口&#xff0c;向显示器芯片的特定缓存地址&#xff0c;写入像素点。一般来说&#xff0c;显示器芯片会提供2个基本操作API&#…

qt QNetworkProxy详解

一、概述 QNetworkProxy通过设置代理类型、主机、端口和认证信息&#xff0c;可以使应用程序的所有网络请求通过代理服务器进行。它支持为Qt网络类&#xff08;如QAbstractSocket、QTcpSocket、QUdpSocket、QTcpServer、QNetworkAccessManager等&#xff09;配置网络层代理支持…

数据仓库基础概念

数据仓库 概念 数据仓库&#xff08;Data Warehouse, DW&#xff09;是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合。它是为满足企业决策分析需求而设计的。 面向主题&#xff1a;数据仓库围绕特定的主题组织数据&#xff0c;例如“销售”或“人力资源”&am…

学成在线实战

#1024程序员节&#xff5c;征文# 一、Bug修改 在实战之前&#xff0c;老师留了一个bug&#xff0c;这个bug出现的原因是因为在查询课程计划时&#xff0c;使用的是Inner join查询&#xff0c;所以当章节下面没有小节的时候&#xff0c;是查不出来数据的&#xff0c;只需要将其…

PHP企业门店订货通进销存系统小程序源码

订货通进销存系统&#xff0c;企业运营好帮手&#xff01; &#x1f4e6; 开篇&#xff1a;告别繁琐&#xff0c;企业运营新选择 嘿&#xff0c;各位企业主和创业者们&#xff01;今天我要给大家介绍一款超实用的企业运营神器——“订货通进销存系统”。在这个数字化时代&…

YOLOv5_DeepSORT实现电动自行车头盔佩戴检测系统

获取更多完整项目代码数据集&#xff0c;点此加入免费社区群 &#xff1a; 首页-置顶必看 文档说明 本文档是毕业设计——基于深度学习的电动自行车头盔佩戴检测系统的开发环境配置说明文档&#xff0c;该文档包括运行环境说明以及基本环境配置两大部分。在程序运行前请认真查…

零售行业的数字化营销转型之路

一方面&#xff0c;市场竞争激烈&#xff0c;电商平台、新兴品牌和跨界对手带来巨大压力。另一方面&#xff0c;消费者需求变化迅速&#xff0c;更加追求个性化、多元化和便捷化的购物体验&#xff0c;同时传统零售企业还面临着高成本压力&#xff0c;如租金、人力和库存等。 然…

Rsync数据复制/备份服务应用

文章目录 1. rsync概述1.1 什么是Rsync1.2 rsync的功能1.3 rsync 的功能特性1.4 Rsync 增量复制原理1.5 生产场景架构集群备份方案 2. Rsync工作方式介绍与实践2.1 本地数据传输模式2.1.1 本地数据传输模式语法2.1.2 本地数据传输模式实践 2.2 远程Shell 数据传输模式2.2.1 远程…