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:在完成一个签约项目之后,我决定测试另一个生态系统来检查它是b2b信息网否可以避免一些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提供的库(只有当特定项目需要某些库时才缺乏实际,否则没有区别)。
另一种看法是JavaScript开发周期快了约20%。通过这种方式,我的意思是,由于更复杂的代码和过度设计的Java应用程序结构遵循经典指南和重建代码所花费的时间,因此您在Java中开发相同功能的时间比在JavaScript中花费的时间多得多。
因此,在应用程序不提供计算或阻塞处理的情况下,并且关注经典的小型Web应用程序的开发,我几乎肯定会选择使用所描述的JavaScript堆栈进行开发,而在其他情况下,我会将应用程序基于从长远来看,我认为Spring Boot堆栈提供了更强的可维护性。



![假定你想要在你的家庭/办公网络中设置一台Linux打印服务器,而你手头上却只有USB打印机可用(因为他们比那些有着内建网络接口或无线模块的打印机要便宜得多)。此外,假如这些设备中有一台是一体化的,而你也想要通过网络共享其整合的扫描仪,这该怎么办?在本文中,我将介绍怎样安装并共享一台USB一体机(Epson CX3900喷墨打印机和扫描仪),一台USB激光打印机(Samsung ML-1640),以及作为锦上添花,配置一台PDF打印机。所有这一切,我们都将在GNU/Linux Debian 7.2 [Wheezy]服务器中实现。尽管这些打印机看起来有点老旧了(我是在2007年买的Epson一体机,2009年买的激光打印机),但我仍然相信我从安装过程中学到的东西也一样能应用到该品牌的新产品和其它品牌中去:有一些预编译的.deb包驱动可用,而其它驱动可以从仓库中直接安装。毕竟,它是重要的基本原则。先决条件 要设置网络打印机和扫描仪,我们将使用CUPS,它是一个用于Linux/UNIX/OSX的开源打印系统。# aptitude install cups cups-pdf 排障提示:根据你的系统状况(这个问题很可能在手动安装包失败后,或者缺少依赖包的时候会发生),在安装cups和cups-pdf前端包管理系统可能会提示你卸载许多包以尝试解决当前依赖问题。假如这种情况真的发生,你只有两个选择:1)通过另外一个前端包管理系统安装包,如apt-get。注意,并不建议进行这样的处理,因为它不会解决当前的问题。2)运行以下命令:aptitude update && aptitude upgrade。该命令会修复此问题,并同时更新包到最新版本。配置CUPS 为了能够访问CUPS的网页接口,我们需要至少对cupsd.conf文件(用于CUPS的服务器配置文件)进行一次最低限度的修改。在进行修改前,让我们为cupsd.conf做个备份副本:# cp cupsd.conf cupsd.conf.bkp 然后,编辑原始文件(下面只显示了最为有关联的部分):Listen:监听指定的地址和端口,或者域套接口路径。Location /path:为该名字所代表的位置指定访问控制。Order:指定HTTP访问控制顺序(allow,deny或deny,allow)。Order allow,deny是说允许规则先于(并且优先处理)拒绝规则。DefaultAuthType (也可以用AuthType): 指定默认使用的认证类型。Basic是指使用/etc/passwd文件来认证CUPS中的用户。DefaultEncryption:指定认证请求所使用的加密类型。WebInterface:指定是否启用网页接口。    # Listen for connections from the local machine    Listen 192.168.0.15:631    # Restrict access to the server          Order allow,deny      Allow 192.168.0.0/24        # Default authentication type, when authentication is required    DefaultAuthType Basic    DefaultEncryption IfRequested    # Web interface setting    WebInterface Yes    # Restrict access to the admin pages          Order allow,deny      Allow 192.168.0.0/24    现在,让我们重启CUPS来应用修改:# service cups restart 为了允许另外一个用户(除了root之外)修改打印机设置,我们必须像下面这样添加他/她到lp(授权对打印机硬件的访问并启用用户管理打印任务)和lpadmin(拥有打印优先)组。假如在你当前网络设置没有必要或不需要该设置,你可以不用理会该步骤。# adduser xmodulo lp# adduser xmodulo lpadmin 通过网页接口配置网络打印机 1、 启动网页浏览器,并打开CUPS接口http://:Port,这里在我们的例子中是http://192.168.0.15:631:2、 转到管理标签,然后点击添加打印机:3、 选择你的打印机;在本例中,EPSON Stylus CX3900 @ debian (Inkjet Inkjet Printer),然后点击继续:4、 是时候为打印机取个名字,并指定我们是否想要从当前工作站共享它:5、 安装驱动——选择品牌并点击继续。6、 假如打印机假如不被CUPS支持(没有在下一页中列出来),我们必须从生产厂家的网站上下载驱动(如http://download.ebz.epson.net/dsc/search/01/search/ OSC=LX),安装完后回到该页。7、 注意,预编译的.deb文件必须从我们使用的机器上发送(例如,通过sftp或scp)到打印服务器(当然,假如我们有一个直接的下载链接就更加简单了,而不用下载按钮了):8、 在将.deb文件放到服务器上后,我们就可以安装了: # dpkg -i epson-inkjet-printer-escpr_1.4.1-1lsb3.2_i386.deb 排障提示:假如lsb包(一个第三方Linux应用编写者可以依赖标准核心系统)没有安装,那么驱动会无法安装:我们将安装lsb,然后尝试再次安装打印机驱动:# aptitude install lsb# dpkg -i epson-inkjet-printer-escpr_1.4.1-1lsb3.2_i386.deb9、 现在,我们可以返回到第五步并安装打印机:配置网络扫描仪 现在,我们将继续配置打印机服务器来共享扫描仪。首先,安装xsane,这是SANE——扫描仪快捷访问的前端:# aptitude install xsane 接下来,让我们编辑/etc/default/saned文件以启用saned服务:# Set to yes to start saned                                                     RUN=yes最后,我们将检查saned是否已经在运行了(很可能不在运行哦——那么我们将启动服务并再来检查):# ps -ef | grep saned | grep -v grep# service saned start 配置另一台网络打印机 通过CUPS,你可以配置多台网络打印机。让我们通过CUPS配置一台额外的打印机:Samsung ML-1640,它是一台USB打印机。splix包包含了单色(ML-15xx, ML-16xx, ML-17xx, ML-2xxx)和彩色(CLP-5xx, CLP-6xx)Samsung打印机驱动。此外,此包的详细信息中指出,一些新命名的Samsung打印机,如Xerox Phaser 6100也适用此驱动。# aptitude install splix 然后我们将使用CUPS网页接口来安装打印机,就像前面一样:安装PDF打印机 接下来,让我们在打印服务器上配置一台PDF打印机。这样,你就可以将来自客户计算机的文档转换成PDF格式了。由于我们已经安装了cups-pdf包,PDF打印机就已经自动安装好了,可以通过网页接口验证:当选定PDF打印机后,文档将被写入可配置目录(默认是~/PDF),或者也可以通过后续处理命令进行复制。在下一篇文章中,我们将配置桌面客户端来通过网络访问打印机和扫描仪。](http://www.bgvu.cn/uploads/2025-10-24/1761274639117.png)

