Web開發(fā)比較:Spring Boot與Express.js
JavaScript的服務(wù)器端開發(fā)比Java更好嗎?它可能只取決于正在開發(fā)的應(yīng)用程序。我現(xiàn)在可以聽到來自Java開發(fā)人員的發(fā)聲。
從Java開發(fā)人員的角度來看,使用Spring Boot生態(tài)系統(tǒng)和JavaScript與Express進(jìn)行Web開發(fā)的簡單比較。
本文的目標(biāo)
這是一個不太技術(shù)性的比較(您可以在其他地方找到更具體的技術(shù)比較)。我只想概述當(dāng)您是一名Java開發(fā)人員時,如何在Node.js中開發(fā)Web應(yīng)用程序。
所以請記住,這篇文章充滿了個人意見。
在開始之前,我概述了一些前提:
1. 我是一名使用Java語言的軟件開發(fā)人員。我已經(jīng)開發(fā)了基于Java的軟件大約15年了。
2. 我目前正在學(xué)習(xí)JavaScript開發(fā)(自2007年以來我一直在編寫前端JavaScript,但服務(wù)器端JavaScript已成為它自己的野獸)。
我想要比較什么
我想強(qiáng)調(diào)一下開發(fā)基于Node / Express堆棧的應(yīng)用程序與基于Spring Boot的應(yīng)用程序相比時所感受到的一些差異。
為什么我要比較這些
TL; DR:在完成一個簽約項目之后,我決定測試另一個生態(tài)系統(tǒng)來檢查它是否可以避免一些Java最受批評的點(diǎn)。
我***一個客戶是一家正在創(chuàng)建加密交換的公司(是的,在當(dāng)今市場上很常見,但對于一家意大利公司來說并不常見)。他們讓我加入他們的團(tuán)隊(三個不同的開發(fā)團(tuán)隊)并幫助他們建立自己的平臺。我主要開發(fā)用于授權(quán)和身份驗(yàn)證的微服務(wù),核心事務(wù)處理,以及客戶的KYC微服務(wù)和不同微服務(wù)之間共享的代碼庫等其他東西。
這是一個大而有趣的項目。
但在與其他團(tuán)隊和人員的討論中,我經(jīng)常聽到對基于Java的Web開發(fā)的批評,轉(zhuǎn)而支持Python或Go。其他語言似乎沒有遭受Java的一些批評是:
- Java很冗長。
- Java中的一切都是界面混亂的。
- Java應(yīng)用程序的內(nèi)存消耗是壓倒性的。
- 磁盤空間消耗也可能是壓倒性的。
- 發(fā)展需要很多時間。
在編寫數(shù)百個基于Docker的微服務(wù)時應(yīng)該考慮使用3.和4.我認(rèn)為這個規(guī)模問題可能是無稽之談,因?yàn)槿绻阌袛?shù)百個微服務(wù)運(yùn)行,你的組織可能是相當(dāng)有利可圖的,你可以買得起“昂貴” “實(shí)例支持內(nèi)存貪婪的Java應(yīng)用程序。
我必須誠實(shí),有時我認(rèn)為,在2019年,上述所有五點(diǎn)都是合理的批評,所以我想嘗試自籌資金項目來測試其他一些技術(shù)。
由于我需要進(jìn)行Web開發(fā)而不一定是基于微服務(wù)的項目,在快速(非??焖俚兀┛碐O之后,我決定反對這種語言。我認(rèn)為它是一種很棒的語言(從我讀到的內(nèi)容)但它不適合我當(dāng)前的項目。
所以我看了Python并開始使用Python,但我需要編寫一些JavaScript代碼,因?yàn)槲覍⑹褂肞uppeteer作為PricePaladin(一種價格跟蹤和監(jiān)控工具)的基本組件, 并在審查了非常好的 語言比較之后 我決定使用Node.js.
對照
語言
如果您是Java開發(fā)人員,您會發(fā)現(xiàn)JavaScript并不難學(xué)。當(dāng)你處理回調(diào)時,你肯定會凍結(jié)。你會發(fā)現(xiàn)Promises,并且在一天結(jié)束時,你將使用async-await語法糖,使一切恢復(fù)正常。
也就是說,JavaScript聽起來有點(diǎn)奇怪,但今天的JavaScript絕對沒問題(正如我之前所說,它不是2015年的JavaScript)。它簡單,功能強(qiáng)大且簡潔。
我留下關(guān)于動態(tài)打字的所有觀察結(jié)果,在我看來,這并不是什么大不了的事。
Node.js是單線程的
好的,對于Java開發(fā)人員來說,這是最“令人震驚”的事情之一。但片刻之后震驚消失了。您應(yīng)該考慮一切都在一個線程上運(yùn)行(在任何Java Web應(yīng)用程序上,您有多個線程),并且回調(diào)函數(shù)(異步函數(shù))在執(zhí)行它們時排隊并執(zhí)行,但所有代碼都在單個線程上運(yùn)行(Node.js的速度和低內(nèi)存消耗的關(guān)鍵)。從Java開發(fā)人員的角度來看,這意味著:
1. 不要運(yùn)行CPU時間密集型代碼,否則在執(zhí)行新的排隊功能之前,所有內(nèi)容都將等待CPU空閑。
2. 如果出現(xiàn)問題并且Node.js崩潰,那么 一切都會 崩潰:在Web應(yīng)用程序服務(wù)多個并發(fā)請求的情況下,所有請求都會崩潰。您沒有Java Web應(yīng)用程序的隔離。
JS相當(dāng)于Spring Boot Ecosystem:Express.js,Passport.js,Sequelize
如果我們僅限于與MVC Web應(yīng)用程序部分的比較,Spring Boot絕對是非常棒的:輕巧,快速,完整且極其可配置。從這個角度來看,與Express.js提供的相比,Java開發(fā)人員并沒有任何重大缺陷。
Express.js也提供相同的潛力。根據(jù)個人品味,可以更好地理解或不是路由:不是在Java注釋級別定義,而是在路由文件級別定義。
更一般地說,Spring Boot表示將代碼組織到包(模型,服務(wù),控制器)中的非常精確的方法,而在Express.js上下文中則沒有這樣的指導(dǎo)。盡管如此,可以重新應(yīng)用類似的代碼結(jié)構(gòu),并且通常有一些項目的代碼結(jié)構(gòu)與Spring Boot項目類似。
對于身份驗(yàn)證部分,Spring Security是“***工具”......但如果用于某些特別復(fù)雜的情況,它也是“馴服的野獸”。JavaScript對應(yīng)的是Passport.js,它非常強(qiáng)大,但結(jié)構(gòu)和成熟度較低。然而,您感覺它能夠處理與Spring Security相同的情況和條件。在任何情況下,該框架也廣泛支持開發(fā)通用認(rèn)證機(jī)制,例如JWT認(rèn)證或其他常見的auth機(jī)制。Spring Security的成熟度尚未與Passport.js相匹配,但我認(rèn)為Spring Security提供的80%的功能也是在Passport.js中實(shí)現(xiàn)的,有時候更簡單。
從我的觀點(diǎn)來看,Java中的ORM一直是Java應(yīng)用程序的致命弱點(diǎn)。Java標(biāo)準(zhǔn)大致是Hibernate(盡管有各種各樣的選擇,無論多么廣泛,如Jooq和MyBatis),而對于與關(guān)系數(shù)據(jù)庫相關(guān)的JS世界,***的庫是Sequelize。
Hibernate與Sequelize
TL; DR:Hibernate仍然是最完整,最成熟,最通用的解決方案,但成本非常高!Sequelize可能會覆蓋90%的用例。
我不討厭Hibernate,但我肯定不喜歡它。它過于設(shè)計,緩慢而復(fù)雜。它就像一頭大象。但是,它可以對任何受支持的數(shù)據(jù)庫執(zhí)行任何操作。相反,Sequelize小而簡單但無法管理所有用例。
我通過使用Sequelize發(fā)現(xiàn)的一些事情:
1. 你會有一個不那么難,但絕對不是那么容易的時間嘗試使用蛇案件的桌子的領(lǐng)域。您可以逐個手動指定它們(但這太過分了),或者您可以使用一些黑客將名稱轉(zhuǎn)換為蛇案例。這是一個簡單的解決方案,但它的缺點(diǎn)在于它會破壞遷移命令行工具。無論如何,用于引入命名約定定義的靈活性的所有請求都被丟棄并被忽略是不可接受的。
2. 它不完全支持復(fù)合鍵。正如這里明確指出的那樣 ,“雖然可以在Sequelize中創(chuàng)建復(fù)合主鍵,但Sequelize當(dāng)前不支持復(fù)合外鍵,因此無法引用具有復(fù)合主鍵的模型/表。”從我的角度來看,這是不成熟的。
3. 由于時區(qū)解釋,你必須做一些很好的技巧來管理日期字段(這真是出乎意料)。
4. 將實(shí)例添加到兩個實(shí)體(例如Book和Author)之間相關(guān)的字段時,會立即保存實(shí)體。這并不是什么大不了的事,但表明Sequelize遠(yuǎn)不如Hibernate復(fù)雜,后者有內(nèi)部機(jī)制來決定何時刷新數(shù)據(jù)。
在Sequelize中也有一些我喜歡的東西,比如在運(yùn)行時創(chuàng)建查詢的容易性(這是輕而易舉的,你可以在運(yùn)行時編寫一個JSON對象并將其傳遞給查詢引擎)。嘗試在創(chuàng)建JPQL查詢時執(zhí)行此操作,或者考慮使用某些條件進(jìn)行復(fù)雜化的過程。老實(shí)說,在嘗試通過某些字段在運(yùn)行時動態(tài)過濾查詢時使用Hibernate和Spring Data JPA是一件很痛苦的事情,而在Sequelize中這很容易(應(yīng)該用任何框架/語言)。
Sequelize在Hibernate方面閃耀的另一個方面是,當(dāng)你遇到一些困難的情況并且需要進(jìn)行本機(jī)查詢時:它們都允許你執(zhí)行本機(jī)查詢,但老實(shí)說,將結(jié)果轉(zhuǎn)換為模型更簡單Sequelize比Spring Data JPA / Hibernate。
而且我不是在談?wù)搯訒r間:介紹Hibernate會增加啟動時間,而Sequelize則非常直接。
作為***的考慮,很明顯:
1. Sequelize比Hibernate成熟得多,
2. Hibernate能夠做任何事情,而Sequelize僅覆蓋90%的用例。
3. Sequelize不那么抽象,而且更容易使用。
4. 這可能是一個很大的優(yōu)勢,特別是當(dāng)您擁有數(shù)據(jù)庫模式,不必適應(yīng)遺留數(shù)據(jù)庫,并且您不打算有一天遷移數(shù)據(jù)庫引擎時(說實(shí)話,我只看到一個案例)數(shù)據(jù)庫遷移在我的生活中,當(dāng)兩家銀行決定合并時,因此決定只保留一個IT系統(tǒng)并將廢棄的代碼重寫到另一個平臺。有數(shù)千個存儲過程需要重寫,所以代碼可移植性,在我看來,在談?wù)揙RM時,是一個無用的功能。)
***的考慮因素
我目前正在使用描述的JavaScript堆棧,目前我對它非常滿意。 PricePaladin(一種價格跟蹤和監(jiān)控工具) 是使用上面提到的堆棧構(gòu)建的,由于其內(nèi)存占用少,目前已部署到廉價的服務(wù)器上。
使用JavaScript可以為您帶來更高級的簡單性。它是腳本和標(biāo)準(zhǔn)Web開發(fā)的理想選擇,但我不會將它用于復(fù)雜項目(小型專用和隔離的微服務(wù)除外),也不會將它用于數(shù)字應(yīng)用程序或數(shù)字計數(shù)的應(yīng)用程序(如Java和Java的加密交換)它的 BigDecimal類非常適合該范圍)。
最終,我在開發(fā)服務(wù)器端JavaScript時的一般感覺是,與基于Java的等效應(yīng)用程序相比,一切都更簡單,更簡單,盡管我強(qiáng)烈認(rèn)為缺乏穩(wěn)定性和成熟度。用Java提供的庫(只有當(dāng)特定項目需要某些庫時才缺乏實(shí)際,否則沒有區(qū)別)。
另一種看法是JavaScript開發(fā)周期快了約20%。通過這種方式,我的意思是,由于更復(fù)雜的代碼和過度設(shè)計的Java應(yīng)用程序結(jié)構(gòu)遵循經(jīng)典指南和重建代碼所花費(fèi)的時間,因此您在Java中開發(fā)相同功能的時間比在JavaScript中花費(fèi)的時間多得多。
因此,在應(yīng)用程序不提供計算或阻塞處理的情況下,并且關(guān)注經(jīng)典的小型Web應(yīng)用程序的開發(fā),我?guī)缀蹩隙〞x擇使用所描述的JavaScript堆棧進(jìn)行開發(fā),而在其他情況下,我會將應(yīng)用程序基于從長遠(yuǎn)來看,我認(rèn)為Spring Boot堆棧提供了更強(qiáng)的可維護(hù)性。