摘要:中有兩個(gè)接口能實(shí)現(xiàn)該功能和。首先了解一下的基本用法,可以在系統(tǒng)啟動(dòng)后執(zhí)行里面的方法執(zhí)行數(shù)據(jù)初始化如果有多個(gè)類的話也可以通過(guò)注解指定每個(gè)類的執(zhí)行順序。
最近遇到一個(gè)功能點(diǎn),數(shù)據(jù)庫(kù)中一張很簡(jiǎn)單的表有一千多條數(shù)據(jù),這里的數(shù)據(jù)主要做到了值域映射的作用,簡(jiǎn)單來(lái)講就是我可以通過(guò)中文名拿到數(shù)據(jù)庫(kù)中對(duì)應(yīng)的code值。原本的實(shí)現(xiàn)方式是每次用到之后去查一次sql,雖然不會(huì)有什么問(wèn)題,但是只要是走了網(wǎng)絡(luò)io,都會(huì)消耗時(shí)間。所以這個(gè)方案需要想辦法優(yōu)化。
優(yōu)化的方式其實(shí)很簡(jiǎn)單,數(shù)據(jù)量不多,一千多條數(shù)據(jù)放在內(nèi)存里也占不了多少空間。因此完全可以把一次性把數(shù)據(jù)加載到內(nèi)存中,后面只需要每次去內(nèi)存里調(diào)用就可以了。
方案想好了就要想實(shí)現(xiàn)方式了,想個(gè)最直接的方案,在Spring容器初始化時(shí)就把這些數(shù)據(jù)從數(shù)據(jù)庫(kù)拿到內(nèi)存中,后面就直接調(diào)用。
SpringBoot中有兩個(gè)接口能實(shí)現(xiàn)該功能:CommandLineRunner和ApplicationRunner。
首先了解一下CommandLineRunner的基本用法,CommandLineRunner可以在系統(tǒng)啟動(dòng)后執(zhí)行里面的run方法
@Componentpublic class DataPrepare implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("CommandLineRunner執(zhí)行數(shù)據(jù)初始化"); }}
如果有多個(gè)類的話也可以通過(guò)@Order注解指定每個(gè)類的執(zhí)行順序。
接著就可以寫(xiě)代碼的實(shí)現(xiàn)了,首先定義一個(gè)類用來(lái)將Mysql的數(shù)據(jù)存到內(nèi)存里,通過(guò)靜態(tài)的Map存儲(chǔ)
public class DataMap { public static Map<String, String> map = new HashMap<>(); public static void putData(String key, String value) { map.put(key, value); } public static String getDataByKey(String key) { return map.get(key); }}
接著在DataPrepare類中將數(shù)據(jù)都存入到靜態(tài)到Map中。
@Componentpublic class DataPrepare implements CommandLineRunner { @Autowired private DataMapper dataMapper; @Override public void run(String... args) throws Exception { //從數(shù)據(jù)庫(kù)中取數(shù)據(jù) List<DataDO> dataDOS = dataMapper.selectList(Wrappers.emptyWrapper()); //寫(xiě)入到DataMap中 dataDOS.forEach(item -> DataMap.putData(item.getName(), item.getCode())); }}
要使用到時(shí)候,只需要調(diào)用DataMap.getDataByKey()方法就可以直接使用了。
ApplicationRunner和CommandLineRunner的功能十分相似,實(shí)現(xiàn)方式也基本相同。同樣繼承接口,并實(shí)現(xiàn)接口的run方法。
@Componentpublic class ApplicationDataPrepare implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunner執(zhí)行數(shù)據(jù)初始化"); }}
在不指定@Order注解的情況下,ApplicationRunner會(huì)優(yōu)先于CommandLineRunner執(zhí)行。
兩者的區(qū)別:
CommandLineRunner和ApplicationRunner的功能幾乎是相同的,最大的區(qū)別在于兩者run方法中的入?yún)⒂兴煌珻ommandLineRunner通過(guò)String數(shù)組
來(lái)接收啟動(dòng)參數(shù),而ApplicationRunner通過(guò)一個(gè)ApplicationArguments對(duì)象來(lái)接收。
在使用時(shí),不管是String數(shù)組還是ApplicationArguments都可以拿到JVM的啟動(dòng)參數(shù)。
為什么通過(guò)實(shí)現(xiàn)一個(gè)接口,重寫(xiě)run方法就能達(dá)到啟動(dòng)程序后就自動(dòng)執(zhí)行代碼的功能呢?我們可以通過(guò)SpringBoot的源碼去看:
點(diǎn)進(jìn)SpringApplication.run()方法,一直進(jìn)入到public ConfigurableApplicationContext run(String… args)方法中,在執(zhí)行完一系列初始化方法之后,執(zhí)行了this.callRunners(context, applicationArguments)方法
callRunners的方法比較簡(jiǎn)單,首先定義了一個(gè)runners集合,并將需要執(zhí)行的Bean放進(jìn)去。可以看到ApplicationRunner和CommandLineRunner在這里被放入了runners中,接著對(duì)Order注解進(jìn)行排序,最后遍歷執(zhí)行。
private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); Iterator var4 = (new LinkedHashSet(runners)).iterator(); while(var4.hasNext()) { Object runner = var4.next(); if (runner instanceof ApplicationRunner) { this.callRunner((ApplicationRunner)runner, args); } if (runner instanceof CommandLineRunner) { this.callRunner((CommandLineRunner)runner, args); } }}
一個(gè)小小的細(xì)節(jié)可以節(jié)約多次的Sql調(diào)用。本章主要通過(guò)一個(gè)簡(jiǎn)單的例子引出ApplicationRunner和CommandLineRunner,實(shí)際在使用時(shí)也可以通過(guò)懶加載,在第一次使用時(shí)將數(shù)據(jù)塞到靜態(tài)的Map里,也能實(shí)現(xiàn)類似緩存的效果。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/123719.html
摘要:文件服務(wù)器項(xiàng)目為文章共享社區(qū),少不了的就是一個(gè)存儲(chǔ)文章的文件服務(wù)器,包括存儲(chǔ)一些圖片之類的靜態(tài)資源。例如數(shù)據(jù)庫(kù)的數(shù)據(jù)文件的配置文件和文件服務(wù)器目錄。 前言 這是一次完整的項(xiàng)目實(shí)踐,Angular頁(yè)面+Springboot接口+MySQL都通過(guò)Dockerfile打包成docker鏡像,通過(guò)docker-compose做統(tǒng)一編排。目的是實(shí)現(xiàn)整個(gè)項(xiàng)目產(chǎn)品的輕量級(jí)和靈活性,在將各個(gè)模塊的鏡像...
摘要:除了,還有十余種,有的是特定操作,比如轉(zhuǎn)儲(chǔ)內(nèi)存日志有的是信息展示,比如顯示應(yīng)用健康狀態(tài)。 showImg(http://ww1.sinaimg.cn/large/006tNc79gy1g5qb2coyfoj30u00k0tan.jpg); 前言 隨著線上應(yīng)用逐步采用 SpringBoot 構(gòu)建,SpringBoot應(yīng)用實(shí)例越來(lái)多,當(dāng)線上某個(gè)應(yīng)用需要升級(jí)部署時(shí),常常簡(jiǎn)單粗暴地使用 kil...
摘要:熱加載代表的是我們不需要重啟服務(wù)器,就能夠類檢測(cè)得到,重新生成類的字節(jié)碼文件無(wú)論是熱部署或者是熱加載都是基于類加載器來(lái)完成的。驗(yàn)證階段字節(jié)碼文件不會(huì)對(duì)造成危害準(zhǔn)備階段是會(huì)賦初始值,并不是程序中的值。 一、SpringBoot入門 今天在慕課網(wǎng)中看見(jiàn)了Spring Boot這么一個(gè)教程,這個(gè)Spring Boot作為JavaWeb的學(xué)習(xí)者肯定至少會(huì)聽(tīng)過(guò),但我是不知道他是什么玩意。 只是大...
摘要:用戶態(tài)不能干擾內(nèi)核態(tài)所以指令就有兩種特權(quán)指令和非特權(quán)指令不同的狀態(tài)對(duì)應(yīng)不同的指令。非特權(quán)指令所有程序均可直接使用。用戶態(tài)常態(tài)目態(tài)執(zhí)行非特權(quán)指令。 這是我今年從三月份開(kāi)始,主要的大廠面試經(jīng)過(guò),有些企業(yè)面試的還沒(méi)來(lái)得及整理,可能有些沒(méi)有帶答案就發(fā)出來(lái)了,還請(qǐng)各位先思考如果是你怎么回答面試官?這篇文章會(huì)持續(xù)更新,請(qǐng)各位持續(xù)關(guān)注,希望對(duì)你有所幫助! 面試清單 平安產(chǎn)險(xiǎn) 飛豬 上汽大通 浩鯨科...
Github 地址:https://github.com/Snailclimb/springboot-integration-examples ,歡迎各位 Star。 目錄: 使用 SpringBoot+Dubbo 搭建一個(gè)簡(jiǎn)單分布式服務(wù) 實(shí)戰(zhàn)之前,先來(lái)看幾個(gè)重要的概念 什么是分布式? 什么是 Duboo? Dubbo 架構(gòu) 什么是 RPC? 為什么要用 Dubbo? 開(kāi)始實(shí)戰(zhàn) 1 ...
閱讀 1847·2021-11-23 09:51
閱讀 1307·2021-11-18 10:02
閱讀 977·2021-10-25 09:44
閱讀 2115·2019-08-26 18:36
閱讀 1635·2019-08-26 12:17
閱讀 1158·2019-08-26 11:59
閱讀 2756·2019-08-23 15:56
閱讀 3369·2019-08-23 15:05