走进JavaWeb技术世界12从手动编译打包到项目构建工具Maven

37次阅读

共计 14566 个字符,预计需要花费 37 分钟才能阅读完成。

微信公众号【黄小斜】大厂程序员,互联网行业新知,终身学习践行者。关注后回复「Java」、「Python」、「C++」、「大数据」、「机器学习」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「笔试」、「面试」、「面经」、「计算机基础」、「LeetCode」等关键字可以获取对应的免费学习资料。

                     

小李的 Build 之路(上)

转自:刘欣 码农翻身 2016-07-10

  • 摘要:手工 Build 的烦恼要不是为了和女朋友留在一个城市, 小李肯定去北上广奋斗去了。现在他只能留在这个 2.5 线城市, 进入这家软件开发公司,7,8 个人,10 来条枪, 是个典型的软件小作坊。上班第一天,CTO 兼架构师兼项目经理兼开发组长老张把小李叫去, 谆谆教导说:“小李啊, 我看了你的简历, 我对你在公司的发展还是挺看好的, 不过作为新人, 你对新业务还不熟悉, 没法开发核心系统, 这段时间, 你要一边学习, 一边帮着项目做个很重要的工作:Build“小李心说你还给我拽英语啊, 虽然心里这么想, 小李还是不
  • 手工 Build 的烦恼

    要不是为了和女朋友留在一个城市, 小李肯定去北上广奋斗去了。

    现在他只能留在这个 2.5 线城市, 进入这家软件开发公司,7,8 个人,10 来条枪, 是个典型的软件小作坊。

    上班第一天,CTO 兼架构师兼项目经理兼开发组长老张把小李叫去, 谆谆教导说:

    “小李啊, 我看了你的简历, 我对你在公司的发展还是挺看好的, 不过作为新人, 你对新业务还不熟悉, 没法开发核心系统, 这段时间, 你要一边学习, 一边帮着项目做个很重要的工作:Build“

    小李心说你还给我拽英语啊, 虽然心里这么想, 小李还是不动声色, 面带微笑的问:

    “这 Build 是什么东西?”

    老张说:“我非常忙, 没时间给你解释, 这儿有个文档, 你看看就知道了”

    说着, 老张甩给了他几张纸 , 补充到:“有问题问小王, 他比你早来一个月, 做 Build 已经很熟了”

    小李仔细看了一遍, 上面写着:

    XXX 公司 Build 流程 (测试环境)

    (1) 设置 Eclipse 工作区, 编码为 UTF-8, java 编译级别为 JDK 1.7

    (2) 从 SVN 下载最新源代码到 Eclipse 工作区

    (3) 确保 Eclispe 工作区没有编译错误

    (4) 手工修改下面 20 个 配置文件

    database.properties

    cache.properties

    user.properties

    。。。。。。

    (5) 把 Eclipse 中的 Web 项目导出成 War 包

    小王还特别在这里用红色的笔加了标注: Web 项目所依赖的其他 java 项目也会被自动包含到 War 包的 WEB-INF/lib 目录下

    (6) 上传到测试服务器, 安装

    (7) 做冒烟测试

    小李笑了: 这不就是一个编译, 打包, 部署, 测试的流程吗? 还 Build !

    正在这时, 开发骨干小梁叫小李了:“小李, 我改了几个 Bug, 马上要测试, 赶紧给我做一个测试环境的 Build”

    小李不敢怠慢, 立刻按照文档做了一遍, 花了将近半个小时才折腾完。

    可是到了最后一步, 做冒烟测试的时候, 系统却启动不了了 !

    小李查了好久才发现, 原来测试环境的 JDK 是 1.6 , 但是 Build 文档上写的是 1.7 当然跑不起来了。

    小李暗暗的骂前任小王: 你小子肯定知道这里有个坑, 怎么不在文档上标注出来?

    赶紧做个新的 Build 放到测试环境, 这次冒烟测试顺利通过了。

    刚松了口气, 测试小赵就叫了起来:“小梁, 你那个 Bug 没有修复啊”

    开发骨干小梁本能的反应到:“这不可能! 我的代码本地都测试过了, 代码也提交了“

    小梁接着把矛头就指向小李:“哎对了小李, 你的 Build 是不是又搞错了。”

    小李心头一惊 , 赶紧去查, 果然, 在第 4 步, 手工修改配置文件的时候把数据库改错了 , 指向了开发库, 而不是测试库。

    赶紧改吧, 原来做 Build 的小王也跑过来凑热闹, 在前 Build 专员小王, 开发小梁和测试小赵三双眼睛的严厉注目下, 小李头上都要冒汗了。

    还好, 第三次终于成功了。所有的测试都顺利通过。

    (实际上, 小李在紧张的忙碌中也忘了去更新那个文档, 把 JDK 改成 1.6)

    就这样过了一周, 小李每天都得战战兢兢的做四五个 Build, 虽然做的越来越熟, 出错越来越少, 但是每天还是占用了不少时间。

    大好年华就要在 Build 中蹉跎了吗, 坚决不行。

    自动化 Build

    小李决定把这个手工的、费事的、容易出错的 Build 给自动化起来, 将来谁要是做测试环境的 Build, 只要运行一个命令即可。

    用什么语言来实现呢? 当然是 Java 大法好 ! 小李在大学修炼了那么久, 自认为对 OO, 设计模式已经炉火纯青了, 现在终于有了用武之地。

    小李白天工作, 晚上回到住处就开发这个自动化的 Build, 每天干到 12 点才罢休。

    但是小李不觉得累, 每天都恋恋不舍的去上床睡觉, 因为创造一个新工具, 造福大家的想法一直激励着自己, 有时候甚至觉得很快乐。

    一个月后, 自动化工具新鲜出炉, 这其实是一套 Java 的 API, 小李把它称为 BuildTool V1.0 专门用于下载源码, 编译, 打包, 部署, 测试。

    例如, 如果你想编译 java 代码, 可以这么写:

    小李对于 FileSet 这个抽象很得意, 它能代表一个文件集合, 既可以是 java 源文件路径, 也可以是 classpath 的路径。

    其他的 API 像下载源码, 打包, 部署, 测试也是类似。

    现在小李真的只需要运行一个命令, 就可以为测试环境生成一个 build :

    java BuildTool test

    工作量一下子少了好多, 并且机器运行, 基本上不会出错。

    小李因为这个自动化的 BuildTool, 获得的公司的嘉奖, 还涨了一点工资。

    对小李来说, 这都不是最重要的, 最重要的通过设计和实现这个 BuildTool, 自己的能力有了很大的提升。

    自己已经 不仅仅是一个只会用 SSH 框架的一个 HTML 填空人员了!

    码农翻身评: 大部分人只会抱怨项目很无趣, 没有挑战, 遇到问题也只会安于现状,

    少数人会发现工作中的“痛点”问题, 并且真正动手解决它, 给公司带来了价值, 这是提高自己, 让自己和别人区分开来的重要方法。

    JAVA vs XML

    今年的形势很好, 公司业务发展的不错, 招了一批新人, 一下子接了 3,4 个新项目, 小李主动请缨, 替这些项目建立一个自动化的 Build。

    但是小李很快就发现了问题, 直接用 Java 语言来编写, 功能虽然能实现, 但是看起来就太繁琐了。

    自己写的代码过几天看也得思考一下才能明白。

    是自己的 BuildTool API 设计的不好吗? 那可是精心设计的啊。

    仔细思考了两天, 小李终于意识到了问题所在: 不是自己设计的不好, 是 Java 语言太“低级”了 !

    自动化 Build 要描述的其实是任务, 是业务层面的东西。

    而用 java 是个什么都能干的通用语言, 用它来写肯定引入了太多的细节, 导致了阅读和编写的难度!

    小李想: 能不能开发一套新的, 专门为自动化 Build 所使用的语言呢?

    (码农翻身注: 这其实就是所谓的领域特定语言(Domain Specific Language , 简称 DSL))

    但是开发一套新语言那成本可就有点高了, 有点得不偿失。

    小李百思不得其解, 直到有一天听到小梁和项目经理在讨论 hibernate 的配置文件, 突然想到 像 spring , hibernate 都是用 XML 来描述系统的。

    “那我的 BuildTool 也完全可以用 XML 来描述啊”小李赶紧把那个编译 java 的程序用 XML 描述了一下:

    果然是清爽多了! 和原来的 Java 程序比起来, 这段 XML 几乎就是自解释的 !

    XML 可扩展性极强, 可以任意自定义标签诸如 <javac> <srcDir> <classpath> 用它来描述 Build 的逻辑。

    但是唯一不爽的地方就是: XML 无法像 Java 程序那样运行, 只是纯文本而已。

    不过这也无妨, 只要用 Java 写一个解析器, 用来解析这些 XML 文件然后在 Java 中执行就可以了。有了 BuildTool V1.0 作为基础, 写一个解析器不是什么难事, 很快 BuildTool V2.0 就新鲜出炉了。

    小李不再帮其他项目组去写 Build 程序, 因为用 XML 描述以后, 大家很快就能学会, 并且乐在其中。

    CTO 老张看到这个工具, 大为赞赏, 它给小李说:“别叫什么 Build Tool, 太俗, 别人听了一点感觉都没有, 我给你起个名, 叫 ANT”

    “ANT? ” 小李似乎看到很多小蚂蚁在不辞劳苦帮着做 Build, 心里暗暗佩服老张: 这个名字起的太好了, 姜还是老的辣啊。

小李的 Build 之路(下)

转自:刘欣 码农翻身 2016-07-12

前言:接上一篇《小李的 Build 之路(上)》

小李发明的 ANT 确实是好用,现在不仅仅是小李的公司,连其他公司的朋友听说了,也拿去使用,交口称赞。

只是小李发现了一点奇怪的现象,每个人在开始写新项目的 Ant build 文件之前,都会找到自己说:

“小李,把你那个 build.xml 文件发我一份吧,让我参考下。”

小李的那一份 build.xml 其实是自己项目的第一个 ant 脚本,为啥大家都要把它

Copy 走呢?   刚开始的时候小李以为大家不会写,要按照自己的模板照葫芦画瓢。

偶然有一次,小李看到了别人项目的 Ant build 脚本,不由得大吃一惊,这简直和自己原始的 build.xml 如出一辙。

小李赶紧把公司内所有项目的 Ant 脚本都要过来,仔细观察了一下,很快就发现了这些脚本中蕴藏着一些共同的“模式”,这些模式主要体现在 Build 的步骤上:

1. 从版本控制系统下载代码

2. 编译 java 文件,形成 jar 包

3. 运行单元测试

4. 生成代码覆盖度报告和测试报告

4. 打包形成 war 文件

5. 上传到测试服务器上,进行安装

其实这也难怪,实际的 Build 不就是这样的嘛。但是中间也有不同之处:

(1) 路径不同,例如

java 源文件 下载下来以后放的位置不同,五花八门

编译成的 java class 放置的位置不同

测试报告放置不同

war 包生成后放置的路径不同

。。。

(2)  项目依赖不同,例如

各个项目依赖的第三方 jar 包可能是不一样的

各个项目都有一个 Web 子项目,它依赖于其他 java 项目,所以在 build 的时候,要先 build 这些 java 项目才行

例如下图中的 OnlineShop, 这是个 Web 项目,它依赖于 ApplicationConfg, LoggingFramework, OnlineShopApi 这三个子项目。

项目依赖这个没办法,毕竟是各个项目的业务所要求的,小李没有办法改变。

但是那些不同的路径真的是必要的吗?能不能让大家的路径都保持一致呢?

一个新的主意像闪电一样划过黑暗的夜空:

确实可以保持一致,但是大家都要遵循一定的约定

如果大家都这么做,小李就可以增强一下 Ant,只要运行 ant  complie , 就会 自动 的去 src/main/java 找到源文件进行编译,只要运行 ant test,        就会 自动 去 src/test/java 找到测试用例,编译并运行。

换句话说,只要遵循目录的约定,大家就不用费心费力的指定各种路径了,一切在背后由工具自动搞定,这样的话 Build 脚本就可以极大的简化了,只需要寥寥几行即可。

这只是一个 java 项目,要是多个 java 项目,有依赖关系,像上面提到的 OnlineShop 依赖 OnlineShopAPI, AppplicationConfig, LoggingFramework , 该怎么处理?

这也不难,小李想,首先每个 java 项目都得遵守上述约定,其次需要定义项目之间的依赖关系,也可以用 XML 描述出来。

每个 java 项目都需要有个叫 pom.xml 的文件,例如 OnlineShop 这个项目的 pom 如下:

这样以来工具就能自动找到被依赖的项目,然后去编译打包它了。

此外,各个 java 项目之间也需要按约定来组织目录,例如:

+- pom.xml

+- online-shop-web

| +- pom.xml

| +- src

|   +- main

|     +- webapp

+- online-shop-api

| +- pom.xml

| +- src

|   +- main

|     +- java

+- logging-framework

| +- pom.xml

| +- src

|   +- main

|     +- java

+- app-config

| +- pom.xml

| +- src

|   +- main

|     +- java

如果扩展一下,把第三方的 jar 文件例如 JUnit 也可以给用这种方式来描述:

想到这一层,小李不禁激动起来,因为第三方的 jar 管理一直是一个令人头疼的问题,最早的时候大家都是手工的 Copy 来 Copy 去,由于版本不同导致的错误特别难于发现。

每个人在建立自己 Eclipse workspace 的时候,得拿到所有依赖的 jar 包,并且在项目上设置好,可是非常的费劲啊。

如果利用这种 声明的办法,每个人岂不卸下了一个巨大的包袱?

当然公司需要建立一个公用的第三方 jar 文件版本库,把公司最常用的第三方 jar 包都放进去,工具在分析项目的配置文件 pom.xml 的时候,就可以去公司的版本库里去读取并且下载到本地。

将来有新人进入公司,只要给他一个 pom.xml,用 Eclipse 导入,就能轻松的把一个可以直接运行的 workspace 建立起来,再也不需要设置那些烦心的 jar 了。

如果将来在网络上建立公开的软件版本库,任何人都可以从那里去下载各种软件包,那受惠的可不仅仅是自己公司了,而是所有人,真是一个激动人心的场景啊。

不过还是从自己公司开始吧,小李冷静下来分析了一下:让所有的项目组都使用约定的目录,并且建立一个公司级别的软件库,自己可是没有这样的权限啊,小李去找 CTO 老张求助。

老张不愧是老江湖,听了几分钟小李的介绍,马上就明白了,并且把这个想法提升了一个高度:

“你这叫 约定重于配置,知道不?从 Ruby on Rails 开始,这个词开始流行了,大家现在都很忙,Ant build 脚本用的也没问题,先不改了”

小李还不死心:“可是这么做的话对以后的新项目大有好处啊,不用 Copy 繁琐的 build 脚本了,也不用费心的折腾 workspace 了”

“那也不能现在改,项目进度最重要,大家都没时间,这样吧,等大家项目闲下来再改动如何?”老张妥协了一下。

可是在公司基本上就不会有空闲的时间,一个个新需求压的大家透不过气来,偶尔有空闲时间,大家也都犯懒了,总是想休息。

此外惯性的力量是惊人的,大家都愿意待在舒适区里,不愿意变化,虽然也看到了新工具的好处,大家都懒得换新的。

时间过的很快,一年过去了,小李看着自己辛辛苦苦加班写出来的 Ant 2.0 ,  还是无人采用,很是伤心。

经过公司的允许,小李决定把这个工具开源,为了和 Ant 区分开来,特地起了个新的名称:Maven。

Maven 迅速被大家用了起来,除了小李的公司。

又过了半年,小李跳槽了。

(完)

(完)

Maven 三十分钟入门

阅读 1164

收藏 95

2017-05-08

原文链接:sadwxqezc.github.io

腾讯云移动开发者专区,一站式涵盖开发,测试,发布,营销、运维等全生命周期,有效降低技术门槛、减少研发成本、提升效率。立即了解详情:cloud.tencent.com

Maven

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model(POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.

参考文档:Maven Documentation

Maven 概述

一个基本的 Pom 文件

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  my-app
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      junit
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Pom 文件是面向工程的一个管理模型,全称是 Project Object Model。这个 Pom 文件中包含的基本内容有:

  1. project pom 文件的顶层元素
  2. modelVersion Pom 对象模型的版本
  3. groupId 是创建这个项目的组织或部门的唯一标志,比如说 org.apache.maven.plugins 就是所有 Maven plugins 的 groupId
  4. artifactId 是这个项目生成结果的唯一标志,Maven 生成结果的命名模式为-<version>.<extension>,比如说my app-1.0.jar
  5. packaging 这个参数表明了项目生成结果的打包模式,比如 JAR,WAR,EAR 等,同时这个参数还表明了 build 过程采用的特定生命周期
  6. version 这个参数表明了项目生成结果的版本,在 version 里经常会看到 SNAPSHOT 标志,它表明了项目处于开发阶段。
  7. name 这个参数代表项目的展示名字,通常作用在 Maven 生成的文档中
  8. url 这个参数代表哪里可以找到该项目,通常作用在 Maven 生成的文档中
  9. description 这个参数描述了项目的基本信息,通常作用在 Maven 生成的文档中

Maven 项目的基本结构

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

上面是一个 Maven 项目的基本结构,项目的相关资源位于 ${basedir}/src/main/java 中,而测试的资源位于 ${basedir}/src/test/java 中,而 pom 文件位于 pom.xml 中。

Maven 的执行

1. mvn compile

执行 mvn compile,编译的结果会默认放在${basedir}/target/classes 目录下。

2. mvn test

执行 mvn test,会执行${basedir}/src/test/java 中的单元测试。如果只想编译测试代码而不执行,则执行mvn test-compile

3. mvn package

执行 mvn package 会对项目进行打包,假如当前在 pom 中的 packaging 设定为 jar,那么执行该命令后会在 ${basedir}/target 目录下生成对应的 jar 包。

4. mvn install

如果想把 mvn package 生成的 Jar 文件安装在本地库中以让其它项目引用,则可以执行 mvn install 命令,将生成的 jar 包放在 ${user.home}/.m2/repository 中。

Plugins

Plugins 用来定制 Maven 项目的编译过程,假如要配置 Java Compiler 允许 JDK 5.0 的资源,那么只需要在 Pom 中增加如下内容:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      maven-compiler-plugin
      <version>3.3</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

<configuration>中的配置会应用在对应 Plugin 的所有 Goal。

资源文件打包

${basedir}/src/main/resources目录下的所有文件都会被打包到 Jar 文件中,比如如下一个文件结构:

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           `-- application.properties
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

该项目打包成 Jar 文件后的内部组织结构为:

|-- META-INF
|   |-- MANIFEST.MF
|   |-- application.properties
|   `-- maven
|       `-- com.mycompany.app
|           `-- my-app
|               |-- pom.properties
|               `-- pom.xml
`-- com
    `-- mycompany
        `-- app
            `-- App.class

文件过滤

Maven 支持文件过滤的功能,可以在 build 时候为文件提供变量赋值,比如说上面的 application.properties 文件中有如下定义:

# application.properties
application.name=${project.name}
application.version=${project.version}

那么需要在 pom 文件中做如下的定义:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany.app</groupId>
  my-app
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      junit
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
</project>

执行 mvn process-resources 命令后,在 target/classes 下找到 application.properties 可以看到如下结果:

# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT

可见其中形如 ${<property name>} 的变量已经被替换成了对应的值,如果要引入其它文件中定义的属性,只需要在 pom 文件中定义<filters>,比如:

  <build>
    <filters>
      <filter>src/main/filters/filter.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>

那么 Maven 会先读出 filter.properties 中的属性,然后把这些属性注入对应的 resources 中。

Dependencies

<dependencies>标签下列出了所有的外部依赖,比如下面的 Pom 文件添加了 Junit 的依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany.app</groupId>
  my-app
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      junit
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

<dependency><scope> 标签的值可以为 compile,test 和 runtime,当 Maven 编译项目时,它首先会在 ${user.home}/.m2/repository 这个本地库目录下寻找所需的依赖,如果没有会去远程的库上寻找,并将其下载到本地库中,默认的远程库地址为 http://repo.maven.apache.org/maven2/

包的发布

当需要发布一个包的远程仓库时,需要配置库的地址和相应的权限,一个范例如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany.app</groupId>
  my-app
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      junit
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.codehaus.plexus</groupId>
      plexus-utils
      <version>1.0.4</version>
    </dependency>
  </dependencies>

  <build>
    <filters>
      <filter>src/main/filters/filters.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
  <!--
   |
   |
   |
   -->
  <distributionManagement>
    <repository>
      <id>mycompany-repository</id>
      <name>MyCompany Repository</name>
      <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
  </distributionManagement>
</project>

它所需要的权限配置在 settings.xml 中:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
  <servers>
    <server>
      <id>mycompany-repository</id>
      <username>jvanzyl</username>
      <!-- Default value is ~/.ssh/id_dsa -->
      <privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
      <passphrase>my_key_passphrase</passphrase>
    </server>
  </servers>
  ...
</settings>

多 Modules 管理

Maven 很好的支持了多个 Modules 的管理,假如一个 Maven 项目结构如下:

+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- webapp

对于根目录下的 pom 文件,内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany.app</groupId>
  app
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>

其中的 <modules> 定义了其管理的两个子 modules。

假如 my-webapp 需要依赖 my-app 包,那么在 my-webapp/pom.xml 中增加:

  ...
  <dependencies>
    <dependency>
      <groupId>com.mycompany.app</groupId>
      my-app
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>

然后在 my-app 和 my-webapp 的 pom 文件中都增加 parent 配置:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <groupId>com.mycompany.app</groupId>
    app
    <version>1.0-SNAPSHOT</version>
  </parent>
  ...

然后在最顶层目录下执行mvn clean install,会创建my-webapp/target/my-webapp.war,其中包含:

$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/
 222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
 215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
 123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
  52 Fri Jun 24 10:59:56 EST 2005 index.jsp
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar

可见 my-app-1.0-SNAPSHOT.jar 已经被放到了 WEB-INF/lib 目录下。

一位阿里 Java 工程师的技术小站。作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点 Docker、ELK,同时也分享技术干货和学习经验,致力于 Java 全栈开发!(关注公众号后回复”Java“即可领取 Java 基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的 Java 学习指南、Java 程序员面试指南等干货资源)

正文完
 0