原创作者: 许晓斌   阅读:61148次   评论:19条   更新时间:2011-06-23    
你是否早已厌倦了日复一日的手工构建工作?你是否对各个项目风格迥异的构建系统感到恐惧?Maven——这一Java社区事实标准的项目管理工具,能帮你从琐碎的手工劳动中解脱出来,帮你规范整个组织的构建系统。不仅如此,它还有依赖管理、自动生成项目站点等超酷的特性,已经有无数的开源项目使用它来构建项目并促进团队交流,每天都有数以万计的开发者在访问中央仓库以获取他们需要的依赖。 
《Maven实战》是国内第一本公开出版的Maven专著。它内容新颖,基于最新发布的Maven 3.0,不仅详尽讲解了Maven 3.0的所有新功能和新特性,而且还将这些新功能和新特性与Maven 2.x版本进行了对比,以便于正在使用Maven 2.x版本的用户能更好地理解。本书它内容全面,以从专家的角度阐释Maven的价值开篇,全面介绍了Maven的安装、配置和基本使用方法,以便于初学者参考;详细讲解了坐标和依赖、Maven仓库、生命周期和插件、聚合与继承等Maven的核心概念,建议所有读者仔细阅读;系统性地阐述了使用Nexus建立私服、使用Maven进行测试、使用Hudson进行持续集成、使用Maven构建Web应用、Maven的版本管理、Maven的灵活构建、生成项目站点和Maven的m2eclipse插件等实用性较强的高级知识,读者可有选择性的阅读;扩展性地讲解了如何Maven和Archetype插件,这部分内容对需要编写插件扩展Maven或需要编写Archetype维护自己的项目骨架以更便于团队开发的读者来说尤为有帮助。它实战性强,不仅绝大部分知识点都有相应的案例,而且本书还在第4章设计了一个背景案例,后面的很多章节都是围绕这个案例展开的,可操作性极强。 
本书适合所有Java程序员阅读,无论你是从未使用过Maven,亦或是已经使用Maven很长一段时间了,相信你都能从本书中获得有价值的参考。本书也适合所有项目经理阅读,它能帮助你更规范、更高效地管理Java项目。

</modelVersion>

  • <groupId>com.juvenxu.mvnbook</groupId>
  • <artifactId>hello-world</artifactId>
  • <version>章介绍如何使用Maven管理项目版本的升级发布。

    最后一个name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但我还是推荐为每个POM声明name,以方便信息交流。

    没有任何实际的Java代码,我们就能够定义一个Maven项目的POM,这体现了Maven的一大优点,它能让项目对象模型最大程度地与实际代码相独立,我们可以称之为解耦,或者正交性,这在很大程度上避免了Java代码和POM代码的相互影响。比如当项目需要升级版本时,只需要修改POM,而不需要更改Java代码;而在POM稳定之后,日常的Java代码开发工作基本不涉及POM的修改。

  • 3.2 编写主代码 

    项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包。默认情况下,Maven假设项目主代码位于src/main/java目录,我们遵循Maven的约定,创建该目录,然后在该目录下创建文件com/juvenxu/mvnbook/helloworld/HelloWorld.java,其内容如代码清单3-2:

    代码清单3-2:Hello World的主代码

    Java代码  
    1. <span style="font-size: small;"> source file to D: \code\hello-world\target\classes
    2. [INFO] ------------------------------------------------------------------------
    3. [INFO] BUILD SUCCESSFUL
    4. [INFO] ------------------------------------------------------------------------
    5. [INFO] Total time:  second
    6. [INFO] Finished at: Fri Oct  :: CST
    7. [INFO] Final Memory: 9M/16M
    8. [INFO] ------------------------------------------------------------------------
    9. </span>

    clean告诉Maven清理输出目录target/,compile告诉Maven编译项目主代码,从输出中我们看到Maven首先执行了clean:clean任务,删除target/目录,默认情况下Maven构建的所有输出都在target/目录中;接着执行resources:resources任务(未定义项目资源,暂且略过);最后执行compiler:compile任务,将项目主代码编译至target/classes目录(编译好的类为com/juvenxu/mvnbook/helloworld/HelloWorld.Class)。

    上文提到的clean:clean、resources:resources,以及compiler:compile对应了一些Maven插件及插件目标,比如clean:clean是clean插件的clean目标,compiler:compile是compiler插件的compile目标,后文会详细讲述Maven插件及其编写方法。

    至此,Maven在没有任何额外的配置的情况下就执行了项目的清理和编译任务,接下来,我们编写一些单元测试代码并让Maven执行自动化测试。

    3.3 编写测试代码 

    为了使项目结构保持清晰,主代码与测试代码应该分别位于独立的目录中。3.2节讲过Maven项目中默认的主代码目录是src/main/java,对应地,Maven项目中默认的测试代码目录是src/test/java。因此,在编写测试用例之前,我们先创建该目录。

    在Java世界中,由Kent Beck和Erich Gamma建立的JUnit是事实上的单元测试标准。要使用JUnit,我们首先需要为Hello World项目添加一个JUnit依赖,修改项目的POM如代码清单3-3:

    代码清单3-3:为Hello World的POM添加依赖

    Java代码  
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    5. http://maven.apache.org/maven-v4_0_0.xsd">
    6. <modelVersion></modelVersion>
    7. <groupId>com.juvenxu.mvnbook</groupId>
    8. <artifactId>hello-world</artifactId>
    9. <version> source file to D: \code\hello-world\target\classes
    10. [INFO] [resources:testResources {execution:  source file to D:\ code\hello-world\target\test-classes
    11. [INFO] ------------------------------------------------------------------------
    12. [ERROR] BUILD FAILURE
    13. [INFO] ------------------------------------------------------------------------
    14. [INFO] Compilation failure
    15. D:\code\hello-world\src\test\java\com\juvenxu\mvnbook\helloworld\HelloWorldTest.java:[,] -source  或更高版本以启用注释)
    16. source file to D: \code\hello-world\target\test-classes
    17. [INFO] [surefire:test {execution: , Failures: , Errors: , Skipped: , Time elapsed: , Failures: , Errors: , Skipped:
    18. [INFO] ------------------------------------------------------------------------
    19. [INFO] BUILD SUCCESSFUL
    20. [INFO] ------------------------------------------------------------------------

    我们看到compiler:testCompile任务执行成功了,测试代码通过编译之后在target/test-classes下生成了二进制文件,紧接着surefire:test任务运行测试,surefire是Maven世界中负责执行测试的插件,这里它运行测试用例HelloWorldTest,并且输出测试报告,显示一共运行了多少测试,失败了多少,出错了多少,跳过了多少。显然,我们的测试通过了——BUILD SUCCESSFUL。

    3.4 打包和运行 

    将项目进行编译、测试之后,下一个重要步骤就是打包(package)。Hello World的POM中没有指定打包类型,使用默认打包类型jar,我们可以简单地执行命令 mvn clean package 进行打包,可以看到如下输出:

    Java代码  
    1. Tests run: , Failures: , Errors: , Skipped:
    2. [INFO] [jar:jar {execution: </version>
    3. <executions>
    4. <execution>
    5. <phase>package</phase>
    6. <goals>
    7. <goal>shade</goal>
    8. </goals>
    9. <configuration>
    10. <transformers>
    11. <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">            <mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>
    12. </transformer>
    13. </transformers>
    14. </configuration>
    15. </execution>
    16. </executions>
    17. </plugin>

    plugin元素在POM中的相对位置应该在<project><build><plugins>下面。我们配置了mainClass为com.juvenxu.mvnbook.helloworld.HelloWorld,项目在打包时会将该信息放到MANIFEST中。现在执行 mvn clean install ,待构建完成之后打开target/目录,我们可以看到hello-world-1.0-SNAPSHOT.jaroriginal-hello-world-1.0-SNAPSHOT.jar,前者是带有Main-Class信息的可运行jar,后者是原始的jar,打开hello-world-1.0-SNAPSHOT.jarMETA-INF/MANIFEST.MF,可以看到它包含这样一行信息:

    Main-Class: com.juvenxu.mvnbook.helloworld.HelloWorld

    现在,我们在项目根目录中执行该jar文件:

    D: \code\hello-world>java -jar target\hello-world-1.0-SNAPSHOT.jar

    Hello Maven

    控制台输出为Hello Maven,这正是我们所期望的。

    本小节介绍了Hello World项目,侧重点是Maven而非Java代码本身,介绍了POM、Maven项目结构、以及如何编译、测试、打包,等等。

    3.5 使用Archetype生成项目骨架 

    Hello World项目中有一些Maven的约定:在项目的根目录中放置pom.xml,在src/main/java目录中放置项目的主代码,在src/test/java中放置项目的测试代码。我之所以一步一步地展示这些步骤,是为了能让可能是Maven初学者的你得到最实际的感受。我们称这些基本的目录结构和pom.xml文件内容称为项目的骨架,当你第一次创建项目骨架的时候,你还会饶有兴趣地去体会这些默认约定背后的思想,第二次,第三次,你也许还会满意自己的熟练程度,但第四、第五次做同样的事情,就会让程序员恼火了,为此Maven提供了Archetype以帮助我们快速勾勒出项目骨架。

    还是以Hello World为例,我们使用maven archetype来创建该项目的骨架,离开当前的Maven项目目录。

    如果是Maven 3,简单的运行:

    mvn archetype:generate

    如果是Maven 2,最好运行如下命令:

    mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate

    很多资料会让你直接使用更为简单的 mvn archetype:generate 命令,但在Maven2中这是不安全的,因为该命令没有指定archetype插件的版本,于是Maven会自动去下载最新的版本,进而可能得到不稳定的SNAPSHOT版本,导致运行失败。然而在Maven 3中,即使用户没有指定版本,Maven也只会解析最新的稳定版本,因此这是安全的,具体内容见7.7小节。

    我们实际上是在运行插件maven-archetype-plugin,注意冒号的分隔,其格式为groupId:artifactId:version:goal ,org.apache.maven.plugins 是maven官方插件的groupId,maven-archetype-plugin 是archetype插件的artifactId,2.0-alpha-5 是目前该插件最新的稳定版,generate是我们要使用的插件目标。

    紧接着我们会看到一段长长的输出,有很多可用的archetype供我们选择,包括著名的Appfuse项目的archetype,JPA项目的archetype等等。每一个archetype前面都会对应有一个编号,同时命令行会提示一个默认的编号,其对应的archetype为maven-archetype-quickstart,我们直接回车以选择该archetype,紧接着Maven会提示我们输入要创建项目的groupId、artifactId、 version、以及包名package,如下输入并确认:

    Java代码  
    1. Define value for groupId: : com.juvenxu.mvnbook
    2. Define value for artifactId: : hello-world
    3. Define value for version:  1.0-SNAPSHOT: :
    4. Define value for package:  com.juvenxu.mvnbook: : com.juvenxu.mvnbook.helloworld
    5. Confirm properties configuration:
    6. groupId: com.juvenxu.mvnbook
    7. artifactId: hello-world
    8. version: 1.0-SNAPSHOT
    9. package: com.juvenxu.mvnbook.helloworld
    10. Y: : Y

    Archetype插件将根据我们提供的信息创建项目骨架。在当前目录下,Archetype插件会创建一个名为hello-world(我们定义的artifactId)的子目录,从中可以看到项目的基本结构:基本的pom.xml已经被创建,里面包含了必要的信息以及一个junit依赖;主代码目录src/main/java已经被创建,在该目录下还有一个Java类com.juvenxu.mvnbook.helloworld.App,注意这里使用到了我们刚才定义的包名,而这个类也仅仅只有一个简单的输出Hello World!的main方法;测试代码目录src/test/java也被创建好了,并且包含了一个测试用例com.juvenxu.mvnbook.helloworld.AppTest

    Archetype可以帮助我们迅速地构建起项目的骨架,在前面的例子中,我们完全可以在Archetype生成的骨架的基础上开发Hello World项目以节省我们大量时间。

    此外,我们这里仅仅是看到了一个最简单的archetype,如果你有很多项目拥有类似的自定义项目结构以及配置文件,你完全可以一劳永逸地开发自己的archetype,然后在这些项目中使用自定义的archetype来快速生成项目骨架,本书后面的章节会详细阐述如何开发Maven Archetype。

    3.6 m2eclipse简单使用 

    介绍前面Hello World项目的时候,我们并没有涉及IDE,如此简单的一个项目,使用最简单的编辑器也能很快完成,但对于稍微大一些的项目来说,没有IDE就是不可想象的,本节我们先介绍m2eclipse的基本使用。

    3.6.1 导入Maven项目

    第2章介绍了如何安装m2eclipse,现在,我们使用m2ecilpse导入Hello World项目。选择菜单项File,然后选择Import,我们会看到一个Import对话框,在该对话框中选择General目录下的Maven Projects,然后点击Next,就会出现Import Projects对话框,在该对话框中点击Browse…选择Hello World的根目录(即包含pom.xml文件的那个目录),这时对话框中的Projects:部分就会显示该目录包含的Maven项目,如图3-1所示:

    图3-1 在Eclipse中导入Maven项目

    点击Finish之后,m2ecilpse就会将该项目导入到当前的workspace中,导入完成之后,我们就可以在Package Explorer视图中看到如图3-2所示的项目结构:

    图3-2 Eclipse中导入的Maven项目结构

    我们看到主代码目录src/main/java和测试代码目录src/test/java成了Eclipse中的资源目录,包和类的结构也十分清晰,当然pom.xml永远在项目的根目录下,而从这个视图中我们甚至还能看到项目的依赖junit-4.7.jar,其实际的位置指向了Maven本地仓库(这里我自定义了Maven本地仓库地址为D:\java\repository,后续章节会介绍如何自定义本地仓库位置)。

    3.6.2 创建Maven项目

    创建一个Maven项目也十分简单,选择菜单项File -> New -> Other,在弹出的对话框中选择Maven下的Maven Project,然后点击Next >,在弹出的New Maven Project对话框中,我们使用默认的选项(不要选择Create a simple project选项,那样我们就能使用Maven Archetype),点击Next >,此时m2eclipse会提示我们选择一个Archetype,我们选择maven-archetype-quickstart,再点击Next >。由于m2eclipse实际上是在使用maven-archetype-plugin插件创建项目,因此这个步骤与上一节我们使用archetype创建项目骨架类似,输入groupId,、artifactId、version、package(暂时我们不考虑Properties),如图3-3所示:

    图3-3 在Eclipse中使用Archetype创建项目

    注意,为了不和前面已导入的Hello World项目产生冲突和混淆,我们使用不同的artifactId和package。OK,点击Finish,Maven项目就创建完成了,其结构与前一个已导入的Hello World项目基本一致。

    3.6.3 运行mvn命令

    我们需要在命令行输入如mvn clean install之类的命令来执行maven构建,m2eclipse中也有对应的功能,在Maven项目或者pom.xml上右击,再选择Run As,就能看到如下的常见Maven命令,如图3-4所示:

    图3-4 在Eclipse中运行默认mvn命令

    选择想要执行的Maven命令就能执行相应的构建,同时我们也能在Eclipse的console中看到构建输出。这里常见的一个问题是,默认选项中没有我们想要执行的Maven命令怎么办?比如,默认带有mvn test,但我们想执行mvn clean test,很简单,选择Maven buid… 以自定义Maven运行命令,在弹出对话框中的Goals一项中输入我们想要执行的命令,如clean test,设置一下Name,点击Run即可。并且,下一次我们选择Maven build,或者使用快捷键Alt + Shift + X, M快速执行Maven构建的时候,上次的配置直接就能在历史记录中找到。图3-5就是自定义Maven运行命令的界面:

    图3-5 在Eclipse中自定义mvn命令

    3.7 NetBeans Maven插件简单使用 

    NetBeans的Maven插件也十分简单易用,我们可以轻松地在NetBeans中导入现有的Maven项目,或者使用Archetype创建Maven项目,我们也能够在NetBeans中直接运行mvn命令。

    3.7.1 打开Maven项目

    与其说打开Maven项目,不如称之为导入更为合适,因为这个项目不需要是NetBeans创建的Maven项目,不过这里我们还是遵照NetBeans菜单中使用的名称。

    选择菜单栏中的文件,然后选择打开项目,直接定位到Hello World项目的根目录,NetBeans会十分智能地识别出Maven项目,如图3-6所示:

    图3-6 在NetBeans中导入Maven项目

    Maven项目的图标有别于一般的文件夹,点击打开项目后,Hello World项目就会被导入到NetBeans中,在项目视图中可以看到如图3-7所示的项目结构:

    图3-7 NetBeans中导入的Maven项目结构

    NetBeans中项目主代码目录的名称为源包,测试代码目录成了测试包,编译范围依赖为,测试范围依赖为测试库,这里我们也能看到pom.xml,NetBeans甚至还帮我们引用了settings.xml。

    3.7.2 创建Maven项目

    在NetBeans中创建Maven项目同样十分轻松,在菜单栏中选择文件,然后新建项目,在弹出的对话框中,选择项目类别为Maven,项目为Maven项目,点击“下一步”之后,对话框会提示我们选择Maven原型(即Maven Archtype),我们选择Maven快速启动原型(1.0,(即前文提到的maven-archetype-quickstart),点击“下一步”之后,输入项目的基本信息,这些信息在之前讨论archetype及在m2eclipse中创建Maven项目的时候都仔细解释过,不再详述,如图3-8所示:

    图3-8 在NetBeans中使用Archetype创建Maven项目

    点击完成之后,一个新的Maven项目就创建好了。

    3.7.3 运行mvn命令

    NetBeans在默认情况下提供两种Maven运行方式,点击菜单栏中的运行,我们可以看到生成项目清理并生成项目两个选项,我们可以尝试“点击运行Maven构建”,根据NetBeans控制台的输出,我们就能发现它们实际上对应了mvn installmvn clean install两个命令。

    在实际开发过程中,我们往往不会满足于这两种简单的方式,比如,有时候我们只想执行项目的测试,而不需要打包,这时我们就希望能够执行mvn clean test命令,所幸的是NetBeans Maven插件完全支持自定义的mvn命令配置。

    在菜单栏中选择工具,接着选择选项,在对话框中,最上面一栏选择其他,下面选择Maven标签栏,在这里我们可以对NetBeans Maven插件进行全局的配置(还记得第2章中我们如何配置NetBeans使用外部Maven么?)。现在,选择倒数第三行的编辑全局定制目标定义,我们添加一个名为Maven Test的操作,执行目标为clean test,暂时不考虑其他配置选项,如图3-9所示:

    图3-9 在NetBeans中自定义mvn命令

    点击“缺省保存该配置”,在Maven项目上右击,选择定制,就能看到刚才配置好的Maven运行操作,选择Maven Test之后,终端将执行mvn clean test。值得一提的是,我们也可以在项目上右击,选择定制,再选择目标再输入想要执行的Maven目标(如clean package),点击确定之后NetBeans就会执行相应的Maven命令。这种方式十分便捷,但这是临时的,该配置不会被保存,也不会有历史记录。

    3.8 小结 

    本章以尽可能简单且详细的方式叙述了一个Hello World项目,重点解释了POM的基本内容、Maven项目的基本结构、以及构建项目基本的Maven命令。在此基础上,还介绍了如何使用Archetype快速创建项目骨架。最后讲述的是如何在Eclipse和NetBeans中导入、创建及构建Maven项目。

    《Maven实战》的更多相关文章

    1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

      最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

    2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

      前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

    3. 外网访问内网Docker容器

      外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

    4. 外网访问内网SpringBoot

      外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

    5. 外网访问内网Elasticsearch WEB

      外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

    6. 怎样从外网访问内网Rails

      外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

    7. 怎样从外网访问内网Memcached数据库

      外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

    8. 怎样从外网访问内网CouchDB数据库

      外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

    9. 怎样从外网访问内网DB2数据库

      外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

    10. 怎样从外网访问内网OpenLDAP数据库

      外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

    随机推荐

    1. appium+python自动化34-获取元素属性get_attribute

      获取text # coding:utf-8 from appium import webdriver from time import sleep desired_caps = { 'platform ...

    2. SpringMVC中注解控制器及数据绑定

      一.Spring2.5之前,我们都是通过实现Controller接口或其他实现来定义我们的处理器类. 二.Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMap ...

    3. lnmp环境应用实践

      LNMP 用户通过浏览器输入域名请求nginx web服务,如果请求时静态资源,则由nginx解析返回给用户:如果是动态请求(.php结尾),那么nginx就会把它通过FastCGI接口(生产常用方法 ...

    4. 大白话系列之C#委托与事件讲解大结局

      声明:本系列非原创,因为太精彩才转载,如有侵权请通知删除,原文:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html 今天 ...

    5. jQuery笔记——UI

      jQuery UI 的官网网站为:http://jqueryui.com/,我们下载最新版本的即可,使用JQueryUI中的样式比我们使用原生的HTML要好看,还会有一些封装好的特效,JQueryUI ...

    6. Histogram

      folly/Histogram.h Classes Histogram Histogram.h defines a simple histogram class, templated on the t ...

    7. JAVA for循环语句的循环变量类型问题

      class HalfDollars { public static void main(String [] arguments) { int[] denver = {1_900_000,1_700_0 ...

    8. 上传图片demo

      页面: js: 后台: @RequiresPermissions("pointwall:upload:edit") @RequestMapping(value = "sa ...

    9. 升级oracle 9i到10g

      从9i升级到10g两个方案可供选择:   一是利用oracle提供的一个升级实用程序dbua(database upgrade assistant)直接将9i的数据库升级到10g. 再有就是新建一个1 ...

    10. TypeScript--deno前置学习

      第一节:前言: 1.JavaScript 的发展简史图: 2.关于node与deno: (1)Node与Deno 的区别:Node 可以工作,而 Deno 不行,Deno 只是一个原型或实验性产品. ...