色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

使用AOP實現異步上傳

Android編程精選 ? 來源:稀土掘金技術社區(qū) ? 作者:天機術士 ? 2022-07-25 15:30 ? 次閱讀

前言

相信很多系統(tǒng)里都有這一種場景:用戶上傳Excel,后端解析Excel生成相應的數據,校驗數據并落庫。這就引發(fā)了一個問題:如果Excel的行非常多,或者解析非常復雜,那么解析+校驗的過程就非常耗時。

如果接口是一個同步的接口,則非常容易出現接口超時,進而返回的校驗錯誤信息也無法展示給前端,這就需要從功能上解決這個問題。一般來說都是啟動一個子線程去做解析工作,主線程正常返回,由子線程記錄上傳狀態(tài)+校驗結果到數據庫。同時提供一個查詢頁面用于實時查詢上傳的狀態(tài)和校驗信息。

50f074e4-068e-11ed-ba43-dac502259ad0.png

進一步的,如果我們每一個上傳的任務都寫一次線程池異步+日志記錄的代碼就顯得非常冗余。同時,非業(yè)務代碼也侵入了業(yè)務代碼導致代碼可讀性下降。

從通用性的角度上講,這種業(yè)務場景非常適合模板方法的設計模式。即設計一個抽象類,定義上傳的抽象方法,同時實現記錄日志的方法,例如:

//偽代碼,省略了一些步驟
@Slf4j
publicabstractclassAbstractUploadService<T>{
publicstaticThreadFactorycommonThreadFactory=newThreadFactoryBuilder().setNameFormat("-upload-pool-%d")
.setPriority(Thread.NORM_PRIORITY).build();
publicstaticExecutorServiceuploadExecuteService=newThreadPoolExecutor(10,20,300L,
TimeUnit.SECONDS,newLinkedBlockingQueue<>(1024),commonThreadFactory,newThreadPoolExecutor.AbortPolicy());

protectedabstractStringupload(Listdata);

protectedvoidexecute(StringuserName,Listdata){
//生成一個唯一編號
Stringuuid=UUID.randomUUID().toString().replace("-","");
uploadExecuteService.submit(()->{
//記錄日志
writeLogToDb(uuid,userName,updateTime,"導入中");
//一個字符串,用于記錄upload的校驗信息
StringerrorLog="";
//執(zhí)行上傳
try{
errorLog=upload(data);
writeSuccess(uuid,"導入中",updateTime);
}catch(Exceptione){
LOGGER.error("導入錯誤",e);
//計入導入錯誤日志
writeFailToDb(uuid,"導入失敗",e.getMessage(),updateTime);
}
/**
*檢查一下upload是不是返回了錯誤日志,如果有,需要注意記錄
*
*因為錯誤日志可能比較長,
*可以寫入一個文件然后上傳到公司的文件服務器,
*然后在查看結果的時候允許用戶下載該文件,
*這里不展開只做示意
*/
if(StringUtils.isNotEmpty(errorLog)){
writeFailToDb(uuid,"導入失敗",errorLog,updateTime);
}

});
}
}

如上文所示,模板方法的方式雖然能夠極大地減少重復代碼,但是仍有下面兩個問題:

  • upload方法得限定死參數結構,一旦有變化,不是很容易更改參數類型or數量
  • 每個上傳的service還是要繼承一下這個抽象類,還是不夠簡便和優(yōu)雅

為解決上面兩個問題,我也經常進行思考,結果在某次自定義事務提交or回滾的方法的時候得到了啟發(fā)。這個上傳的邏輯過程和事務提交的邏輯過程非常像,都是在實際操作前需要做初始化操作,然后在異常或者成功的時候做進一步操作。這種完全可以通過環(huán)裝切面的方式實現,由此,我寫了一個小輪子給團隊使用。

當然了,這個小輪子在本人所在的大團隊內部使用的很好,但是不一定適合其他人,但是思路一樣,大家可以擴展自己的功能

多說無益,上代碼!

代碼與實現

首先定義一個日志實體

publicclassFileUploadLog{
privateIntegerid;
//唯一編碼
privateStringbatchNo;
//上傳到文件服務器的文件key
privateStringkey;
//錯誤日志文件名
privateStringfileName;
//上傳狀態(tài)
privateIntegerstatus;
//上傳人
privateStringcreateName;
//上傳類型
privateStringuploadType;
//結束時間
privateDateendTime;
//開始時間
privateDatestartTime;
}

然后定義一個上傳的類型枚舉,用于記錄是哪里操作的

publicenumUploadType{
未知(1,"未知"),
類型2(2,"類型2"),
類型1(3,"類型1");

privateintcode;
privateStringdesc;
privatestaticMapmap=newHashMap<>();
static{
for(UploadTypevalue:UploadType.values()){
map.put(value.code,value);
}
}

UploadType(intcode,Stringdesc){
this.code=code;
this.desc=desc;
}

publicintgetCode(){
returncode;
}

publicStringgetDesc(){
returndesc;
}

publicstaticUploadTypegetByCode(Integercode){
returnmap.get(code);
}
}

最后,定義一個注解,用于標識切點

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public@interfaceUpload{
//記錄上傳類型
UploadTypetype()defaultUploadType.未知;
}

然后,編寫切面

@Component
@Aspect
@Slf4j
publicclassUploadAspect{
publicstaticThreadFactorycommonThreadFactory=newThreadFactoryBuilder().setNameFormat("upload-pool-%d")
.setPriority(Thread.NORM_PRIORITY).build();
publicstaticExecutorServiceuploadExecuteService=newThreadPoolExecutor(10,20,300L,
TimeUnit.SECONDS,newLinkedBlockingQueue<>(1024),commonThreadFactory,newThreadPoolExecutor.AbortPolicy());


@Pointcut("@annotation(com.aaa.bbb.Upload)")
publicvoiduploadPoint(){}

@Around(value="uploadPoint()")
publicObjectuploadControl(ProceedingJoinPointpjp){
//獲取方法上的注解,進而獲取uploadType
MethodSignaturesignature=(MethodSignature)pjp.getSignature();
Uploadannotation=signature.getMethod().getAnnotation(Upload.class);
UploadTypetype=annotation==null?UploadType.未知:annotation.type();
//獲取batchNo
StringbatchNo=UUID.randomUUID().toString().replace("-","");
//初始化一條上傳的日志,記錄開始時間
writeLogToDB(batchNo,type,newDate)
//線程池啟動異步線程,開始執(zhí)行上傳的邏輯,pjp.proceed()就是你實現的上傳功能
uploadExecuteService.submit(()->{
try{
StringerrorMessage=pjp.proceed();
//沒有異常直接成功
if(StringUtils.isEmpty(errorMessage)){
//成功,寫入數據庫,具體不展開了
writeSuccessToDB(batchNo);
}else{
//失敗,因為返回了校驗信息
fail(errorMessage,batchNo);
}
}catch(Throwablee){
LOGGER.error("導入失敗:",e);
//失敗,拋了異常,需要記錄
fail(e.toString(),batchNo);
}
});
returnnewObject();
}

privatevoidfail(Stringmessage,StringbatchNo){
//生成上傳錯誤日志文件的文件key
Strings3Key=UUID.randomUUID().toString().replace("-","");
//生成文件名稱
StringfileName="錯誤日志_"+
DateUtil.dateToString(newDate(),"yyyy年MM月dd日HH時mm分ss秒")+ExportConstant.txtSuffix;
StringfilePath="/home/xxx/xxx/"+fileName;
//生成一個文件,寫入錯誤數據
Filefile=newFile(filePath);
OutputStreamoutputStream=null;
try{
outputStream=newFileOutputStream(file);
outputStream.write(message.getBytes());

}catch(Exceptione){
LOGGER.error("寫入文件錯誤",e);
}finally{
try{
if(outputStream!=null)
outputStream.close();
}catch(Exceptione){
LOGGER.error("關閉錯誤",e);
}
}
//上傳錯誤日志文件到文件服務器,我們用的是s3
upFileToS3(file,s3Key);
//記錄上傳失敗,同時記錄錯誤日志文件地址到數據庫,方便用戶查看錯誤信息
writeFailToDB(batchNo,s3Key,fileName);
//刪除文件,防止硬盤爆炸
deleteFile(file)
}

}

至此整個異步上傳功能就完成了,是不是很簡單?(笑)

那么怎么使用呢?更簡單,只需要在service層加入注解即可,頂多就是把錯誤信息return出去。

@Upload(type=UploadType.類型1)
publicStringupload(Listitems){
if(items==null||items.size()==0){
return;
}
//校驗
Stringerror=uploadCheck(items);
if(StringUtils.isNotEmpty){
returnerror;
}
//刪除舊的
deleteAll();
//插入新的
batchInsert(items);
}

結語

寫了個小輪子提升團隊整體開發(fā)效率感覺真不錯。程序員的最高品質就是解放雙手(偷懶?),然后成功的用自己寫的代碼把自己干畢業(yè)。。。。。。

審核編輯:湯梓紅


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

    關注

    33

    文章

    8575

    瀏覽量

    151017
  • Excel
    +關注

    關注

    4

    文章

    218

    瀏覽量

    55518
  • AOP
    AOP
    +關注

    關注

    0

    文章

    40

    瀏覽量

    11098

原文標題:實現一個小輪子—用AOP實現異步上傳

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

收藏 人收藏

    評論

    相關推薦

    Spring Boot如何實現異步任務

    Spring Boot 提供了多種方式來實現異步任務,這里介紹三種主要實現方式。 1、基于注解 @Async @Async 注解是 Spring 提供的一種輕量級異步方法
    的頭像 發(fā)表于 09-30 10:32 ?1436次閱讀

    AOP知識詳解

    今天我們繼續(xù)看看AOP相關的知識,前面說到了Javassit,Spring AOP,通過該篇,讓你對AOP有更完整的認識。 AOP 再看AOP
    的頭像 發(fā)表于 09-25 11:14 ?954次閱讀
    <b class='flag-5'>AOP</b>知識詳解

    Spring AOP如何破解java應用

    預編譯方式和運行期間動態(tài)代理實現程序功能的統(tǒng)一維護的一種技術。AOP是OOP的延續(xù),從另一視角擴展了對面向對象編程的形式。利用AOP可以對業(yè)務邏輯的各個部分進行隔離,從而使得業(yè)務邏輯各部分之間的耦合度
    的頭像 發(fā)表于 09-25 11:16 ?892次閱讀
    Spring <b class='flag-5'>AOP</b>如何破解java應用

    Labview 異步TCP怎么實現

    Labview的TCP控件為同步超時模式實現的,在一對多場景明顯不夠用,效率低,看了官方例程也沒有異步TCP的說明,該如何實現異步TCP呢?
    發(fā)表于 04-25 17:08

    具有AoP技術的雷達傳感器

    毫米波雷達為汽車和工業(yè)應用提供了一種高度精確的感應方式,可提供富有洞察力的物體信息,如距離、角度和速度,從而實現更智能的感應解決方案,用于檢測幾厘米到幾百米范圍內的物體。通常,雷達傳感器安裝在由雷達
    發(fā)表于 11-04 06:32

    AOP中使用標注改進日志功能的實現

    面向方面編程(AOP)可避免橫切關注點對核心代碼的不良影響,但AOP 中的方法簽名匹配模式難以精確表達系統(tǒng)中的橫切點,使得在大中型系統(tǒng)中直接使用連接點匹配方式捕獲某些橫
    發(fā)表于 04-17 09:01 ?25次下載

    高速異步FIFO的設計與實現

    本文主要研究了用FPGA 芯片內部的EBRSRAM 來實現異步FIFO 設計方案,重點闡述了異步FIFO 的標志信號——空/滿狀態(tài)的設計思路,并且用VHDL 語言實現,最后進行了仿真驗
    發(fā)表于 01-13 17:11 ?40次下載

    基于反射機制的AOP模型的研究_張波

    基于反射機制的AOP模型的研究_張波
    發(fā)表于 03-17 15:47 ?0次下載

    基于AOP的軟件缺陷檢測框架設計

    方法監(jiān)控層、數據過濾層和邏輯表現層組成,自底向上傳遞數據。該框架可實現軟件方法的實時監(jiān)控、自定義監(jiān)控規(guī)則、對于缺陷按照嚴重等級進行分類顯示等功能。最后通過與實際項目相整合,設計測試用例,測試結果表明本文提出的框
    發(fā)表于 11-03 16:05 ?20次下載
    基于<b class='flag-5'>AOP</b>的軟件缺陷檢測框架設計

    基于Iframe內聯框架的異步文件上傳與刪除

    在Weh應用程序開發(fā)過程中,文件上傳功能是個很常用又非常重要的功能,它要處理的內容主要包括:如何將上傳的文件以文件的形式保存到服務器,上傳Internet上的資源,提取相應文件名等信息傳遞到數據庫
    發(fā)表于 11-11 10:20 ?5次下載
    基于Iframe內聯框架的<b class='flag-5'>異步</b>文件<b class='flag-5'>上傳</b>與刪除

    基于AOP的科研申報系統(tǒng)的設計與實現

    也帶來困難。針對上述問題,本論文使用面向方面編程(AOP)的思想來解決,利用AOP中的方面(Aspect)來對非功能屬性進行建模,并采用UML中的類圖進行描述,并給出其在科研申報系統(tǒng)中權限控制模塊的實現,驗證了面向方面編程在解決
    發(fā)表于 11-11 17:44 ?8次下載
    基于<b class='flag-5'>AOP</b>的科研申報系統(tǒng)的設計與<b class='flag-5'>實現</b>

    java Web如何實現文件的上傳與下載

    文件上傳概述,實現web開發(fā)中的文件上傳功能,需完成如下二步操作: 在web頁面中添加上傳輸入項在servlet 中讀取上傳文件的數據,
    發(fā)表于 03-06 11:03 ?7次下載
    java Web如何<b class='flag-5'>實現</b>文件的<b class='flag-5'>上傳</b>與下載

    AOP要怎么使用

    AOP(Aspect-Oriented Programming)經常會出現在面試過程中,AOP到底有沒有用,要怎么使用呢。本篇來一起撥開迷霧! 1 第一個AOP示例 我們會一次將所有的通知類型都覆蓋
    的頭像 發(fā)表于 10-09 16:18 ?674次閱讀
    <b class='flag-5'>AOP</b>要怎么使用

    IWR1843AOP單芯片77GHz和79GHz FMCW毫米波傳感器天線封裝(AOP)數據表

    電子發(fā)燒友網站提供《IWR1843AOP單芯片77GHz和79GHz FMCW毫米波傳感器天線封裝(AOP)數據表.pdf》資料免費下載
    發(fā)表于 08-15 11:20 ?1次下載
    IWR1843<b class='flag-5'>AOP</b>單芯片77GHz和79GHz FMCW毫米波傳感器天線封裝(<b class='flag-5'>AOP</b>)數據表

    基于機器學習的IWR6843AOP跌倒和姿態(tài)檢測實現

    電子發(fā)燒友網站提供《基于機器學習的IWR6843AOP跌倒和姿態(tài)檢測實現.pdf》資料免費下載
    發(fā)表于 09-03 10:02 ?1次下載
    基于機器學習的IWR6843<b class='flag-5'>AOP</b>跌倒和姿態(tài)檢測<b class='flag-5'>實現</b>
    主站蜘蛛池模板: 国产一区日韩二区欧美三区| 一级毛片西西人体44rt高清| 欧美另类老少配hd| 久久re这里视频精品8| 国产一级做a爰片久久毛片男| 成人影院久久久久久影院| 99视频精品全部免费免费观| 最近韩国HD免费观看国语| 在公交车上被JB草坏了被轮J了| 亚洲视频第二页| 亚洲欧美日韩高清中文在线| 亚洲国产AV无码综合在线 | 国产精品一区二区三区免费| 国产成人精品电影| 国产产乱码一二三区别免费| 国产Av影片麻豆精品传媒| 囯产精品久久久久免费蜜桃| 国产成人啪精品视频免费网| 国产成人综合高清在线观看 | 亚洲中文无码亚洲人在线观看-| 亚洲精品视频免费看| 夜夜澡人人爽人人喊_欧美| 妖精视频免费高清观看| 中文免费视频| 91久久线看在观草草青青 | 熟妇的味道HD中文字幕| 脱jk裙的美女露小内内无遮挡| 无码AV精品久久一区二区免费| 性生生活大片又黄又| 亚洲视频精选| 87影院午夜福利| xxx88中国| 国产欧美无码亚洲毛片| 精品亚洲一区二区在线播放| 凌晨三点免费WWW| 欧美男同gay粗大又长| 色迷迷电影| 亚洲欧洲日韩国产一区二区三区| 又大又硬又爽免费视频| 99国产在线视频| 国产成人女人在线视频观看|