几年来,我一直很沮丧的基于java的构建工具项目。 在我的工作中,我看到几个Java项目和模块使用不同的构建系统。 值得庆幸的是,我所见过的大多数项目都是建立在过去一年Maven或Gradle。 根据这一趋势,您只需要知道两个不同的系统来了解项目的基本结构和依赖关系。 我不想给所有构建系统的概述,目前可以用于定义构建的一个基于Java的项目,我认为他们都很容易分裂成两个不同的类型:
- 基于脚本的构建系统。
- 配置为基础构建系统。
目前,Maven和Gradle最著名的构建系统,他们每个人的类型有关。 让我们有一个更深的看着他们两人。
关于它
从我的观点来看,它是一个基于脚本的构建系统。 对于这样一个构建系统,您可以定义您自己的基于命令或一个API的任务。 在它,你可以编写自定义构建任务很容易使用Groovy。 它提供了一些基本的插件为共同构建Java项目的工作流程。 在此基础上,你不需要定义任何任务,像Java的编译为每个项目来源,一遍又一遍。 但是由于它是基于任务,可以很容易地构建脚本中定义的,你没有任何结构或最佳实践应该如何定义结构构建脚本和应该如何定义信息,如项目名称或一个项目的依赖关系。 别误会我的意思:它提供了良好的api,但它是由开发人员决定在构建脚本,例如,定义项目的依赖关系。 此外,你总是需要运行构建脚本得到关于项目的信息。
对于Maven
Maven在基于脚本的构建工具的功能非常有限。 所有的项目信息和如何构建它必须指定pom.xml文件。 在内部,您可以配置使用XML语法项目和构建。 所有的可能性,你必须配置项目的定义Maven在XSD文件。 通过这样做,很容易定义的静态元数据项目名称或项目描述。 甚至技术信息像groupId,artifactId、版本或静态依赖关系可以很容易地定义的。 通过使用Maven构建工具,您的项目将被建立一个最佳实践工作流程构建Java项目中定义的多个任务。 对于小项目来说这是可以和api,但是如果你需要做一些特别的事情,你需要将插件添加到Maven。 这样一个插件必须定义为您的项目通过使用Maven的有限的XML语法。 这种插件必须的功能用Java编写的并提供了一个罐子。 大而复杂的项目,你需要几个永远结束在一个大的这些项目和读取XML文件作为描述和构建您的项目的定义。
结论
一点,值得庆幸的是,这两种方法的共同点是依赖性的方式将得到解决。 Maven和Gradle将下载(传递)从任何构件库的依赖关系。 Maven使用Maven中央这里作为默认Gradle用途JCenter。 此外,其他存储库(如私人公司存储库)可以很容易地定义的。 因为工件库遵循一些共同的标准,所有提到的存储库可以很容易地用于Maven或Gradle。
另一方面,这两个工具/构建系统有一些大的缺点在我看来。 很容易在Maven中定义项目元数据和依赖关系,但这绝对是可怕的创建高度定制的构建与Maven。 如果你想创建asciidoc-based文档或上传最终工件到Java EE服务器。 你的POM文件很快就会变得不可读。 的Maven pom的Hazelcast项目例如,超过1000行。 理解一个1000行基于xml的新开发人员构建定义可以是非常令人沮丧的。 所以,Maven是漂亮的小模块和api,比如Apache commons或GSON。 开发人员可以快速地了解项目及其依赖项只需看看POM文件。 此外,工具不需要运行构建流程/脚本获取信息。 POM文件可以被解析。
Gradle,另一方面,提供了很大的灵活性。 因为它是基于一个脚本,你可以做几乎一切,并支持自定义比Maven构建步骤要容易得多。 这很好如果你想要部署到服务器或创建你的工件,例如,文档。 但基于灵活性,构建脚本可能会变得复杂起来。 在大多数大型Java项目我已经看到在过去的几年里,只有少数开发人员知道如何改变它的构建。 此外,任何工具都需要运行Gradle构建项目的基本信息。 自从Gradle构建脚本是基于一种脚本语言,无法解析。 所以,最后,Gradle可悲的不是用于构建Java项目的完美的解决方案。
在此基础上,我想说,目前,没有Java构建工具是所有基于Java项目的完美的解决方案。 Maven太有限但伟大的小型项目,按照定义的Maven生命周期和定义。 Gradle,另一方面,可以做你想做的一切,但甚至在其定义小型项目可能不同,因为结构/可以定义您的构建描述以任何方式。 此外,您需要运行构建接收关于项目的信息。
基于这些观点,我认为,有一种方法的好处是简单的总和。 当有一个看构建系统JavaScript,你可以看到一个不同。 现代JavaScript构建系统狼吞虎咽地吃、工作或多或少地喜欢它。 你可以很容易地定义您自己的自定义任务基于脚本语言。 此外,元数据中定义的项目通常是一个单独的文件中。 大多数项目,我看到过去的几个月里使用鲍尔定义项目的静态元数据。 这包括项目的描述(名称、描述、许可证等)及其依赖项。 构建工具像杯现在可以使用鲍尔建造项目的信息(是的,这是一个非常简单的描述的内部流程)。 在此基础上,我问自己为什么Gradle,例如,不能做同样的事情。 让我们考虑一个静态定义Java项目和模块,可以很容易地集成到一个Gradle或Maven构建。 因为这样的定义将使用这两个工具都是开发人员轻松的学习如何阅读和使用这样一个静态的定义。 此外,工具不需要任何外部过程开始,像一个构建脚本,获得关于Java项目的信息。 对于完整的项目,您可以简单地创建自定义Gradle内部任务得到的所有信息的静态定义和重用它真正的建立。
下面,我将尝试素描这样的静态定义的样子和它如何可以使用。
定义一个静态模块描述
一个静态模块定义应该包含一个可读的描述模块。 这应该包括几个参数:
- 模块名称
- 模块描述
- 许可证
- url(回购问题跟踪器、医生等)。
- 开发人员信息(姓名、邮件等等)。
基于这个信息模块描述可能看起来像这样:
除了这些信息,一个项目需要一个惟一的标识符。 这可以很容易地定义的groupId artifactId,所以静态定义应该重用这些属性:
定义一个特定版本的一个项目,versionId应该添加。 基于这些信息,提供的一切Maven中央或JCenter被定义的模块。 此外,Maven pom。 xml可以很容易地创建基于这些信息,可以依赖这个模块和其他模块。 后添加的属性。 一个静态项目定义可能看起来像这样:
编译Java模块,我们需要一些额外的信息。 我认为最基本的信息是源编码和应该用于编译的Java版本。 在这里,我们需要指定一个Java版本定义所需的最低版本编译的来源和定义的Java版本,编译目标版本。 将这些信息添加到一个模块的描述可能会在以下文件:
基于这些信息,一个项目,不需要额外的类类路径中的下一个基本的Java类可以很容易地进行编译。 自完成模块定义中提供了一个静态方法,这可以很容易地集成到任何支持IDE或构建工具。
由于大多数项目取决于外部api和模块,静态模块定义应该提供信息模块的依赖关系。 像在Maven或Gradle,基于artifactId依赖项的定义,groupId,版本是最好的方法。 在编译、构建工具或IDE可以轻易下载从Maven中央或JCenter(传递)的依赖关系。 静态项目定义主要应该提供所有功能的Maven依赖的定义,但在大多数用例,简单地添加所需的依赖关系是所有你需要。 通过添加依赖关系信息,一个模块的定义是这样的:
ava模块定义为这样一个静态结构必须遵循的一些最佳实践和基本规则,从Maven和Gradle-based是众所周知的项目:
- 所有Java源必须被放置在src / main / Java。
- 所有资源,如图片或配置文件,必须放置在src / main /资源。
- 所有Java源单元测试必须放置在src /测试/ Java。
- 单元测试的所有资源都必须放在src /测试/资源。
- 的静态定义基于utf - 8的文件中定义的项目必须在项目的根文件夹。 该文件必须命名为“元数据。
jmm:(jmm代表Java模块元数据)。
我为什么要用这个吗?
你们大多数人已经在使用Maven这样的构建工具,它,或者Ant来定义构建的Java项目。 我认为这是好的,应该使用在未来,。 尤其是当使用它,这是最新的构建工具所提到的,开发人员有这么多可能要创建一个自定义构建文件,通常每个构建作品以不同的方式,很难了解构建过程。 在所有这些文件中,关于构建过程的信息(比如一个构建脚本)和元数据的一个项目是混合。 通过封装从构建的元数据,这将是更容易得到一个模块或一个构建的总体概述。 此外,每个构建文件或脚本取决于使用的构建系统。 这意味着开发人员总是使用Maven经常不能读或解释Gradle构建脚本。 tool-independent方式通过定义元数据,任何Java项目的开发人员可以理解的信息一旦他们至少有一个项目工作,提供静态元数据。 元数据不仅为开发人员提供更好的可读性,但构建工具可以解释元数据提供支持。 通过这样做,所有的元数据文件的一部分的信息不应该被重新定义的构建脚本。 构建工具可以直接使用元数据文件中的信息来构建项目。 Gradle文件通过这样做,可以构建一个JAR文件基于静态元数据描述的模块:
这将是足够的编译所有的项目来源,运行所有单元测试,并构建一个JAR,他的名字叫artifactId和版本创建的元数据文件。
旁边的通用构建工具的ide可以提供支持的静态模块的元数据。 在这种情况下,您甚至不需要一个构建脚本。 基于的信息可以在元数据中定义,IDE可以下载所需的所有依赖项,编译项目的来源,并运行所有单元测试。 而这仅仅是开始。 基于这种方法,它可以扫描所有Java项目在GitHub,GitLab,BitBucket都找到一个模块的使用。
提供一个图形化的概述的传递依赖模块将容易,。 而不是运行Gradle建立接收信息的依赖,任何工具可以简单地解析静态元数据。 一个构建工具甚至没有安装。 构建工具和ide,其他工具如构建服务器将受益于这种方法。
曾经最重要的工具支持静态元数据,主要是所有Java项目的维护将变得更加容易。 方面喜欢定义的版本将只有一个焦点,和改变释放的版本将会很容易。
方法的局限性
静态元数据并不适用于每个项目。 一些项目需要在运行时生成的来源或动态依赖关系。 对于这类项目,静态元数据可能不足以编译项目。 但即使在这里,这样的元数据定义并不是无用的。 可读元数据可以指定名称或许可和非动态的所有依赖项,这些元数据文件的一部分,。 这将结束在需要构建文件的代码,和工具,解释静态元数据至少可以处理项目描述的一个子集。 是的,这种方法目前没有可用的项目是基于另一个编程语言,比如芬兰湾的科特林或Groovy。 但随着说:这只是一个初步的想法,我想要你的想法关于这个话题。