国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何實現動態上傳jar包熱部署

Android編程精選 ? 來源:CSDN技術社區 ? 作者:zhangzhiqiang_0912 ? 2022-06-20 16:57 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

近期開發系統過程中遇到的一個需求,系統給定一個接口,用戶可以自定義開發該接口的實現,并將實現打成jar包,上傳到系統中。系統完成熱部署,并切換該接口的實現。

定義簡單的接口

這里以一個簡單的計算器功能為例,接口定義比較簡單,直接上代碼。

publicinterfaceCalculator{
intcalculate(inta,intb);
intadd(inta,intb);
}

該接口的一個簡單的實現

考慮到用戶實現接口的兩種方式,使用spring上下文管理的方式,或者不依賴spring管理的方式,這里稱它們為注解方式和反射方式。calculate方法對應注解方式,add方法對應反射方式。計算器接口實現類的代碼如下:

@Service
publicclassCalculatorImplimplementsCalculator{
@Autowired
CalculatorCorecalculatorCore;
/**
*注解方式
*/
@Override
publicintcalculate(inta,intb){
intc=calculatorCore.add(a,b);
returnc;
}
/**
*反射方式
*/
@Override
publicintadd(inta,intb){
returnnewCalculatorCore().add(a,b);
}
}

這里注入CalculatorCore的目的是為了驗證在注解模式下,系統可以完整的構造出bean的依賴體系,并注冊到當前spring容器中。CalculatorCore的代碼如下:

@Service
publicclassCalculatorCore{
publicintadd(inta,intb){
returna+b;
}
}

反射方式熱部署

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

privatestaticStringjarAddress="E:/zzq/IDEA_WS/CalculatorTest/lib/Calculator.jar";
privatestaticStringjarPath="file:/"+jarAddress;

并且可以要求用戶填寫jar包中接口實現類的完整類名。接下來系統要把上傳的jar包加載到當前線程的類加載器中,然后通過完整類名,加載得到該實現的Class對象。然后反射調用即可,完整代碼:

/**
*熱加載Calculator接口的實現反射方式
*/
publicstaticvoidhotDeployWithReflect()throwsException{
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
Classclazz=urlClassLoader.loadClass("com.nci.cetc15.calculator.impl.CalculatorImpl");
Calculatorcalculator=(Calculator)clazz.newInstance();
intresult=calculator.add(1,2);
System.out.println(result);
}

注解方式熱部署

如果用戶上傳的jar包含了spring的上下文,那么就需要掃描jar包里的所有需要注入spring容器的bean,注冊到當前系統的spring容器中。其實,這就是一個類的熱加載+動態注冊的過程。

直接上代碼:

/**
*加入jar包后動態注冊bean到spring容器,包括bean的依賴
*/
publicstaticvoidhotDeployWithSpring()throwsException{
SetclassNameSet=DeployUtils.readJarFile(jarAddress);
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
for(StringclassName:classNameSet){
Classclazz=urlClassLoader.loadClass(className);
if(DeployUtils.isSpringBeanClass(clazz)){
BeanDefinitionBuilderbeanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(clazz);
defaultListableBeanFactory.registerBeanDefinition(DeployUtils.transformName(className),beanDefinitionBuilder.getBeanDefinition());
}
}
}

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

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

/**
*讀取jar包中所有類文件
*/
publicstaticSetreadJarFile(StringjarAddress)throwsIOException{
SetclassNameSet=newHashSet<>();
JarFilejarFile=newJarFile(jarAddress);
Enumerationentries=jarFile.entries();//遍歷整個jar文件
while(entries.hasMoreElements()){
JarEntryjarEntry=entries.nextElement();
Stringname=jarEntry.getName();
if(name.endsWith(".class")){
StringclassName=name.replace(".class","").replaceAll("/",".");
classNameSet.add(className);
}
}
returnclassNameSet;
}
/**
*方法描述判斷class對象是否帶有spring的注解
*/
publicstaticbooleanisSpringBeanClass(Classcla){
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
*/
publicstaticStringtransformName(StringclassName){
Stringtmpstr=className.substring(className.lastIndexOf(".")+1);
returntmpstr.substring(0,1).toLowerCase()+tmpstr.substring(1);
}

刪除jar時,需要同時刪除spring容器中注冊的bean

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

代碼如下:

/**
*刪除jar包時需要在spring容器刪除注入
*/
publicstaticvoiddelete()throwsException{
SetclassNameSet=DeployUtils.readJarFile(jarAddress);
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
for(StringclassName:classNameSet){
Classclazz=urlClassLoader.loadClass(className);
if(DeployUtils.isSpringBeanClass(clazz)){
defaultListableBeanFactory.removeBeanDefinition(DeployUtils.transformName(className));
}
}
}

測試

測試類手動模擬用戶上傳jar的功能。測試函數寫了個死循環,一開始沒有找到jar會拋出異常,捕獲該異常并睡眠10秒。這時候可以把jar手動放到指定的目錄下。

代碼如下:

ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml");
DefaultListableBeanFactorydefaultListableBeanFactory=(DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
while(true){
try{
hotDeployWithReflect();
//hotDeployWithSpring();
//delete();
}catch(Exceptione){
e.printStackTrace();
Thread.sleep(1000*10);
}
}

		

					
						


																															

																															

																															

																																			

																																			

																																					

																																					

																																					

原文標題:求求你別再手動部署jar包了,太low了!動態上傳熱部署真的太爽了!

文章出處:【微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    9519

    瀏覽量

    157020
  • 開發系統
    +關注

    關注

    0

    文章

    39

    瀏覽量

    10293
  • spring
    +關注

    關注

    0

    文章

    341

    瀏覽量

    15935

原文標題:求求你別再手動部署jar包了,太low了!動態上傳熱部署真的太爽了!

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    RT-Thread Vector軟件:嵌入式開發的動態數組容器 | 技術集結

    RT-Thread Vector軟件:嵌入式開發的動態數組容器 | 技術集結
    的頭像 發表于 01-25 09:33 ?5375次閱讀
    RT-Thread Vector軟件<b class='flag-5'>包</b>:嵌入式開發的<b class='flag-5'>動態</b>數組容器 | 技術集結

    元服務發布選擇待發布軟件

    上傳軟件并通過基礎合法檢查后,就可以從上傳的版本中選擇需要發布的軟件。 登錄AppGallery Connect,點擊“APP與元服務”。 選擇要發布的元服務。 左側導航選擇“應用
    發表于 11-03 17:10

    商品圖片批量上傳接口設計與實現

    ? 在電商平臺或內容管理系統中,商品圖片的高效管理是核心需求之一。批量上傳接口允許用戶一次性上傳多張圖片,顯著提升操作效率。本文將逐步介紹如何設計并實現一個可靠的商品圖片批量上傳接口,
    的頭像 發表于 10-13 15:25 ?444次閱讀

    產品圖片上傳API接口

    ? 在電商平臺、內容管理系統或移動應用中,產品圖片上傳API接口是核心功能之一。它允許用戶或第三方應用通過HTTP請求將圖片文件上傳到服務器,實現產品圖像的快速添加和管理。本文將逐步介紹該接口
    的頭像 發表于 07-25 14:30 ?682次閱讀
    產品圖片<b class='flag-5'>上傳</b>API接口

    上傳壓縮的時候總是顯示上傳失敗,為什么?

    上傳壓縮的時候總是顯示上傳失敗是說明原因
    發表于 07-23 08:17

    ocr識別時數據集上傳壓縮上傳成功,但不顯示圖片,圖片數量仍顯示0,為什么?

    ocr識別時數據集上傳壓縮上傳成功,但不顯示圖片,圖片數量仍顯示0
    發表于 07-23 08:11

    動態BGP與靜態BGP的區別?

    BGP(邊界網關協議,Border Gateway Protocol) 是互聯網中用于自治系統(AS)之間路由信息交換的核心協議。在實際部署中,BGP 可分為靜態 BGP和動態 BGP兩種方式,二者
    發表于 06-24 06:57

    ?數字孿生熱管理:NTC熱敏電阻陣列與場重構算法的動態適配

    本文以東莞市平尚電子科技有限公司(平尚科技)的NTC熱敏電阻陣列與場重構算法為核心,探討其在車載數字孿生熱管理系統中的動態適配技術。通過高精度NTC陣列、多物理場耦合模型及實時反饋控制算法,實現
    的頭像 發表于 06-06 17:59 ?838次閱讀
    ?數字孿生熱管理:NTC熱敏電阻陣列與<b class='flag-5'>熱</b>場重構算法的<b class='flag-5'>動態</b>適配

    桂花網藍牙網關物聯網醫院動態血糖管理應用案例

    醫院動態血糖管理應用案例 1、三諾動態血糖管理 該方案是集智能硬件、物聯網、大數據分析于一體的綜合性解決方案,通過以下核心步驟實現院內糖尿病患者的精準管理: (1)、全院CGM統一管理:通過統一平臺
    發表于 06-05 16:17

    藍牙數據通道空口(數據

    ? 與藍牙廣播相對應,藍牙數據是另一種Bluetooth LE packet。藍牙數據是藍牙數據信道空中的簡稱,表示空中只在藍牙數
    發表于 06-03 10:51

    業務監控—一站式搭建jmeter+telegraf+influxdb+Grafana看板

    jar的JVM指標如何?jar的火焰圖是什么樣的? 對此,只能望洋興嘆。基于以上背景,對jar監控做了一些調研和實戰。 ? ? 二、調研
    的頭像 發表于 05-27 14:40 ?1247次閱讀
    業務監控—一站式搭建jmeter+telegraf+influxdb+Grafana看板

    鴻蒙開發實現圖片上傳上傳用戶頭像)

    (FilePicker),實現該能力。通過Picker訪問相關文件,將拉起對應的應用,引導用戶完成界面操作,接口本身無需申請權限。 import picker from \'@ohos.file.picker
    發表于 05-24 23:09

    HarmonyOS5云服務技術分享--Serverless抽獎模板部署

    通過endCallback實現中獎消息推送 ? ??安全加固?? 非免認證模式下建議: 添加請求頻率限制 使用HTTPS加密回調 用戶ID做哈希處理 五、常見問題QA ? 部署后訪問顯示空白
    發表于 05-22 20:25

    鋰電池失控原理及安全檢測技術解析

    與未來趨勢 現有設備大多已實現高精度檢測,但仍面臨兩大瓶頸: 動態監測能力不足:現有系統多局限于實驗室環境,難以實時監控車載電池狀態; 多參數耦合分析缺失:-電-機械多場耦合效應對
    發表于 05-12 16:51

    K230D部署模型失敗的原因?

    重現步驟 1.按照教程實現MicroPython 版本部署流程,連接上并將文件放到對應位置后,剛運行就斷開和canmv ide的連接了(此時用的固件版本是圖中推薦的K230D_Zero...
    發表于 03-11 06:19