Web开发比较:Spring Boot与Express.js
JavaScript的服务器端开发比Java更好吗?它可能只取决于正在开发的应用程序。我现在可以听到来自Java开发人员的发声。
从Java开发人员的角度来看,使用Spring Boot生态系统和JavaScript与Express进行Web开发的简单比较。
本文的目标
这是一个不太技术性的比较(您可以在其他地方找到更具体的技术比较)。我只想概述当您是一名Java开发人员时,如何在Node.js中开发Web应用程序。
所以请记住,这篇文章充满了个人意见。
在开始之前,我概述了一些前提:
1. 我是一名使用Java语言的软件开发人员。我已经开发了基于Java的软件大约15年了。
2. 我目前正在学习JavaScript开发(自2007年以来我一直在编写前端JavaScript,但服务器端JavaScript已成为它自己的野兽)。
我想要比较什么
我想强调一下开发基于Node / Express堆栈的应用程序与基于Spring Boot的应用程序相比时所感受到的一些差异。
为什么我要比较这些
TL; DR:在完成一个签约项目之后,我决定测试另一个生态系统来检查它是否可以避免一些Java最受批评的点。
我最后一个客户是一家正在创建加密交换的公司(是的,在当今市场上很常见,但对于一家意大利公司来说并不常见)。他们让我加入他们的团队(三个不同的开发团队)并帮助他们建立自己的平台。我主要开发用于授权和身份验证的微服务,核心事务处理,以及客户的KYC微服务和不同微服务之间共享的代码库等其他东西。
这是一个大而有趣的项目。
但在与其他团队和人员的讨论中,我经常听到对基于Java的Web开发的批评,转而支持Python或Go。其他语言似乎没有遭受Java的一些批评是:
- Java很冗长。
- Java中的一切都是界面混乱的。
- Java应用程序的内存消耗是压倒性的。
- 磁盘空间消耗也可能是压倒性的。
- 发展需要很多时间。
在编写数百个基于Docker的微服务时应该考虑使用3.和4.我认为这个规模问题可能是无稽之谈,因为如果你有数百个微服务运行,你的组织可能是相当有利可图的,你可以买得起“昂贵” “实例支持内存贪婪的Java应用程序。
我必须诚实,有时我认为,在2019年,上述所有五点都是合理的批评,所以我想尝试自筹资金项目来测试其他一些技术。
由于我需要进行Web开发而不一定是基于微服务的项目,在快速(非常快速地)看GO之后,我决定反对这种语言。我认为它是一种很棒的语言(从我读到的内容)但它不适合我当前的项目。
所以我看了Python并开始使用Python,但我需要编写一些JavaScript代码,因为我将使用Puppeteer作为PricePaladin(一种价格跟踪和监控工具)的基本组件, 并在审查了非常好的 语言比较之后 我决定使用Node.js.
对照
语言
如果您是Java开发人员,您会发现JavaScript并不难学。当你处理回调时,你肯定会冻结。你会发现Promises,并且在一天结束时,你将使用async-await语法糖,使一切恢复正常。
也就是说,JavaScript听起来有点奇怪,但今天的JavaScript绝对没问题(正如我之前所说,它不是2015年的JavaScript)。它简单,功能强大且简洁。
我留下关于动态打字的所有观察结果,在我看来,这并不是什么大不了的事。
Node.js是单线程的
好的,对于Java开发人员来说,这是最“令人震惊”的事情之一。但片刻之后震惊消失了。您应该考虑一切都在一个线程上运行(在任何Java Web应用程序上,您有多个线程),并且回调函数(异步函数)在执行它们时排队并执行,但所有代码都在单个线程上运行(Node.js的速度和低内存消耗的关键)。从Java开发人员的角度来看,这意味着:
1. 不要运行CPU时间密集型代码,否则在执行新的排队功能之前,所有内容都将等待CPU空闲。
2. 如果出现问题并且Node.js崩溃,那么 一切都会 崩溃:在Web应用程序服务多个并发请求的情况下,所有请求都会崩溃。您没有Java Web应用程序的隔离。
JS相当于Spring Boot Ecosystem:Express.js,Passport.js,Sequelize
如果我们仅限于与MVC Web应用程序部分的比较,Spring Boot绝对是非常棒的:轻巧,快速,完整且极其可配置。从这个角度来看,与Express.js提供的相比,Java开发人员并没有任何重大缺陷。
Express.js也提供相同的潜力。根据个人品味,可以更好地理解或不是路由:不是在Java注释级别定义,而是在路由文件级别定义。
更一般地说,Spring Boot表示将代码组织到包(模型,服务,控制器)中的非常精确的方法,而在Express.js上下文中则没有这样的指导。尽管如此,可以重新应用类似的代码结构,并且通常有一些项目的代码结构与Spring Boot项目类似。
对于身份验证部分,Spring Security是“终极工具”......但如果用于某些特别复杂的情况,它也是“驯服的野兽”。JavaScript对应的是Passport.js,它非常强大,但结构和成熟度较低。然而,您感觉它能够处理与Spring Security相同的情况和条件。在任何情况下,该框架也广泛支持开发通用认证机制,例如JWT认证或其他常见的auth机制。Spring Security的成熟度尚未与Passport.js相匹配,但我认为Spring Security提供的80%的功能也是在Passport.js中实现的,有时候更简单。
从我的观点来看,Java中的ORM一直是Java应用程序的致命弱点。Java标准大致是Hibernate(尽管有各种各样的选择,无论多么广泛,如Jooq和MyBatis),而对于与关系数据库相关的JS世界,最受欢迎的库是Sequelize。
Hibernate与Sequelize
TL; DR:Hibernate仍然是最完整,最成熟,最通用的解决方案,但成本非常高!Sequelize可能会覆盖90%的用例。
我不讨厌Hibernate,但我肯定不喜欢它。它过于设计,缓慢而复杂。它就像一头大象。但是,它可以对任何受支持的数据库执行任何操作。相反,Sequelize小而简单但无法管理所有用例。
我通过使用Sequelize发现的一些事情:
1. 你会有一个不那么难,但绝对不是那么容易的时间尝试使用蛇案件的桌子的领域。您可以逐个手动指定它们(但这太过分了),或者您可以使用一些黑客将名称转换为蛇案例。这是一个简单的解决方案,但它的缺点在于它会破坏迁移命令行工具。无论如何,用于引入命名约定定义的灵活性的所有请求都被丢弃并被忽略是不可接受的。
2. 它不完全支持复合键。正如这里明确指出的那样 ,“虽然可以在Sequelize中创建复合主键,但Sequelize当前不支持复合外键,因此无法引用具有复合主键的模型/表。”从我的角度来看,这是不成熟的。
3. 由于时区解释,你必须做一些很好的技巧来管理日期字段(这真是出乎意料)。
4. 将实例添加到两个实体(例如Book和Author)之间相关的字段时,会立即保存实体。这并不是什么大不了的事,但表明Sequelize远不如Hibernate复杂,后者有内部机制来决定何时刷新数据。
在Sequelize中也有一些我喜欢的东西,比如在运行时创建查询的容易性(这是轻而易举的,你可以在运行时编写一个JSON对象并将其传递给查询引擎)。尝试在创建JPQL查询时执行此操作,或者考虑使用某些条件进行复杂化的过程。老实说,在尝试通过某些字段在运行时动态过滤查询时使用Hibernate和Spring Data JPA是一件很痛苦的事情,而在Sequelize中这很容易(应该用任何框架/语言)。
Sequelize在Hibernate方面闪耀的另一个方面是,当你遇到一些困难的情况并且需要进行本机查询时:它们都允许你执行本机查询,但老实说,将结果转换为模型更简单Sequelize比Spring Data JPA / Hibernate。
而且我不是在谈论启动时间:介绍Hibernate会增加启动时间,而Sequelize则非常直接。
作为最后的考虑,很明显:
1. Sequelize比Hibernate成熟得多,
2. Hibernate能够做任何事情,而Sequelize仅覆盖90%的用例。
3. Sequelize不那么抽象,而且更容易使用。
4. 这可能是一个很大的优势,特别是当您拥有数据库模式,不必适应遗留数据库,并且您不打算有一天迁移数据库引擎时(说实话,我只看到一个案例)数据库迁移在我的生活中,当两家银行决定合并时,因此决定只保留一个IT系统并将废弃的代码重写到另一个平台。有数千个存储过程需要重写,所以代码可移植性,在我看来,在谈论ORM时,是一个无用的功能。)
最后的考虑因素
我目前正在使用描述的JavaScript堆栈,目前我对它非常满意。 PricePaladin(一种价格跟踪和监控工具) 是使用上面提到的堆栈构建的,由于其内存占用少,目前已部署到廉价的服务器上。
使用JavaScript可以为您带来更高级的简单性。它是脚本和标准Web开发的理想选择,但我不会将它用于复杂项目(小型专用和隔离的微服务除外),也不会将它用于数字应用程序或数字计数的应用程序(如Java和Java的加密交换)它的 BigDecimal类非常适合该范围)。
最终,我在开发服务器端JavaScript时的一般感觉是,与基于Java的等效应用程序相比,一切都更简单,更简单,尽管我强烈认为缺乏稳定性和成熟度。用Java提供的库(只有当特定项目需要某些库时才缺乏实际,否则没有区别)。