主頁 > 後端開發 > 聊一聊系統重構

聊一聊系統重構

2023-03-21 07:05:54 後端開發

打破常規,重立新規;


01


開始想聊這個話題的時候,我是打算放棄的;因為這個話題涉及范圍之廣,內容之多,讓我犯怵;

近幾年,待過兩家公司;一家經歷過重構,另一家也打算重構......

其實要下定決心,推翻重來,是一個很有勇氣的決定;

歸根結底,不到萬不得已,誰想這么玩,誰愿意花費大精力去做這些臟活、累活;

所以究其原因,也只能說是一種綜合因素吧,就像古話說的,天時、地利、人和;

至于為什么這是個很有勇氣的決定,因為做重構這事的團隊風險極高;上至業務高層,下至底層碼農,都有可能一個不小心就被刀;

我曾經待過的一個團隊,經歷過一次重構,不過那是一次失敗的經歷;

開發預估了兩個多月的時間,業務大佬決定,期間直接對新需求停滯;但是,最終上到生產的系統,老問題還在,然后又多了很多的新問題;

再后來啊,業務大佬和技術主管都被刀了;然后系統回退成老版本,重新承接新需求,并且開發時間被嚴重壓縮,導致技術部門沒日沒夜的加班;

下面,我大致做了歸檔和整理,從這八個方面重新聊一聊系統重構;


02



【重構原因】
其實上面也提到過,這是一個綜合因素,可能是各種各樣的因素疊加,造成一個不得不重構的結果;

下面,聊一聊我所碰到過的因素;要是沒聊到的地方,也歡迎大家補充;

第一個,可以歸結為系統的穩定性或可用性:不管吹得怎么天花亂墜,你的系統總要可用吧,所以說可用和穩定是一個系統的最基本要求,開發一個需求還要全服務停用嗎?業務量增長,系統還能抗下所有嗎?那么問題來了,怎么保證可用和穩定?

首先,如果你是單服務系統,那么為了保障可用和穩定,需要對服務進行擴展,加入更多的機器來分擔系統的性能壓力,也就是常說的“服務集群”;

但是,往往我們的系統并不是單服務的,也就是我們常說的分布式微服務;這種情況下,就不得不扯到分布式的三大法寶:限流、熔斷、快取,相信要實作這三個法寶,有很多成熟的框架和工具等,這里就不過多闡述了;

第二個,開發規范問題:這也考驗了團隊leader對底下成員的約束力,以及是否存在代碼review的環節;

假設一個團隊,leader確實沒有對成員強制約束開發規范,更別提代碼的review了;最終導致的問題就是,各寫各的,每個人都有自己的一套開發習慣和開發規范;最終就是一個大寫的“亂”;

這樣榷訓月累,一代目埋坑,一代目撤,二代目上,二代目撤...... 系統不知道經了多少開發人員的手,最終,新入職的冤種某天需要排查一個產線問題,仿佛誤入了代碼的迷宮,深陷其中,無法自拔;

第三個,推翻原先核心業務,重立新規:這個要解釋起來比較麻煩,也碰到會比較少,然而,我恰恰就遇到了;

某天,業務大佬宣布,目前做的這套業務規則要被廢棄了,他們重新擬定了一套全新的規則,意味著先前不知道幾手的代碼已經失去意義了,幾乎90%都需要重新寫;

都到這一步了,那就大刀闊斧的改革吧;出事了,emmm,業務的鍋;


03



【重構會議】
既然已經確定要進行專案的重構,那么拉成員例會是必不可少的,不然就會一片迷茫,不知道干點啥;

第一次會議,由技術老大牽頭,叫上業務負責人,技術主管,開發全員,測驗,產品,運維;

一般,第一次這種全體會議是沒有結果,但是又非常必要的;因為上級領導需要知曉整個重構涉及到的點,影響的方面,開發的時間,以及整體的技術方案,參與的人員,還有需要的資源等等;

第一次會議消化完后,很快就是第二次會議;這個會議也是由技術老大牽頭,參會的主要是技術主管和參與開發的人員和運維;主要是對系統重構進行總體的技術選型,討論用到的框架,組件,實作的方案,部署方案等等;

這個會議持續的時間會比較久,大家搬好小板凳,準備打持久戰,可能從上班開始,到下班點了都還不能結束;當然,還是會有中場休息時間的;基本可以各抒己見,提出自己的意見和看法;主要是圍繞做什么?怎么做?做多久?這三個疑問點討論;

接下來,就是由技術主管組織的技術部內部會議了;由于之前已經確定好了統一的技術堆疊和實作方案,這一次討論都是在此基礎上展開的;

當然這一次會議可能需要更久的時間,因為涉及到是微服務的話,就避免不了一個問題:“服務拆分”;

大家都知道,微服務是需要根據業務去進行拆分的;那么問題來了,業務的劃分界限是什么?為什么A業務部分要包含A1,A2,A3;其實這里就需要大家達成一個統一的認知,也是這次會議要達成的最終目的;

這次會議最后,服務已經劃分完畢,但是缺少去維護這些服務的人;那就需要對開發人員進行分組,每組有對應的負責人,看人員情況而定(如果就兩三個,甚至更少的開發,那就沒必要分組什么的了,就是冤種,活都得你干),每組對N個服務的開發和維護;

分組過后,組長會進行簡短的組內會議,這次其實就是派活會議,認領各自的作業;也會明確一點,大家要干些什么?誰干哪些?每個人干完都需要多久的時間?

最后,會整理一份排期計劃,上面每個人的名字赫然在列,當然還有任務串列,工時,等等;

一切準備作業就緒,最后就是開干了,當然后面開發程序中還有一些不明確的點,也會臨時組織一些會議,讓大家達到統一的認知;


04



【并行需求】
在系統重構的開發程序中,因為占用的周期會很長,投入的資源會比較多,所以難免還會遇到這樣一個問題;

一天產品經理急沖沖的跑過來說,現在有一些需求很著急,需要將重構停一停,先把這些需求排期上線;至于為什么會這么著急,咱也不知道,咱也不敢問呀;

這時候就會面臨一個惡心的局面,這次開發的需求,肯定需要在原先的服務中進行開發,那么重構的服務中,是不是還需要再寫一遍?

王德發!說歸說,罵歸罵,辦法總比困難多!這時候有一種方式,那就是派出個談判專家,以三寸不爛之舌,動之以情,曉之以理;多說說技術難點、痛點,占用的資源,實作的難度等等,去打動他,說服他,讓這次需求排在重構后面;

如果你成功了,那么恭喜你,這次重構任務,大家幫你分擔一半

什么?產品經理不同意;那就沒有辦法,只能在改動老服務的基礎上,記錄調整的點,最終在寫新服務業務代碼的時候,將改動的點一并加上去;

最后在提測的時候,通知測驗同學,這些需求相關的地方,在重構的新服務上線之前都需要重新走一遍流程;

當然,還有一種情況,就是像我之前說的,需求即伴隨著重構;這種需求也肯定是大版本,開發周期較長;這種情況是最理想化的,只需要按部就班的進行開發即可;


05



【技術選型】
這個話題,在上面的會議模塊已經提到過了,這里再來詳細的聊一聊;

當然,這次也僅限于比較流行的分布式微服務的技術選型;單服務的話,額,暫且不說吧;

其實也沒什么好爭議的,對于Java系統而言,無非就是spring全家桶無腦往上堆,服務器資源拉滿;就像買汽車一樣,越豪華的車,堆的配置越多,價格越貴,但是舒適性和操控性也就越好;

但是還需要考慮一些因素:成本、產品開源與否、技術社區活躍度、產品的成熟度、結合實際情況等等;

成本:時間成本、學習成本、金錢成本;

事情是人做的,代碼也是人敲的;需要考慮團隊成員擅長哪些技術堆疊,如果一門技術只有少部分人會或者都不會,那就需要結合開發時間,去斟酌需不需要用它,即便是熱門的技術;

當然啦,如果老板愿意出錢,直接買各種付費的技術就行,我們只需要搭好基礎的框架,然后往里面填充業務代碼即可;如果不行,那就老老實實看看免費版,出了啥問題,只能自己排查去解決;

產品開源與否:說到這個,開源是關鍵,最香的詞“開源免費”;

就像上面說的,一旦遇到了什么問題,其實有必要去看這門技術的原始碼去解決的;比如典型的SpringBoot自定義starter,需要定義“META-INF/spring.factories”檔案,將檔案中配置的型別資訊加載到 Spring 容器;

一旦你閉源,那怎么玩?我怎么知道你內部怎么去實作的?只能看官方檔案,看你自己吹什么什么功能;

技術社區活躍度:這個因素其實和產品開源可以歸為一類,都講的是一旦這個框架或產品出了問題,我們就可以去它的官方社區上找類似的解決方案;如果一個產品連社區都沒,或者活躍度很低,那也就意味著你只能靠自己去解決了,那花的時間成本可就......

產品的成熟度:我們選用一款合適的產品,首先它得符合我們主要的需求,而后它才有其他額外的功能,這當然是最好的;因為一旦咱有一些特殊的業務場景,恰巧這些額外功能正好符合你這個場景,豈不美哉;這樣就不必要接入額外的產品或組件了;

比如Redis,大家都不陌生;相信這個工具大家最多的是用它做快取,它確實也是一款優秀的快取工具;

但是,我之前在做OA軟體時,碰到這么一個需求;用戶申請一個會議,并且指定了參會人員,當在會議開始前15分鐘,前5分鐘,分別對參會人員發送一個提醒;

典型的發布、訂閱的模式,然后正好Redis就有現成的功能,當時就是用了Redis的這個功能;

但Redis適合小型應用,如果是大型架構,相信還是會使用rabbitMQ或者kafka等更專業的MQ佇列軟體

結合實際情況:說到這個,有句老話說:“只有適合自己的才是最好”;在考慮需要用到哪項技術時,最理想的情況那就是直接付費購買,出啥問題,都是有技術支持滴,我出錢了,你得為我解決,但是,成本有限啊;

當然,有些人會說,技術選型這玩意,那是技術主管或者技術總監他們決定的,我們小碼農只管擰好螺絲就行;是的,往往很多時候就是這樣;但是,你不去大膽說出你的想法和意見,你怎么知道他們不會聽取呢?格局打開,往上一層考慮就對了;


06



【服務劃分】
這塊內容其實可聊的沒多少,但是,也是最難的一塊;

首先,劃分;怎么分?按什么標準去分?分多少服務合適?分好之后怎么去管理?安排那些人去管理?等等一堆問題;

我也只能淺談下我之前做過的一次劃分經歷,因為每個公司遇到業務和場景是不同的,最終得到的結果也是不同的;而且,服務并不是一次劃分就能結束,它是一個持續不斷的程序;

當時我們是全部參與這次重構的開發一起拉會議的,在此之前,已經確定好了技術堆疊,就是熱門的springcloud全家桶;技術主管先是淺談一波他自己的想法,然后讓大家在他劃分服務的基礎上,提出自己的看法,并且每個人都要說,因為不可能想法都是一致的;

我記得比較清楚的是,他劃分中,有個序列號的服務,就是這個服務專門去生成序列號;后面幾個人都點名這個服務也包括我;其實當時想的是,我們的系統業務里沒那么大,能省一個服務,也是省一點資源;最終大家統一共識,將這種場景寫一個工具類去處理;

最終討論后,達到的共識,也只是一個初步的共識;隨著業務需求的增長,一部分業務服務必將變得臃腫,那時候第二波拆分也就隨之到來了;


07



【開發規范】
上面提到,造成系統重構的因素有很多,其中一個因素就是代碼混亂,大家各有各的習慣和規范;

其實不難發現問題了,并不是每個人不知道開發規范,而是大家沒有統一的一套規范,大家只是沒有達成共識;

那就來解決這個問題,制定一套統一的標準,讓大家都沒有異議的一套規范;

這時候就不得不提到阿里的規范,現在廣為流傳的《阿里巴巴Java開發手冊》,甚至基于這套規范,在IDEA上還有專門的檢查插件可以安裝;

當然,這樣做確實省事,省去了leader對代碼的review時間,包括我之前待過的一家公司,也確實就是這么做的;

其實仔細用過幾次這款插件就會發現,有些檢測其實大可不必,但是你又不得不去遵守它的規則,這時候反而徒增作業量;

遇到這種情況就需要看上級了,可以把這個疑問點反饋給他,或者反饋給身邊其他的小伙伴,起碼讓他們GET到你要表達的點,引起大家的共鳴;相信越來越多的人反饋這些問題,上級不會坐視不管的;那么恭喜你,又去掉一塊大家都認為不合適的規范,讓你開發不繞彎路;

總之,總結起來就是一句話:沒有標準,大家統一認可的就是標準犯規;


08



【資料、介面遷移】
談到這個,除非開發的是0-1的專案,否則在平時開發中,或多或少都是會遇到的,而非重構會單獨遇到的問題;

而我們在入職一家新公司,或者長期在一家公司干活,遇到0-1的專案幾乎沒有;如果有,那么你的運氣很好;

就拿我上面的經歷來說,業務推翻了之前的規則,重新制定了新的業務規則,那就不得不引出一個問題,之前的老資料怎么辦?

這個時候就需要跟業務確認,這批老資料是否可以按照某種默認的規則,做統一的處理;或者說,直接廢棄不管;一般來說,按前者處理的方案居多;

考慮到重構,往往你的表也是重新設計過的,也有可能是老表和新表公用,一般來說后者的情況居多;

其實,說白了就是在老表里面去修改資料,在新表里面去新增資料,而我們要考慮的是這批資料怎么去調整比較合適;

按我們之前的處理方式,如果涉及到的表,欄位等較少,存盤結構也頗為簡單,是可以直接用SQL腳本去解決的;另外,還需要考慮如果表資料較多,SQL執行快慢的問題;

還有一種情況,要是涉及到的場景很多,處理的表也居多,可以考慮寫程式去解決;比如,寫個任務,去手動執行這個任務,處理掉這批資料;當然,也得考慮資料量的問題,如果資料量大,用多執行緒跑批,或者多服務跑批等方式;

下面,來談談重構中的介面遷移;

要保證一個原則,就是對介面的出入參保持不動;不然,前端直接飛過來跟你聊人生;

但是,老服務的介面很多怎么辦?還能怎么辦,分工處理;

上面提到過,我們是分組的方式,每個組負責一部分服務,分工比較明確,所以相對來說,也比較快;

大家整理檔案,老介面的URL是什么,新介面的URL是什么,出參,入參能不變就不變;如果真的需要調整的,需要給出合理的解釋,大家一致通過后,然后自行跟前端去battle;

有些老服務還會運行一段時間,所以并不是所有介面都會涉及到遷移,這種介面,那就相安無事;

在遷移的程序中,肯定也會遇到各種問題;比如舉個簡單的例子,之前老服務的分頁插件使用的是PageHelper;而在新服務中,由于用上了Mybatis Plus框架,那自然也就用它框架自帶的分頁插件了;這個時候就涉及到修改,你只能自己內部消化了;

最后,當你覺得一切介面都遷移完畢的時候,別忘記對自己遷移的介面,進行一次自測;不要怕麻煩,這個自測對于后面的聯調和提測流程,都可以免去很多不必要的問題,也可以大大提高團隊的效率;


09



【實作方案】
最后還有一點,業務場景的實作方案;這個聽著有點抽象,其實在上面說的會議中,也會涉及;

不要以為這只是技術的決定,其實產品的參與也是很有必要的;你品,你細品;

我拿一個經典場景舉例,A賬戶往B賬戶打錢,然后系統是微服務,很熟悉吧;

沒錯,就是分布式事務的一個經典場景,要保證資料的一致性,A被扣錢的同時,B要加上相應的錢;

分布式事務我不多說,相信很多同學隨便一查,各種五花八門的方案;

但是這里我只講一點,達到資料一致的時間節點;你是要什么時候保證這個資料達到一致,也就是說,強一致性還是最終一致性;

要求強一致必然是犧牲掉一部分性能的,要求最終一致性就有可能在一段時間內產生資料不一致的問題;

這個時候,就需要拉上產品經理,跟他闡述其中的緣由,說明技術方案上無法規避的點,讓他做取舍;

有的時候,好的設計往往能規避技術上的難點,也可以節省開發的成本和時間;

所以,在討論這塊內容的時候,必須要有產品經理在場,提出設計上不合理之處;我們不能只局限于研究技術問題,其實換個角度,或者你質疑的點,就不存在了;

記得實習的時候,公司的老板講過一句話“人人都是產品經理”,現在回過頭一想,還真是那么回事;

大膽的提出自己的意見,做一個有自己主見的小碼農;


10



對于系統重構,我就以一句話結尾吧,這也是參考了一位大佬的話,“對公司現有的資源和戰略妥協,在技術堆疊和方案之間取舍”,

編程檔案:
https://gitee.com/cicadasmile/butte-java-note

應用倉庫:
https://gitee.com/cicadasmile/butte-flyer-parent
Gitee主頁: https://gitee.com/cicadasmile/butte-java-note

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/547439.html

標籤:Java

上一篇:深入理解Go語言中的sync.Cond

下一篇:Spring Boot 如果防護 XSS + SQL 注入攻擊 ?一文帶你搞定!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more