一、SpringBoot整合jetcache缓存
目前我们使用的缓存都是要么A要么B,能不能AB一起用呢?这一节就解决这个问题。springboot针对缓存的整合仅仅停留在用缓存上面,如果缓存自身不支持同时支持AB一起用,springboot也没办法,所以要想解决AB缓存一起用的问题,就必须找一款缓存能够支持AB两种缓存一起用,有这种缓存吗?还真有,阿里出品,jetcache。
jetcache严格意义上来说,并不是一个缓存解决方案,只能说他算是一个缓存框架,然后把别的缓存放到jetcache中管理,这样就可以支持AB缓存一起用了。并且jetcache参考了springboot整合缓存的思想,整体技术使用方式和springboot的缓存解决方案思想非常类似。下面咱们就先把jetcache用起来,然后再说它里面的一些小的功能。
做之前要先明确一下,jetcache并不是随便拿两个缓存都能拼到一起去的。目前jetcache支持的缓存方案本地缓存支持两种,远程缓存支持两种,分别如下:
本地缓存(Local) LinkedHashMap Caffeine 远程缓存(Remote) Redis Tair
二、纯远程方案
步骤①:导入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); } }
三、纯本地方案
远程方案中,配置中使用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: 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即使用本地缓存。
四、本地+远程方案
本地和远程方法都有了,两种方案一起使用如何配置呢?其实就是将两种配置合并到一起就可以了。
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.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: 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提供有简单的缓存信息命中报表方便开发者即时监控缓存数据命中情况
五、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: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: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: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
总结
j2cache是一个缓存框架,自身不具有缓存功能,它提供多种缓存整合在一起使用的方案
j2cache需要通过复杂的配置设置各级缓存,以及缓存之间数据交换的方式
j2cache操作接口通过CacheChannel实现
六、Quartz任务技术
springboot整合第三方技术第二部分我们来说说任务系统,其实这里说的任务系统指的是定时任务。定时任务是企业级开发中必不可少的组成部分,诸如长周期业务数据的计算,例如年度报表,诸如系统脏数据的处理,再比如系统性能监控报告,还有抢购类活动的商品上架,这些都离不开定时任务。本节将介绍两种不同的定时任务技术。
Quartz
Quartz技术是一个比较成熟的定时任务框架,怎么说呢?有点繁琐,用过的都知道,配置略微复杂。springboot对其进行整合后,简化了一系列的配置,将很多配置采用默认设置,这样开发阶段就简化了很多。再学习springboot整合Quartz前先普及几个Quartz的概念。
工作(Job):用于定义具体执行的工作 工作明细(JobDetail):用于描述定时工作相关的信息 触发器(Trigger):描述了工作明细与调度器的对应关系 调度器(Scheduler):用于描述触发工作的执行规则,通常使用cron表达式定义规则
简单说就是你定时干什么事情,这就是工作,工作不可能就是一个简单的方法,还要设置一些明细信息。工作啥时候执行,设置一个调度器,可以简单理解成设置一个工作执行的时间。工作和调度都是独立定义的,它们两个怎么配合到一起呢?用触发器。完了,就这么多。下面开始springboot整合Quartz。
步骤①:导入springboot整合Quartz的starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
步骤②:定义任务Bean,按照Quartz的开发规范制作,继承QuartzJobBean
public class MyQuartz extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("quartz task run..."); } }
步骤③:创建Quartz配置类,定义工作明细(JobDetail)与触发器的(Trigger)bean
@Configuration public class QuartzConfig { @Bean public JobDetail printJobDetail(){ //绑定具体的工作 return JobBuilder.newJob(MyQuartz.class).storeDurably().build(); } @Bean public Trigger printJobTrigger(){ ScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?"); //绑定对应的工作明细 return TriggerBuilder.newTrigger().forJob(printJobDetail()).withSchedule(schedBuilder).build(); } }
工作明细中要设置对应的具体工作,使用newJob()操作传入对应的工作任务类型即可。
触发器需要绑定任务,使用forJob()操作传入绑定的工作明细对象。此处可以为工作明细设置名称然后使用名称绑定,也可以直接调用对应方法绑定。触发器中最核心的规则是执行时间,此处使用调度器定义执行时间,执行时间描述方式使用的是cron表达式。有关cron表达式的规则,各位小伙伴可以去参看相关课程学习,略微复杂,而且格式不能乱设置,不是写个格式就能用的,写不好就会出现冲突问题。
总结
springboot整合Quartz就是将Quartz对应的核心对象交给spring容器管理,包含两个对象,JobDetail和Trigger对象 JobDetail对象描述的是工作的执行信息,需要绑定一个QuartzJobBean类型的对象 Trigger对象定义了一个触发器,需要为其指定绑定的JobDetail是哪个,同时要设置执行周期调度器
七、SpringBoot整合Task
spring根据定时任务的特征,将定时任务的开发简化到了极致。怎么说呢?要做定时任务总要告诉容器有这功能吧,然后定时执行什么任务直接告诉对应的bean什么时间执行就行了,就这么简单,一起来看怎么做
步骤①:开启定时任务功能,在引导类上开启定时任务功能的开关,使用注解@EnableScheduling
@SpringBootApplication //开启定时任务功能 @EnableScheduling public class Springboot22TaskApplication { public static void main(String[] args) { SpringApplication.run(Springboot22TaskApplication.class, args); } }
步骤②:定义Bean,在对应要定时执行的操作上方,使用注解@Scheduled定义执行的时间,执行时间的描述方式还是cron表达式
@Component public class MyBean { @Scheduled(cron = "0/1 * * * * ?") public void print(){ System.out.println(Thread.currentThread().getName()+" :spring task run..."); } }
完事,这就完成了定时任务的配置。总体感觉其实什么东西都没少,只不过没有将所有的信息都抽取成bean,而是直接使用注解绑定定时执行任务的事情而已。
如何想对定时任务进行相关配置,可以通过配置文件进行
spring: task: scheduling: pool: size: 1 # 任务调度线程池大小 默认 1 thread-name-prefix: ssm_ # 调度线程名称前缀 默认 scheduling- shutdown: await-termination: false # 线程池关闭时等待所有任务完成 await-termination-period: 10s # 调度线程关闭前最大等待时间,确保最后一定关闭