自己有网站怎么赚钱,网站建设使用的什么软件有哪些方面,软件网站技术开发公司,上海网站制作科技公司#x1f648;作者简介#xff1a;练习时长两年半的Java up主 #x1f649;个人主页#xff1a;程序员老茶 #x1f64a; ps:点赞#x1f44d;是免费的#xff0c;却可以让写博客的作者开心好久好久#x1f60e; #x1f4da;系列专栏#xff1a;Java全栈#xff0c;… 作者简介练习时长两年半的Java up主 个人主页程序员老茶 ps:点赞是免费的却可以让写博客的作者开心好久好久 系列专栏Java全栈计算机系列火速更新中 格言种一棵树最好的时间是十年前其次是现在 动动小手点个关注不迷路感谢宝子们一键三连 目录 课程名Java内容/作用知识点/设计/实验/作业/练习学习整合第三方技术整合第三方技术缓存SpringBoot内置缓存解决方案手机验证码案例SpringBoot整合Ehcache缓存SpringBoot整合Redis缓存SpringBoot整合Memcached缓存SpringBoot整合jetcache缓存纯远程方案纯本地方案本地远程方案远程方案的数据同步数据报表 SpringBoot整合j2cache缓存 课程名Java
内容/作用知识点/设计/实验/作业/练习
学习整合第三方技术
整合第三方技术
前面的学习我们领略到了springboot在整合第三方技术时强大的一致性在后面我们要使用springboot继续整合各种各样的第三方技术通过本章的学习可以将之前学习的springboot整合第三方技术的思想贯彻到底还是那三板斧。导坐标、做配置、调API。
springboot能够整合的技术实在是太多了可以说是万物皆可整。本章将从企业级开发中常用的一些技术作为出发点对各种各样的技术进行整合。
缓存
企业级应用主要作用是信息处理当需要读取数据时由于受限于数据库的访问效率导致整体系统性能偏低。 应用程序直接与数据库打交道访问效率低
为了改善上述现象开发者通常会在应用程序与数据库之间建立一种临时的数据存储机制该区域中的数据在内存中保存读写速度较快可以有效解决数据库访问效率低下的问题。这一块临时存储数据的区域就是缓存。 使用缓存后应用程序与缓存打交道缓存与数据库打交道数据访问效率提高 缓存是什么缓存是一种介于数据永久存储介质与应用程序之间的数据临时存储介质使用缓存可以有效的减少低速数据读取过程的次数例如磁盘IO提高系统性能。此外缓存不仅可以用于提高永久性存储介质的数据读取效率还可以提供临时的数据存储空间。而springboot提供了对市面上几乎所有的缓存技术进行整合的方案下面就一起开启springboot整合缓存之旅。
SpringBoot内置缓存解决方案
springboot技术提供有内置的缓存解决方案可以帮助开发者快速开启缓存技术并使用缓存技术进行数据的快速操作例如读取缓存数据和写入数据到缓存。
步骤①导入springboot提供的缓存技术对应的starter
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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(valuecacheSpace,key#id)public Book getById(Integer id) {return bookDao.selectById(id);}
} 在业务方法上面使用注解Cacheable声明当前方法的返回值放入缓存中其中要指定缓存的存储位置以及缓存中保存当前方法返回值对应的名称。上例中value属性描述缓存的存储位置可以理解为是一个存储空间名key属性描述了缓存中保存数据的名称使用#id读取形参中的id值作为缓存名称。
使用Cacheable注解后执行当前操作如果发现对应名称在缓存中没有数据就正常读取数据然后放入缓存如果对应名称在缓存中有数据就终止当前业务方法执行直接返回缓存中的数据。
手机验证码案例
为了便于下面演示各种各样的缓存技术我们创建一个手机验证码的案例环境模拟使用缓存保存手机验证码的过程。
手机验证码案例需求如下
输入手机号获取验证码组织文档以短信形式发送给用户页面模拟输入手机号和验证码验证结果
为了描述上述操作我们制作两个表现层接口一个用来模拟发送短信的过程其实就是根据用户提供的手机号生成一个验证码然后放入缓存另一个用来模拟验证码校验的过程其实就是使用传入的手机号和验证码进行匹配并返回最终匹配结果。下面直接制作本案例的模拟代码先以上例中springboot提供的内置缓存技术来完成当前案例的制作。
步骤①导入springboot提供的缓存技术对应的starter
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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缓存
手机验证码的案例已经完成了下面就开始springboot整合各种各样的缓存技术第一个整合Ehcache技术。Ehcache是一种缓存技术使用springboot整合Ehcache其实就是变更一下缓存技术的实现方式话不多说直接开整
步骤①导入Ehcache的坐标
dependencygroupIdnet.sf.ehcache/groupIdartifactIdehcache/artifactId
/dependency 此处为什么不是导入Ehcache的starter而是导入技术坐标呢其实springboot整合缓存技术做的是通用格式不管你整合哪种缓存技术只是实现变化了操作方式一样。这也体现出springboot技术的优点统一同类技术的整合方式。
步骤②配置缓存技术实现使用Ehcache
spring:cache:type: ehcacheehcache:config: ehcache.xml 配置缓存的类型type为ehcache此处需要说明一下当前springboot可以整合的缓存技术中包含有ehcach所以可以这样书写。其实这个type不可以随便写的不是随便写一个名称就可以整合的。
由于ehcache的配置有独立的配置文件格式因此还需要指定ehcache的配置文件以便于读取相应配置
?xml version1.0 encodingUTF-8?
ehcache xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:noNamespaceSchemaLocationhttp://ehcache.org/ehcache.xsdupdateCheckfalsediskStore pathD:\ehcache /!--默认缓存策略 --!-- external是否永久存在设置为true则不会被清除此时与timeout冲突通常设置为false--!-- diskPersistent是否启用磁盘持久化--!-- maxElementsInMemory最大缓存数量--!-- overflowToDisk超过最大缓存数量是否持久化到磁盘--!-- timeToIdleSeconds最大不活动间隔设置过长缓存容易溢出设置过短无效果可用于记录时效性数据例如验证码--!-- timeToLiveSeconds最大存活时间--!-- memoryStoreEvictionPolicy缓存清除策略--defaultCacheeternalfalsediskPersistentfalsemaxElementsInMemory1000overflowToDiskfalsetimeToIdleSeconds60timeToLiveSeconds60memoryStoreEvictionPolicyLRU /cachenamesmsCodeeternalfalsediskPersistentfalsemaxElementsInMemory1000overflowToDiskfalsetimeToIdleSeconds10timeToLiveSeconds10memoryStoreEvictionPolicyLRU /
/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的坐标
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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总结
springboot使用redis作为缓存实现需要导入redis的坐标修改设置配置缓存供应商为redis并提供对应的缓存配置
SpringBoot整合Memcached缓存
目前我们已经掌握了3种缓存解决方案的配置形式分别是springboot内置缓存ehcache和redis本节研究一下国内比较流行的一款缓存memcached。
按照之前的套路其实变更缓存并不繁琐但是springboot并没有支持使用memcached作为其缓存解决方案也就是说在type属性中没有memcached的配置选项这里就需要更变一下处理方式了。在整合之前先安装memcached。
安装
windows版安装包下载地址https://www.runoob.com/memcached/window-install-memcached.html
下载的安装包是解压缩就能使用的zip文件解压缩完毕后会得到如下文件 可执行文件只有一个memcached.exe使用该文件可以将memcached作为系统服务启动执行此文件时会出现报错信息如下 此处出现问题的原因是注册系统服务时需要使用管理员权限当前账号权限不足导致安装服务失败切换管理员账号权限启动命令行 然后再次执行安装服务的命令即可如下
memcached.exe -d install 服务安装完毕后可以使用命令启动和停止服务如下
memcached.exe -d start # 启动服务
memcached.exe -d stop # 停止服务 也可以在任务管理器中进行服务状态的切换 变更缓存为Memcached
由于memcached未被springboot收录为缓存解决方案因此使用memcached需要通过手工硬编码的方式来使用于是前面的套路都不适用了需要自己写了。
memcached目前提供有三种客户端技术分别是Memcached Client for Java、SpyMemcached和Xmemcached其中性能指标各方面最好的客户端是Xmemcached本次整合就使用这个作为客户端实现技术了。下面开始使用Xmemcached
步骤①导入xmemcached的坐标
dependencygroupIdcom.googlecode.xmemcached/groupIdartifactIdxmemcached/artifactIdversion2.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操作其实更符合我们开发者的习惯。
上述代码中对于服务器的配置使用硬编码写死到了代码中将此数据提取出来做成独立的配置属性。
定义配置属性
以下过程采用前期学习的属性配置方式进行当前操作有助于理解原理篇中的很多知识。 定义配置类加载必要的配置属性读取配置文件中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;}
}总结
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支持的缓存方案本地缓存支持两种远程缓存支持两种分别如下
本地缓存Local LinkedHashMapCaffeine 远程缓存Remote RedisTair
其实也有人问我为什么jetcache只支持22这么4款缓存呢阿里研发这个技术其实主要是为了满足自身的使用需要。最初肯定只有11种逐步变化成22种。下面就以LinkedHashMapRedis的方案实现本地与远程缓存方案同时使用。
纯远程方案
步骤①导入springboot整合jetcache对应的坐标starter当前坐标默认使用的远程方案是redis
dependencygroupIdcom.alicp.jetcache/groupIdartifactIdjetcache-starter-redis/artifactIdversion2.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(namejetCache_,expire 10,timeUnit TimeUnit.SECONDS)private CacheString ,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(areasms,namejetCache_,expire 10,timeUnit TimeUnit.SECONDS)private CacheString ,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);}
}纯本地方案
远程方案中配置中使用remote表示远程换成local就是本地只不过类型不一样而已。
步骤①导入springboot整合jetcache对应的坐标starter
dependencygroupIdcom.alicp.jetcache/groupIdartifactIdjetcache-starter-redis/artifactIdversion2.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(namejetCache_,expire 1000,timeUnit TimeUnit.SECONDS,cacheType CacheType.LOCAL)private CacheString ,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控制当前缓存使用本地缓存还是远程缓存配置cacheTypeCacheType.LOCAL即使用本地缓存。
本地远程方案
本地和远程方法都有了两种方案一起使用如何配置呢其实就是将两种配置合并到一起就可以了。
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(namejetCache_,expire 1000,timeUnit TimeUnit.SECONDS,cacheType CacheType.BOTH)private CacheString ,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
dependencygroupIdcom.alicp.jetcache/groupIdartifactIdjetcache-starter-redis/artifactIdversion2.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.itheima)
public class Springboot20JetCacheApplication {public static void main(String[] args) {SpringApplication.run(Springboot20JetCacheApplication.class, args);}
}步骤④使用注解Cached标注当前方法使用缓存
Service
public class BookServiceImpl implements BookService {Autowiredprivate BookDao bookDao;OverrideCached(namebook_,key#id,expire 3600,cacheType CacheType.REMOTE)public Book getById(Integer id) {return bookDao.selectById(id);}
}远程方案的数据同步
由于远程方案中redis保存的数据可以被多个客户端共享这就存在了数据同步问题。jetcache提供了3个注解解决此问题分别在更新、删除操作时同步缓存数据和读取缓存时定时刷新数据
更新缓存
CacheUpdate(namebook_,key#book.id,value#book)
public boolean update(Book book) {return bookDao.updateById(book) 0;
}删除缓存
CacheInvalidate(namebook_,key #id)
public boolean delete(Integer id) {return bookDao.deleteById(id) 0;
}定时刷新缓存
Cached(namebook_,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坐标
dependencygroupIdnet.oschina.j2cache/groupIdartifactIdj2cache-core/artifactIdversion2.8.4-release/version
/dependency
dependencygroupIdnet.oschina.j2cache/groupIdartifactIdj2cache-spring-boot2-starter/artifactIdversion2.8.0-release/version
/dependency
dependencygroupIdnet.sf.ehcache/groupIdartifactIdehcache/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 jgroupss 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 - dont 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 12 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 isnt 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 fsts 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:password127.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:password127.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总结
j2cache是一个缓存框架自身不具有缓存功能它提供多种缓存整合在一起使用的方案j2cache需要通过复杂的配置设置各级缓存以及缓存之间数据交换的方式j2cache操作接口通过CacheChannel实现
往期专栏Java全栈开发数据结构与算法计算机组成原理操作系统数据库系统物联网控制原理与技术