SpringBoot程序预装载数据怎么实现
这篇文章主要介绍“SpringBoot程序预装载数据怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringBoot程序预装载数据怎么实现”文章能帮助大家解决问题。
简介
在项目实际的开发过程中,有时候会遇到需要在应用程序启动完毕对外提供服务之前预先将部分数据装载到缓存的需求。
适用场景
预装载应用级别数据到缓存:如字典数据、公共的业务数据
系统预热
心跳检测:如在系统启动完毕访问一个外服务接口等场景
常用方法
ApplicationEvent
CommandLineRunner
ApplicationRunner
ApplicationEvent
应用程序事件,就是发布订阅模式。在系统启动完毕,向应用程序注册一个事件,监听者一旦监听到了事件的发布,就可以做一些业务逻辑的处理了。
既然是发布-订阅模式,那么订阅者既可以是一个,也可以是多个。
定义event
import org.springframework.context.ApplicationEvent;public class CacheEvent extends ApplicationEvent { public CacheEvent(Object source) { super(source); }}
定义listener
import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.util.List;import java.util.Map;import java.util.stream.Collectors;@Slf4j@Componentpublic class CacheEventListener implements ApplicationListener<CacheEvent> { @Autowired private MaskingService maskingService; @Autowired private RedisCache redisCache; @Override public void onApplicationEvent(CacheEvent cacheEvent) { log.debug("CacheEventListener-start"); List<SysMasking> maskings = maskingService.selectAllSysMaskings(); if (!CollectionUtils.isEmpty(maskings)) { log.debug("CacheEventListener-data-not-empty"); Map<String, List<SysMasking>> cacheMap = maskings.stream().collect(Collectors.groupingBy(SysMasking::getFieldKey)); cacheMap.keySet().forEach(x -> { if (StringUtils.isNotEmpty(x)) { log.debug("CacheEventListener-x={}", x); List<SysMasking> list = cacheMap.get(x); long count = redisCache.setCacheList(RedisKeyPrefix.MASKING.getPrefix() + x, list); log.debug("CacheEventListener-count={}", count); } else { log.debug("CacheEventListener-x-is-empty"); } }); } else { log.debug("CacheEventListener-data-is-empty"); } log.debug("CacheEventListener-end"); }}
注册event
@Slf4j@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class BAMSApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BAMSApplication.class, args); log.debug("app-started"); context.publishEvent(new CacheEvent("处理缓存事件")); }}
CommandLineRunner
通过实现 CommandLineRunner 接口,可以在应用程序启动完毕,回调到指定的方法中。
package com.ramble.warmupservice.runner;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;@Slf4j@Componentpublic class CacheCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { log.debug("CacheCommandLineRunner-start"); log.debug("CacheCommandLineRunner-参数={}", args); // 注入业务 service ,获取需要缓存的数据 // 注入 redisTemplate ,将需要缓存的数据存放到 redis 中 log.debug("CacheCommandLineRunner-end"); }}
ApplicationRunner
同CommandLineRunner 类似,区别在于,对参数做了封装。
package com.ramble.warmupservice.runner;import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.ApplicationArguments;import org.springframework.boot.ApplicationRunner;import org.springframework.stereotype.Component;@Slf4j@Componentpublic class CacheApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { log.debug("CacheApplicationRunner-start"); log.debug("CacheApplicationRunner-参数={}", JSON.toJSONString(args)); // 注入业务 service ,获取需要缓存的数据 // 注入 redisTemplate ,将需要缓存的数据存放到 redis 中 log.debug("CacheApplicationRunner-end"); }}
测试
上述代码在idea中启动,若不带参数,输出如下:
2022-04-28 15:44:00.981 INFO 1160 --- [ main] c.r.w.WarmupServiceApplication : Started WarmupServiceApplication in 1.335 seconds (JVM running for 2.231)
2022-04-28 15:44:00.982 DEBUG 1160 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-start
2022-04-28 15:44:01.025 DEBUG 1160 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-参数={"nonOptionArgs":[],"optionNames":[],"sourceArgs":[]}
2022-04-28 15:44:01.025 DEBUG 1160 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-end
2022-04-28 15:44:01.025 DEBUG 1160 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-start
2022-04-28 15:44:01.026 DEBUG 1160 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-参数={}
2022-04-28 15:44:01.026 DEBUG 1160 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-end
2022-04-28 15:44:01.026 DEBUG 1160 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener-start
2022-04-28 15:44:01.026 DEBUG 1160 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener-参数=ApplicationEvent-->缓存系统数据
2022-04-28 15:44:01.029 DEBUG 1160 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener-end
Disconnected from the target VM, address: '127.0.0.1:61320', transport: 'socket'
Process finished with exit code 130
若使用 java -jar xxx.jar --server.port=9009 启动,则输入如下:
2022-04-28 16:02:05.327 INFO 9916 --- [ main] c.r.w.WarmupServiceApplication : Started WarmupServiceApplication in 1.78 seconds (JVM running for 2.116)
2022-04-28 16:02:05.329 DEBUG 9916 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-start
2022-04-28 16:02:05.393 DEBUG 9916 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-参数={"nonOptionArgs":[],"optionNames":["server.port"],"sourceArgs":["--server.port=9009"]}
2022-04-28 16:02:05.395 DEBUG 9916 --- [ main] c.r.w.runner.CacheApplicationRunner : CacheApplicationRunner-end
2022-04-28 16:02:05.395 DEBUG 9916 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-start
2022-04-28 16:02:05.395 DEBUG 9916 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-参数=--server.port=9009
2022-04-28 16:02:05.395 DEBUG 9916 --- [ main] c.r.w.runner.CacheCommandLineRunner : CacheCommandLineRunner-end
2022-04-28 16:02:05.395 DEBUG 9916 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener-start
2022-04-28 16:02:05.396 DEBUG 9916 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener- 参数=ApplicationEvent-->缓存系统数据
2022-04-28 16:02:05.396 DEBUG 9916 --- [ main] c.r.w.listener.CacheEventListener : CacheEventListener-end
执行顺序
从上面测试的输出,可以看到三种方式执行的顺序为:
ApplicationRunner--->CommandLineRunner--->ApplicationEvent
另外,若同时定义多个runner,可以通过order来指定他们的优先级。
关于“SpringBoot程序预装载数据怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341