国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

手動(dòng)部署jar包,太low了!動(dòng)態(tài)上傳包熱部署,真爽!

0
分享至

Java精選面試題(微信小程序):5000+道面試題和選擇題,包含Java基礎(chǔ)、并發(fā)、JVM、線程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架構(gòu)設(shè)計(jì)、大廠真題等,在線隨時(shí)刷題!

近期開發(fā)系統(tǒng)過程中遇到的一個(gè)需求,系統(tǒng)給定一個(gè)接口,用戶可以自定義開發(fā)該接口的實(shí)現(xiàn),并將實(shí)現(xiàn)打成jar包,上傳到系統(tǒng)中。系統(tǒng)完成熱部署,并切換該接口的實(shí)現(xiàn)。

定義簡(jiǎn)單的接口

這里以一個(gè)簡(jiǎn)單的計(jì)算器功能為例,接口定義比較簡(jiǎn)單,直接上代碼。

public interface Calculator {     int calculate(int a, int b);     int add(int a, int b); }
該接口的一個(gè)簡(jiǎn)單的實(shí)現(xiàn)

考慮到用戶實(shí)現(xiàn)接口的兩種方式,使用spring上下文管理的方式,或者不依賴spring管理的方式,這里稱它們?yōu)樽⒔夥绞胶头瓷浞绞健?code>calculate方法對(duì)應(yīng)注解方式,add方法對(duì)應(yīng)反射方式。計(jì)算器接口實(shí)現(xiàn)類的代碼如下:

@Service publicclass CalculatorImpl implements Calculator {     @Autowired     CalculatorCore calculatorCore;     /**      * 注解方式      */     @Override     public int calculate(int a, int b) {         int c = calculatorCore.add(a, b);         return c;     }     /**      * 反射方式      */     @Override     public int add(int a, int b) {         returnnew CalculatorCore().add(a, b);     } }

這里注入CalculatorCore的目的是為了驗(yàn)證在注解模式下,系統(tǒng)可以完整的構(gòu)造出bean的依賴體系,并注冊(cè)到當(dāng)前spring容器中。CalculatorCore的代碼如下:

@Service public class CalculatorCore {     public int add(int a, int b) {         return a+b;     } }
反射方式熱部署

用戶把jar包上傳到系統(tǒng)的指定目錄下,這里定義上傳jar文件路徑為jarAddress,jar的Url路徑為jarPath。

private static String jarAddress = "E:/zzq/IDEA_WS/CalculatorTest/lib/Calculator.jar"; private static String jarPath = "file:/" + jarAddress;

并且可以要求用戶填寫jar包中接口實(shí)現(xiàn)類的完整類名。接下來系統(tǒng)要把上傳的jar包加載到當(dāng)前線程的類加載器中,然后通過完整類名,加載得到該實(shí)現(xiàn)的Class對(duì)象。然后反射調(diào)用即可,完整代碼:

/**  * 熱加載Calculator接口的實(shí)現(xiàn) 反射方式,公眾號(hào)Java精選  */ public static void hotDeployWithReflect() throws Exception {     URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL(jarPath)}, Thread.currentThread().getContextClassLoader());     Class clazz = urlClassLoader.loadClass("com.nci.cetc15.calculator.impl.CalculatorImpl");     Calculator calculator = (Calculator) clazz.newInstance();     int result = calculator.add(1, 2);     System.out.println(result); }
注解方式熱部署

如果用戶上傳的jar包含了spring的上下文,那么就需要掃描jar包里的所有需要注入spring容器的bean,注冊(cè)到當(dāng)前系統(tǒng)的spring容器中。其實(shí),這就是一個(gè)類的熱加載+動(dòng)態(tài)注冊(cè)的過程。

直接上代碼:

/**  * 加入jar包后 動(dòng)態(tài)注冊(cè)bean到spring容器,包括bean的依賴  */ public static void hotDeployWithSpring() throws Exception {     Set classNameSet = DeployUtils.readJarFile(jarAddress);     URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL(jarPath)}, Thread.currentThread().getContextClassLoader());     for (String className : classNameSet) {         Class clazz = urlClassLoader.loadClass(className);         if (DeployUtils.isSpringBeanClass(clazz)) {             BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);             defaultListableBeanFactory.registerBeanDefinition(DeployUtils.transformName(className), beanDefinitionBuilder.getBeanDefinition());         }     } }

在這個(gè)過程中,將jar加載到當(dāng)前線程類加載器的過程和之前反射方式是一樣的。然后掃描jar包下所有的類文件,獲取到完整類名,并使用當(dāng)前線程類加載器加載出該類名對(duì)應(yīng)的class對(duì)象。判斷該class對(duì)象是否帶有spring的注解,如果包含,則將該對(duì)象注冊(cè)到系統(tǒng)的spring容器中。

DeployUtils包含讀取jar包所有類文件的方法、判斷class對(duì)象是否包含sping注解的方法、獲取注冊(cè)對(duì)象對(duì)象名的方法。代碼如下:

/**  * 讀取jar包中所有類文件  */ public static Set   readJarFile(String jarAddress) throws IOException {     Set classNameSet =  new HashSet<>();     JarFile jarFile = new JarFile(jarAddress);     Enumeration entries = jarFile.entries(); //遍歷整個(gè)jar文件     while (entries.hasMoreElements()) {         JarEntry jarEntry = entries.nextElement();         String name = jarEntry.getName();         if (name.endsWith(".class")) {             String className = name.replace(".class", "").replaceAll("/", ".");             classNameSet.add(className);         }     }     return classNameSet; }

/**  * 方法描述 判斷class對(duì)象是否帶有spring的注解  */ public static boolean isSpringBeanClass(Class cla) {     if (cla == null) {         returnfalse;     }     //是否是接口     if (cla.isInterface()) {         returnfalse;     }     //是否是抽象類     if (Modifier.isAbstract(cla.getModifiers())) {         returnfalse;     }     if (cla.getAnnotation(Component.class) != null) {         returntrue;     }     if (cla.getAnnotation(Repository.class) != null) {         returntrue;     }     if (cla.getAnnotation(Service.class) != null) {         returntrue;     }     returnfalse; }

/**  * 類名首字母小寫 作為spring容器beanMap的key  */ public static String transformName(String className) {     String tmpstr = className.substring(className.lastIndexOf(".") + 1);     return tmpstr.substring(0, 1).toLowerCase() + tmpstr.substring(1); }
刪除jar時(shí),需要同時(shí)刪除spring容器中注冊(cè)的bean

在jar包切換或刪除時(shí),需要將之前注冊(cè)到spring容器的bean刪除。spring容器的bean的刪除操作和注冊(cè)操作是相逆的過程,這里要注意使用同一個(gè)spring上下文。

代碼如下:

/**  * 刪除jar包時(shí) 需要在spring容器刪除注入  */ public static void delete() throws Exception {     Set classNameSet = DeployUtils.readJarFile(jarAddress);     URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL(jarPath)}, Thread.currentThread().getContextClassLoader());     for (String className : classNameSet) {         Class clazz = urlClassLoader.loadClass(className);         if (DeployUtils.isSpringBeanClass(clazz)) {             defaultListableBeanFactory.removeBeanDefinition(DeployUtils.transformName(className));         }     } }
測(cè)試

測(cè)試類手動(dòng)模擬用戶上傳jar的功能。測(cè)試函數(shù)寫了個(gè)死循環(huán),一開始沒有找到j(luò)ar會(huì)拋出異常,捕獲該異常并睡眠10秒。這時(shí)候可以把jar手動(dòng)放到指定的目錄下。

代碼如下:

 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");     DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();     while (true) {         try {               hotDeployWithReflect(); //            hotDeployWithSpring(); //            delete();             } catch (Exception e) {                 e.printStackTrace();                 Thread.sleep(1000 * 10);             }         }

作者:zhangzhiqiang_0912

https://blog.csdn.net/zhangzhiqiang_0912

公眾號(hào)“Java精選”所發(fā)表內(nèi)容注明來源的,版權(quán)歸原出處所有(無法查證版權(quán)的或者未注明出處的均來自網(wǎng)絡(luò),系轉(zhuǎn)載,轉(zhuǎn)載的目的在于傳遞更多信息,版權(quán)屬于原作者。如有侵權(quán),請(qǐng)聯(lián)系,筆者會(huì)第一時(shí)間刪除處理!

最近有很多人問,有沒有讀者交流群!加入方式很簡(jiǎn)單,公眾號(hào)Java精選,回復(fù)“加群”,即可入群!

文章有幫助的話,點(diǎn)在看,轉(zhuǎn)發(fā)吧!

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
被曝生下畸形兒傳聞僅1月,闞清子官宣喜訊,連發(fā)三文表明態(tài)度

被曝生下畸形兒傳聞僅1月,闞清子官宣喜訊,連發(fā)三文表明態(tài)度

一口娛樂
2026-01-29 09:31:09
已確認(rèn),浙江有大到暴雪!今晚變天

已確認(rèn),浙江有大到暴雪!今晚變天

魯中晨報(bào)
2026-01-29 13:39:09
不敢置信!女子十二樂坊成員直播養(yǎng)不活自己,一晚上打賞不到3000

不敢置信!女子十二樂坊成員直播養(yǎng)不活自己,一晚上打賞不到3000

云中浮生
2026-01-24 21:37:46
奇葩!35歲女子4年不回家,母親來探望卻被懟,女子:就當(dāng)我死了

奇葩!35歲女子4年不回家,母親來探望卻被懟,女子:就當(dāng)我死了

娛樂帝皇丸
2026-01-28 15:18:51
16歲武漢男生凌晨離家,失聯(lián)超70小時(shí), 父親:未帶手機(jī)現(xiàn)金,最后出現(xiàn)在橋上不見蹤跡

16歲武漢男生凌晨離家,失聯(lián)超70小時(shí), 父親:未帶手機(jī)現(xiàn)金,最后出現(xiàn)在橋上不見蹤跡

大風(fēng)新聞
2026-01-29 13:53:22
人民日?qǐng)?bào)怒批!炫富、偷稅749萬、跑國(guó)外,現(xiàn)又來“割內(nèi)地韭菜”

人民日?qǐng)?bào)怒批!炫富、偷稅749萬、跑國(guó)外,現(xiàn)又來“割內(nèi)地韭菜”

小熊侃史
2026-01-18 07:20:09
港股地產(chǎn)股大漲,融創(chuàng)中國(guó)漲超30%

港股地產(chǎn)股大漲,融創(chuàng)中國(guó)漲超30%

每日經(jīng)濟(jì)新聞
2026-01-29 11:39:06
外交部:繼續(xù)深化國(guó)際執(zhí)法合作 加大力度打擊網(wǎng)賭電詐

外交部:繼續(xù)深化國(guó)際執(zhí)法合作 加大力度打擊網(wǎng)賭電詐

財(cái)聯(lián)社
2026-01-29 15:26:24
尼帕病毒來勢(shì)洶洶,建議:每家最好備6樣?xùn)|西,關(guān)鍵時(shí)刻能救命呢

尼帕病毒來勢(shì)洶洶,建議:每家最好備6樣?xùn)|西,關(guān)鍵時(shí)刻能救命呢

現(xiàn)代小青青慕慕
2026-01-28 08:59:53
阿富汗的鍋,拜登不背!

阿富汗的鍋,拜登不背!

山河路口
2026-01-28 23:12:39
心理學(xué)上有一個(gè)詞叫:梅拉賓法則(搞好人際關(guān)系最好的辦法)

心理學(xué)上有一個(gè)詞叫:梅拉賓法則(搞好人際關(guān)系最好的辦法)

經(jīng)濟(jì)觀察報(bào)
2025-09-01 10:06:25
1971年,劉思齊蒙冤入獄后向毛主席求助,毛澤東作出:娃娃們無罪

1971年,劉思齊蒙冤入獄后向毛主席求助,毛澤東作出:娃娃們無罪

史海孤雁
2026-01-27 18:02:17
瞞不住了!美媒:美軍高官已進(jìn)臺(tái)島指揮導(dǎo)彈戰(zhàn),戰(zhàn)時(shí)先炸福建沿海

瞞不住了!美媒:美軍高官已進(jìn)臺(tái)島指揮導(dǎo)彈戰(zhàn),戰(zhàn)時(shí)先炸福建沿海

史智文道
2026-01-29 16:14:14
要打就打痛!中國(guó)手段已升級(jí),日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

要打就打痛!中國(guó)手段已升級(jí),日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

通文知史
2026-01-28 14:30:03
太頂了!明明什么都沒露,卻性感得要命!

太頂了!明明什么都沒露,卻性感得要命!

貴圈真亂
2025-12-20 12:02:06
最新傷勢(shì)情況曝光,德約科維奇直言:對(duì)辛納絕不舉白旗

最新傷勢(shì)情況曝光,德約科維奇直言:對(duì)辛納絕不舉白旗

體育妞世界
2026-01-29 12:38:11
起風(fēng)了!加拿大已改口,禁止與中國(guó)簽協(xié)定,65萬噸油菜籽白買了?

起風(fēng)了!加拿大已改口,禁止與中國(guó)簽協(xié)定,65萬噸油菜籽白買了?

墨印齋
2026-01-29 11:47:54
加快男性衰老的因素:喝酒僅第5,排在第1的,很多男性還沒發(fā)現(xiàn)!

加快男性衰老的因素:喝酒僅第5,排在第1的,很多男性還沒發(fā)現(xiàn)!

醫(yī)學(xué)科普匯
2026-01-27 10:41:31
中國(guó)人一年少買了10萬輛進(jìn)口寶馬

中國(guó)人一年少買了10萬輛進(jìn)口寶馬

第一財(cái)經(jīng)資訊
2026-01-29 10:34:13
1973年,毛主席問楊振寧:萬壽無疆科學(xué)嗎?楊振寧的回答,讓主席笑了

1973年,毛主席問楊振寧:萬壽無疆科學(xué)嗎?楊振寧的回答,讓主席笑了

寄史言志
2026-01-24 17:53:13
2026-01-29 17:15:00
Java精選
Java精選
一場(chǎng)永遠(yuǎn)也演不完的戲
1768文章數(shù) 3859關(guān)注度
往期回顧 全部

科技要聞

周亞輝的AI新賭局:國(guó)內(nèi)太卷 出海另起爐灶

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

體育要聞

詹姆斯哭了!騎士視頻致敬41歲超巨

娛樂要聞

張譯不再隱瞞!公開回應(yīng)退圈息影真相

財(cái)經(jīng)要聞

崔東樹:中國(guó)汽車未來年銷或達(dá)5000萬輛

汽車要聞

車長(zhǎng)超5米還帶后輪轉(zhuǎn)向 比亞迪海豹08/海獅08將亮相

態(tài)度原創(chuàng)

房產(chǎn)
家居
手機(jī)
數(shù)碼
時(shí)尚

房產(chǎn)要聞

萬科難眠夜:前董事長(zhǎng)郁亮失聯(lián),三筆債券靠深鐵才通過展期

家居要聞

極簡(jiǎn)輕奢 家的無限可能

手機(jī)要聞

游戲直播神器!iQOO 15 Ultra支持一鍵投屏 開播0門檻

數(shù)碼要聞

這種電熱水袋國(guó)家早已禁售:別再用了

冬天大衣怎么穿才更好看?選好顏色、找對(duì)單品,高級(jí)簡(jiǎn)約又大氣

無障礙瀏覽 進(jìn)入關(guān)懷版