Maven学习心得

Maven学习心得,原文地址:https://www.yiibai.com/maven

7.17
添加了Maven的文件夹结构、依赖机制
创建一个Java项目及其目录结构
创建一个web项目及其目录结构
打包以及运行最基本的jar包

7.18

2. Maven的中央资源库

http://repo1.maven.org/maven/,改版后目录浏览不能使用,但是依然可以从这个网址获得依赖,同时可以通过https://search.maven.org/http://repo1.maven.org/maven2来访问目录浏览。

3. 获取依赖

在Maven中,当你声明的库不存在于本地存储库中,也没有不存在于Maven中心储存库,该过程将停止并将错误消息输出到 Maven 控制台。

例:

<!--获取org.jvnet.localizer依赖,但是由于org.jvnet.localizer只适用于Java.net资源库,
所以将因为找不到依赖报错-->
<dependency>
        <groupId>org.jvnet.localizer</groupId>
        <artifactId>localizer</artifactId>
        <version>1.8</version>
</dependency>
<!--声明Java.net储存库,告诉Maven来获得Java.net的依赖-->
<repositories>
  <repository>
    <id>java.net</id>
    <url>https://maven.java.net/content/repositories/public/</url>
  </repository>
</repositories>

声明库后,Maven的依赖库查找顺序变为:

  1. 在 Maven 本地资源库中搜索,如果没有找到,进入第 2 步,否则退出。
  2. 在 Maven 中央存储库搜索,如果没有找到,进入第 3 步,否则退出。
  3. 在java.net Maven的远程存储库搜索,如果没有找到,提示错误信息,否则退出。
    Maven中央仓库以外的远程仓库
    Java.net资源库:
<project ...>
<repositories>
   <repository>
    <id>java.net</id>
    <url>https://maven.java.net/content/repositories/public/</url>
  </repository>
</repositories>
</project>

JBoss Maven资源库:

<project ...>
<repositories>
  <repository>
    <id>JBoss repository</id>
    <url>http://repository.jboss.org/nexus/content/groups/public/</url>
  </repository>
</repositories>
</project>

4. Maven依赖机制

  1. 知道所需的包的Maven坐标,例如:
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
  1. 由Maven自动下载jar包,如果version标签被忽略,则当有新的版本时它会自动升级。
  2. Maven坐标转换成pom.xml文件,例如:
<dependencies>
  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.14</version>
  </dependency>
</dependencies>
  1. 当Maven编译或构建时,jar包会自动下载,并将其加入Maven本地存储库。
  2. 所有由Maven管理。

5. 将自定义的jar包添加到本地存储库

以kaptcha为例。
1. mvn安装
安装命令:

mvn install:install-file -Dfile=c:\kaptcha-{version}.jar 
-DgroupId=com.google.code 
-DartifactId=kaptcha 
-Dversion={version} 
-Dpackaging=jar
  • -Dfile:文件位置
  • -DgroupId:项目创建者或组织的唯一标识符
  • -DartifactId:项目的唯一标识符
  • -Dversion:版本号
  • -Dpackaging:可选,默认为jar

安装kaptcha-2.3.2.jar的命令:

mvn install:install-file -Dfile=c:\kaptcha-2.3.2.jar -DgroupId='com.google.code' -DartifactId=kaptcha -Dversion='2.3.2' -Dpackaging=jar

成功提示:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom ---
[INFO] Installing d:\kaptcha-2.3.2.jar to C:\Users\话神闲\.m2\repository\com\google\code\kaptcha\2.3.2\kaptcha-2.3.2.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.020 s
[INFO] Finished at: 2019-07-17T13:55:42+08:00
[INFO] ------------------------------------------------------------------------

PS:当带"."的值(例如版本号的2.3.2和组织标识符的com.google.code)不用引号包起来时,有可能报错。
报错信息:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.109 s
[INFO] Finished at: 2019-07-17T14:05:18+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] **The goal you specified requires a project to execute but there is no POM in this directory (C:\Users\话神闲\Downloads). Please verify you invoked Maven from the correct directory. -> [Help 1]

2. 配置pom.xml
在pom.xml中声明刚才安装到本地存储库的jar包的坐标

<dependency>
  <groupId>com.google.code</groupId>
  <artifactId>kaptcha</artifactId>
  <version>2.3</version>
</dependency>

3. 完成

完成以上步骤便可从Maven本地存储库检索了。

6. 创建Java项目

  1. 从Maven模板创建一个项目
    创建命令:
mvn archetype:generate 
-DgroupId={project-packaging} 
-DartifactId={project-name} 
-DarchetypeArtifactId=maven-archetype-quickstart 
-DinteractiveMode=false
  • -DgroupId:组织唯一标识符
  • -DartifactId:项目唯一标识符
  • -DarchetypeArtifactId:使用的模板
  • -DinteractiveMode:是否需要和用户交互以获得输入

PS:

1. 同上面安装jar包到本地存储库的命令相同,带"."的参数(如组织唯一标识符)可能会引起报错,因此最好用引号包住。
2. 创建项目时可能会停留在下面这一步很久
[INFO] Generating project in Batch mode

解决方案是:

  1. http://repo1.maven.org/maven2/archetype-catalog.xmlarchetype-catalog.xml文件下载并放到 ~.m2\repository\org\apache\maven\archetype\archetype-catalog{版本号}"文件夹下。然后在创建项目的命令后增加新的参数-DarchetypeCatalog=local,表示从本地读取这个文件
  2. 第二种方法更简单,只要添加-DarchetypeCatalog=internal参数就可以,而且不需要添加-DinteractiveMode=false

7. Maven Java项目目录布局

HelloWorld
    ├──src
    │   ├──main
    │   │   └──java
    │   │       └──mycompany
    │   │              └──App.java
    │   └──test
    │        └──java
    │             └──mycompany
    │                    └──App.java
    └──pom.xml
Directory Description
src/main/java Application/Library sources
src/main/resources Application/Library resources
src/main/filters Resource filter files
src/main/webapp Web application sources
src/test/java Test sources
src/test/resources Test resources
src/test/filters Test resource filter files
src/it Integration Tests (primarily for plugins)
src/assembly Assembly descriptors
src/site Site
LICENSE.txt Project's license
NOTICE.txt Notices and attributions required by libraries that the project depends on
README.txt Project's readme

8. 打包jar

在终端使用以下命令:

mvn package

在target目录生成jar文件
此时文件目录结构:

HelloWorld
    ├──src
    │   ├──main
    │   │   └──java
    │   │       └──mycompany
    │   │             └──App.java
    │   └──test
    │       └──java
    │           └──mycompany
    │                 └──App.java
    ├──target
    └──pom.xml

9. 运行jar包

java -cp HelloWorld.jar mycompany.App
这里要用cp(classpath)指定运行的主类名称

Maven导出的包中:

  • 如果指定了主类,可以用Java -jar xxx.jar
  • 如果未指定主类,可以用Java -cp xxx.jar 包名.主类

10. Maven创建Web项目

命令:

mvn archetype:generate 
-DgroupId=mycompany
-DartifactId=myapp 
-DarchetypeArtifactId=maven-archetype-webapp 
-DinteractiveMode=false

Web项目目录布局:

MyApp
    ├──src
    │   └──main
    │       ├──webapp
    │       │     ├──WEB-INF
    │       │     │     └──web.xml
    │       │     └──index.jsp
    │       └──resources
    └──pom.xml
Directory Description
src/main/java Application/Library sources
src/main/resources Application/Library resources
src/main/filters Resource filter files
src/main/webapp Web application sources
src/test/java Test sources
src/test/resources Test resources
src/test/filters Test resource filter files
src/it IntegrationTests (primarily for plugins)
src/assembly Assembly descriptors
src/site Site
LICENSE.txt Project's license
NOTICE.txt Notices and attributions required by libraries that the project depends on
README.txt Project's readme

11. 使用IDEA创建Maven项目

12. Maven Pom

POM:项目对象模型
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.yiibai.project-group</groupId>
   <artifactId>project</artifactId>
   <version>1.0</version>
<project>

POM的三个必填字段:groupId、artifactId、version。
在库中的项目符号:groupId:artifactId:version。
根元素:project

节点 描述
groupId 这是项目组的编号,这在组织或项目中通常是独一无二的。 例如,一家银行集团com.company.bank拥有所有银行相关项目。
artifactId 这是项目的ID。这通常是项目的名称。 例如,consumer-banking。 除了groupId之外,artifactId还定义了artifact在存储库中的位置。
version 这是项目的版本。与groupId一起使用,artifact在存储库中用于将版本彼此分离。 例如:com.company.bank:consumer-banking:1.0,com.company.bank:consumer-banking:1.1

有效POM:
超级POM:被所有的POM继承的,包含继承默认值的基础POM。
有效的POM:超级POM加项目配置的配置

子pom.xml会完全继承父pom.xml中所有的元素,而且对于相同的元素,一般子pom.xml中的会覆盖父pom.xml中的元素,但是有几个特殊的元素它们会进行合并而不是覆盖。这些特殊的元素是:

  • dependencies
  • developers
  • contributors
  • plugin列表,包括plugin下面的reports
  • resources

查看有效POM的命令:

mvn help:effective-pom
PS D:\home\mavenworkspace\HelloMaven> mvn help:effective-pom
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< com.ltc:HelloMaven >-------------------------
[INFO] Building HelloMaven 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.2.0:effective-pom (default-cli) @ HelloMaven ---
[INFO]
Effective POMs, after inheritance, interpolation, and profiles are applied:

<?xml version="1.0" encoding="GBK"?>
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Generated by Maven Help Plugin on 2019-07-18T14:47:48+08:00            -->
<!-- See: http://maven.apache.org/plugins/maven-help-plugin/                -->
<!--                                                                        -->
<!-- ====================================================================== -->
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Effective POM for project 'com.ltc:HelloMaven:jar:1.0-SNAPSHOT'        -->
<!--                                                                        -->
<!-- ====================================================================== -->
<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.ltc</groupId>
  <artifactId>HelloMaven</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>HelloMaven</name>
  <url>http://maven.apache.org</url>
  <!--省略pom.xml文件细节-->
</project>
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.881 s
[INFO] Finished at: 2019-07-18T14:47:49+08:00
[INFO] ------------------------------------------------------------------------

13. 快照版本和正式版本

SNAPSHOT版本:

  • 一个SNAPSHOT版本可以多次发布(deploy)到仓库中,也就是说,一个SNAPSHOT是一系列版本的集合,而HEAD指针总是指向最新的版本。因此,当有新的SNAPSHOT版本发布时,由于本地的版本和实际HEAD指针所指向的版本不同,因此Maven会自动下载新版本的SNAPSHOT版本。
    SNAPSHOT文件夹里用来保存历史发布的文件内容
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
  <groupId>ltc</groupId>
  <artifactId>SnapShot</artifactId>
  <version>1.0-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <localCopy>true</localCopy>
    </snapshot>
    <lastUpdated>20190718152857</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>1.0-SNAPSHOT</value>
        <updated>20190718152857</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>1.0-SNAPSHOT</value>
        <updated>20190718152857</updated>
      </snapshotVersion>
    </snapshotVersions>
  </versioning>
</metadata>
  • SNAPSHOT写法:
<version>{version}-SNAPSHOT</version>
  • Maven在工作时,会自动下载最新版的SNAPSHOT版本,但是也可以通过任何命令加上 -U 参数来强制获取最新的SNAPSHOT。
mvn clean -U

RELEASE版本:

  • 一个正式版本对应的就是一个特定的版本,版本名称后缀为:-RELEASE。正式版本,不允许覆盖。如果一定要提交,要么删除私服上已经存在的版本,要么升级版本重新发布。
  • RELEASE写法:
<version>{version}-RELEASE</version>

总结:
RELEASE版本 -> 稳定性
SNAPSHOT版本 -> 方便性

快照和正式版本的选择:

  • 在开发期间,方便性优于稳定性。
  • 生产环境,稳定性重于一切。
    例子:

模块A依赖模块B的1.0版本,而假如B假如发布新特性或者修复了旧版本的漏洞,则必须发布新的1.1版本,并通知所有依赖B-1.0版本的模块更新依赖。
但是如果模块A依赖的是模块B的1.0-SNAPSHOT版本,则B修复完漏洞,只需再次发布1.0-SNAPSHOT版本,而A模块就能获得了最新版本的B模块。

14. 版本区间

范围 说明
1.0 version >= 1.0 * The default Maven meaning for 1.0 is everything (,) but with 1.0 recommended. Obviously this doesn't work for enforcing versions here, so it has been redefined as a minimum version.
(,1.0] version <= 1.0
(,1.0) version < 1.0
[1.0] version == 1.0
[1.0,) version >= 1.0
(1.0,) version > 1.0
(1.0,2.0) 1.0 < version < 2.0
[1.0,2.0] 1.0 <= version <= 2.0
(,1.0],[1.2,) version <= 1.0 or version >= 1.2. Multiple sets are comma-separated
(,1.1),(1.1,) version != 1.0

测试:
本地库版本有:

  • 0.9
  • 1.0
  • 1.0-SNAPSHOT
  • 1.1
  • 1.9
  • 2.0
  • 2.0-SNAPSHOT
  • 2.1-SNAPSHOT
  • 2.2-SNAPSHOT
<version>(1,)</version>
导入的为2.3-SNAPSHOT
----------------------------------
<version>(1,2]</version>
导入的为2.0
----------------------------------
<version>(1,2)</version>
导入的为2.0-SNAPSHOT
----------------------------------
<version>(,1)</version>
导入的为1.0-SNAPSHOT
----------------------------------
<version>(,0.99)</version>
导入的为0.9
----------------------------------
<version>(,0.9) , (2.3,)</version>
报错,找不到符合范围的包
----------------------------------

15. 移除依赖包

当想导入的jar包依赖于另一个jar包,而实际上并没用到这个包又或者自动导入的这个包并不稳定而需要重新导入另一个稳定版本时,可以将其移除。

<dependency>
  <groupId>ltc</groupId>
  <artifactId>B</artifactId>
  <version>1.0-SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>ltc</groupId>
      <artifactId>A</artifactId>
    </exclusion>
  </exclusions>
</dependency>

如上,其中B部分功能依赖于A,当前项目C依赖于B,当未使用到B中依赖A的功能时可以把A包移除。同样的,如果B中自动导入的A并不稳定,也可通过这个方式先将其移除,然后将导入A的稳定版本。

16. Profiles

通过定义多个profile,可以分别为不同的环境配置不同的设置,然后在需要激活的时候通过特定方法激活特定的配置。
项目结构如下:

ProfileTest
    ├──src
    │   ├──main
    │   │   ├──java
    │   │   │    └──ltc
    │   │   │        └──App.java
    │   │   └──resources
    │   │           ├──dev
    │   │           │   └──application-dev.properties
    │   │           ├──prod
    │   │           │   └──application-prod.properties
    │   │           └──test
    │   │                └──application-test.properties
    │   └──test
    │       └──java
    │           └──ltc
    │               └──App.java
    └──pom.xml

其中,pom.xml文件配置如下:

<!--最简单的profiles配置-->
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>ltc</groupId>
  <artifactId>ProfileTest</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>ProfileTest</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <profiles>
    <!--每个profile标签都定义了一个profile-->
    <profile>
      <!--id可以用来表示一个profile,而且可以在打包时通过-P{id}参数来选择激活的profile-->
      <id>dev</id>
      <!--自定义属性,在profile激活时生效-->
      <properties>
        <env>dev</env>
      </properties>
    </profile>
    <profile>
      <id>prod</id>
      <properties>
        <env>prod</env>
      </properties>
      <!--另一种激活profile的方法,当使用maven命令时未指定所激活的profile时,默认激活该profile-->
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
    </profile>
    <profile>
      <id>test</id>
      <properties>
        <env>test</env>
      </properties>
    </profile>
  </profiles>
  <build>
    <resources>
      <!--通过resource标签里的directory来选择要加入打包的文件夹-->
      <resource>
        <directory>src/main/resources/${env}</directory>
      </resource>
    </resources>
  </build>
</project>

激活profile:

  1. 通过<activeByDefault>标签所在的profile来激活,这时无需指定profile
mvn compile

编译后的target文件夹:

target
   ├──classes
   │   ├──ltc
   │   │   └──App.class
   │   └──application-prod.properties
   └──maven-status

可见,被<activeByDefault>所指定的properties文件被添加到了目标文件夹中。

  1. 通过编译时的-P参数来激活
mvn clean compile -Pdev

编译后的target文件夹:

target
   ├──classes
   │   ├──ltc
   │   │   └──App.class
   │   └──application-dev.properties
   └──maven-status

由于在编译时指定了profile,所以默认的profile并没有被添加到target文件夹 。

进阶配置:

  • filter的配置:
    原理:
    用build-filters-filter里选择的文件中的键值对填充resources-resource-directory-includes-include选择的文件中的${...}占位符。
    配置:
    该项目文件结构:
ProfileTest
    ├──src
    │   ├──main
    │   │   ├──java
    │   │   └──resources
    │   │           ├──dev
    │   │           │   └──application-dev.properties
    │   │           ├──prod
    │   │           │   └──application-prod.properties
    │   │           ├──test
    │   │           │   └──application-test.properties
    │   │           └──application.properties
    │   └──test
    └──pom.xml

pom.xml:

<filters>
  <filter>src/main/resources/${env}/application-${env}.properties</filter>
</filters>
<resources>
  <resource>
    <directory>src/main/resources/</directory>
    <!--filtering,当其值为true时,才会填充下面include包含的文件-->
    <filtering>true</filtering>
    <!--includes,用于指定要加入打包的文件-->
    <includes>
      <include>application.properties</include>
     </includes>
 </resource>

application.properties:

url=${url}
username=${username}
password=${password}

application-dev.properties:

url=dev
username=name-dev
password=password-dev

prod和test配置文件的内容与dev基本相似,编译打包后,application.properties中用${...}占位符表示的地方,会用filter选择的文件进行填充,因此编译打包后的application.properties的内容为:

url=dev
username=name-dev
password=password-dev

此外,如果需要打包的配置文件中(application.properties),有filter文件中未出现的键值对,那么${...}将保持原样不会被替换。

参考资料:
maven profile动态选择配置文件
maven(三)最详细的profile的使用
maven 根据profile,resources,filters来区分部署环境

17. 继承

一个项目可以继承另一个项目的依赖,前者被称为子项目,后者被称为父项目。
在父项目声明的依赖,在子项目中可以直接获得。父项目也可以通过<dependencyManagement>标签来管理依赖,该标签下的依赖子项目默认不继承,但可通过在子pom.xml声明groupId和artifactId即可继承父项目中的依赖。

父pom配置:
--------------------------------------------------------------------------------------------
<modelVersion>4.0.0</modelVersion>
  <groupId>ltc</groupId>
  <artifactId>Parent</artifactId>
  <packaging>pom</packaging>
  <version>1.0</version>
  <name>Parent</name>
  <url>http://maven.apache.org</url>
  <dependencies>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
  </dependencies>
  <dependencyManagement>
     <dependencies>
       <dependency>
         <groupId>commons-io</groupId>
         <artifactId>commons-io</artifactId>
         <version>2.5</version>
       </dependency>
         <dependency>
             <groupId>log4j</groupId>
             <artifactId>log4j</artifactId>
             <version>1.2.11</version>
         </dependency>
     </dependencies>
  </dependencyManagement>
--------------------------------------------------------------------------------------------
子pom配置:
--------------------------------------------------------------------------------------------
<modelVersion>4.0.0</modelVersion>
  <artifactId>Child1</artifactId>
  <url>http://maven.apache.org</url>
  <parent>
    <artifactId>Parent</artifactId>
    <groupId>ltc</groupId>
    <version>1.0</version>
  </parent>
  <dependencies>
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
      </dependency>
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
      </dependency>
  </dependencies>
--------------------------------------------------------------------------------------------

子项目中的依赖

可以看到,子项目中不需要配置就直接继承了父项目在dependencies中声明的junit,通过配置commons-io和log4j的groupId和artifactId也获取到了父项目中对应版本的jar包。
PS:

  • 父项目需要打包格式为pom
  • 父项目需要安装或者指定<relativePath>,否则子项目将找不到父项目

18. 聚合

  • 创建方式
    父模块:创建普通的Maven项目,打包方式为pom
    子模块:命令行模式下,在父模块目录下,创建Maven项目。IDEA中在父模块上右键新建Module。
    父模块pom:
  <modelVersion>4.0.0</modelVersion>
  <groupId>ltc</groupId>
  <artifactId>Combine</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Combine</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 <modules>
  <module>Son1</module>
  <module>Son2</module>
 </modules>

子模块pom:

<modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>ltc</groupId>
    <artifactId>Combine</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>ltc</groupId>
  <artifactId>Son1</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>Son1</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

父模块在module声明了子模块的名称,子模块也声明了父模块,不过与继承不同的是父模块不用安装到存储库中,子模块也能找到对应父模块。同时子模块也可以继承父模块的依赖。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容