目录

maven使用记录

[TOC]

常用命令

maven打包生成source.jar

1、生成source.jar

1
mvn source:jar 

2、生成jar和souce.jar

1
mvn clean install source:jar -Dmaven.test.skip

配置

maven配置阿里云镜像

https://help.aliyun.com/document_detail/102512.html

在setttins.xml文件中找到<mirrors></mirrors>标签对,进行修改:

1
2
3
4
5
6
7
8
<mirrors>
     <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>*</mirrorOf>
      <name>阿里云公共仓库</name>
      <url>https://maven.aliyun.com/repository/public</url>
	</mirror>
</mirrors>

jar包搜索地址: https://mvnrepository.com/

maven设置jdk版本

  1. 针对全局 在settings.xml添加
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<profile>
    <id>jdk-1.8</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
    </activation>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
    </properties>
</profile>
  1. 针对项目 在maven项目的pom.xml中添加
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>utf-8</encoding>
    </configuration>
</plugin>

Some 记录

mvn test如何测试

debug

1
mvn test -Dmaven.surefire.debug

执行完上述命令后,idea会卡在“[INFO] Listening for transport dt_socket at address: 5005”

此时idea配置remote,什么都不要改,然后点击debug,就可以跑了

过滤一些类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <!-- JUnit 5 requires Surefire version 2.22.0 or higher -->
                <version>2.22.2</version>
                <configuration>
                    <skipTests>false</skipTests>
                    <excludes>
                        <exclude>**/SomeTest.java</exclude>
                        <exclude>**/FrogComponentUtilTest.java</exclude>
                        <exclude>**/MockitoTest.java</exclude>
                        <exclude>**/YamlTest.java</exclude>
                    </excludes>
                </configuration>
            </plugin>

snapshot和release的区别

aven中的仓库分为两种,snapshot快照仓库和release发布仓库。snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本。定义一个组件/模块为快照版本,只需要在pom文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写)

maven2会根据模块的版本号(pom文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本。

  • 如果是快照版本,那么在mvn deploy时会自动发布到快照版本库中,会覆盖老的快照版本,而在使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。
  • 如果是正式发布版本,那么在mvn deploy时会自动发布到正式版本库中,正式版本不允许覆盖,如果一定要提交,要么删除私服上已经存在的版本,要么升级版本重新发布。在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载(默认跟私服上相同版本的内容一致)

depencyManagement 和 dependencies的区别

  1. dependencies

    即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)

  2. dependencyManagement

    只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

    pluginspluginManagement 的区别,和我们上面研究过的 dependenciesdependencyManagement 的区别是非常类似的。plugins 下的 plugin 是真实使用的,而 pluginManagement 下的 plugins 下的 plugin 则仅仅是一种声明,子项目中可以对 pluginManagement 下的 plugin 进行信息的选择、继承、覆盖等。

  3. 在pom中dependencyManagement部分加入的依赖如果在本地仓库中没有会报编译错误,解决方法是先在dependencies里依赖进来,再加入到dependencyManagement,再删除dependencies中那个依赖。

查看maven依赖树

1
$ mvn dependency:tree |tee a.txt

查看有效的POM

1
$ mvn help:effective-pom

Maven 执行的 POM,在组装了所有的继承信息并应用了所有的活动配置文件之后,被称为 “有效 POM”。要查看它,请在任何 POM 文件所在的目录中执行上面面的 Maven 命令。

配置文件

配置文件(在 <profiles> 中定义)是一组自定义的 POM 元素,可以通过自动或者手动启 用(激活)来改变 POM 的行为。例如,你可以定义一个配置文件,它将根据 JDK 版本、操作系 统或者目标部署环境(如开发、测试或者生产环境)来设置构建参数。

可以通过命令行的 -P 标志来显式地引用配置文件。下面的例子将激活一个将 POM 自定义为 使用 JDK1.6 的配置文件。

1
$ mvn -P jdk16 clean install

在日常开发中,我们项目的开发环境和生产环境以及测试环境往往是不同的,比如:数据库的url等。在项目上生产环境时,就需要修改这些参数,给开发造成不便。 为了解决该问题,Maven 2.0引入了构建配置文件的概念(build profiles)。

  1. 能干什么

    假如你的生产环境和开发环境所需环境配置不同,生产环境配置文件是pro.properties,开发环境配置文件是dev.properties,那么用maven profile , 你可以实现打包开发环境jar包的时候只将dev.properties打包并使用,生产环境打包同理。

  2. 在哪里声明

    它可以在每个项目的pom.xml文件中声明,也可以在maven的用户setting.xml下声明,也可以在maven全局环境下设置setting.xml,详情如下。

    1. Per Project

      Defined in the POM itself (pom.xml).

    2. Per User

      Defined in the Maven-settings (%USER_HOME%/.m2/settings.xml)

    3. Global

      Defined in the global Maven-settings (${maven.home}/conf/settings.xml)

    4. Profile descriptor

      不支持3.0,详情请看: https://cwiki.apache.org/MAVEN/maven-3x-compatibility-notes.html#Maven3.xCompatibilityNotes-profiles.xml

    虽然有这么多define的方式,但是我们一般使用的是第一种defined in the pom,因为不见得每个项目的生产环境都一模一样,当然这个也是因个人情况而异。

  3. 实战

    1. 项目结构

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      ├── pom.xml
      ├── src
         ├── main
            ├── java
               └── com
                   └── fantj
            └── resources
                └── conf
                    ├── dev
                       └── application.properties
                    ├── pro
                       └── application.properties
                    └── test
                        └── application.properties
         └── test
             └── java
      
    2. pom.xml

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      
          <profiles>
              <profile>
                 <!--不同环境Profile的唯一id-->
                  <id>dev</id>
                  <properties>
                     <!--profiles.active是自定义的字段(名字随便起),自定义字段可以有多个-->
                      <profile.env>dev</profile.env>
                  </properties>
                    <!-- 默认激活这个,如果打包时没指定的话就使用这个文件夹下的配置-->
                  <activation>
                      <activeByDefault>dev</activeByDefault>
                  </activation>
              </profile>
              <profile>
                  <id>pro</id>
                  <properties>
                      <profile.env>pro</profile.env>
                  </properties>
              </profile>
              <profile>
                  <id>test</id>
                  <properties>
                      <profile.env>test</profile.env>
                  </properties>
              </profile>
          </profiles>
            
          <build>
            <!--将资源文件分成两块,一块不包括conf,一块包括conf下指定的环境目录下所有文件-->
              <resources>
                  <resource>
                      <directory>${basedir}/src/main/resources</directory>
                      <excludes>
                            <!--过滤-->
                          <exclude>conf/**</exclude>
                      </excludes>
                  </resource>
                  <resource>
                      <!--${profile.env}这个目录下的所有文件被启用-->
                      <directory>src/main/resources/conf/${profile.env}</directory>
                  </resource>
              </resources>
            <!--
                当然也可以使用filters达到同样效果
                <filters>
              <filter>src/main/resources/application-${env}.properties</filter>
            </filters>
                这样不需要配置exclude,直接将${profile.env}变量替换,
                filter这里可以理解为筛选器或者填充器。filters里面可以配置多个filter,但是会以最后一个为准,所以一般只配置一个filter
                -->
          </build>
      
    3. 三个application.properties

      dev/application.properties

      1
      2
      3
      4
      
      env=dev
      db.url=192.168.0.166  
      db.username=db-dev 
      db.password=db-dev
      

      pro/application.properties

      1
      2
      3
      4
      
      env=pro
      db.url=47.xxx.xxx.xxx  
      db.username=db-pro
      db.password=db-pro
      

      test/application.properties

      1
      2
      3
      4
      
      env=test
      db.url=127.0.0.1 
      db.username=db-test
      db.password=db-test
      

      如果采用filter写法,那么目录结构就是

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      ├── pom.xml
      ├── src
      │   ├── main
      │   │   ├── java
      │   │   │   └── com
      │   │   │       └── fantj
      │   │   └── resources
      │   │       └── conf
      │   │           └── application-dev.properties
      │   │           └── application-pro.properties
      │   │           └── application-test.properties
      │   └── test
      │       └── java
      
    4. 打包

      1
      
      $ mvn clean install -P pro
      

    https://gitee.com/lienhui68/picStore/raw/master/null/20200901224800.png

    可以看到只将pro/application.properties进行了编译

插件

配置格式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>3.0.2</version>
	<inherited>true</inherited>
	<configuration><!--有的插件识别这个位置,有的不识别,有的都识别-->
		<skip>false</skip><!--只有部分插件支持这个功能-->
	</configuration>
	<executions>
		<execution>
			<id>default-resources</id>
			<phase>process-resources</phase>
			<goals>
				<goal>resources</goal>
			</goals>
			<configuration><!--有的插件不识别这个位置的configuration-->
				<skip>true</skip><!--只有部分插件支持这个功能-->
			</configuration>
		</execution>
		<execution>
			<id>copy2</id>
			<phase>compile</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<skip>false</skip><!--只有部分插件支持这个功能-->
			</configuration>
		</execution>
	</executions>
</plugin>

inherited 插件是允许被继承。比如child使用parent标签继承其它的pom.xml, parent的pom.xml可以将插件的inherited设置为false, 从而避免child继承某个插件。

configuration 从示例可以看出,configuration的位置有两处:   1. 处于plugin结点   2. 处于execution结点 有的插件只识别位置1,比如exec-maven-plugin; 有的插件两个位置都识别,并采用继承的规则(见[插件的继承与覆盖]),比如maven-resources-plugin。 因此,最好是按照插件的官方例子来写, 避免不必要的调试。

skip 是否跳过execution, 只有部分插件支持这个功能,具体信息需要查看插件的参数。

executions,execution, 定义任务列表

id, 定义任务的id, 相当于任务名称,可以随便写,如果不写,则默认值为default(实践得出来的)。同个插件内的execution的id, 不能重复, 所以,包含多个任务时,需要设置为不同的id。maven的phase绑定的默认的插件的execution id的格式为default- 执行mvn相关命令时,console上会打印被执行的execution的id, 例如: [INFO] --- maven-compiler-plugin:3.6.0:compile (default-compile) @ my-child2 ---[INFO] --- 插件的artifactId:插件的version:插件的goal (execution的id) @ 项目的artifactId ---

phase, 设置execution在哪个阶段执行。phase乱写,将导致execution不被执行。

goals,goal, 需要执行插件的哪些goal, 插件有哪些goal, 可以去官网上查。如果乱写,mvn命令将失败

插件的继承与覆盖

经测试,只要父项目a中的<dependencyManagement>标签中管理了依赖,那在孙项目c中就可以直接不带<version>标签的引用

如果pom继承了其它的pom.xml, plugin也会产生继承关系。parent中的plugin可以设置成无法被继承(似乎没什么意义)。默认情况下,maven会将parent和child的配置合并(如果元素存在,则覆盖)。以maven-resources-plugin来举例,parent的配置如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>3.0.2</version>
	<configuration>
		<outputDirectory>${project.basedir}/target/</outputDirectory>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
			</resource>
		</resources>
		<encoding>UTF-8</encoding>
	</configuration>
</plugin>

child配置如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<configuration>
		<resources>
			<resource>
				<directory>src/main/resources2</directory>
			</resource>
		</resources>
	</configuration>
</plugin>

child会继承version, outputDirectory, encoding这些属性,但是会覆盖resouces属性, 最终只拷贝了resource2中的资源 child可以在给元素加入 combine.children=“append”,将child的此元素属性与parent的属性拼接到一起, 例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<configuration>
		<resources combine.children="append">
			<resource>
				<directory>src/main/resources2</directory>
			</resource>
		</resources>
	</configuration>
</plugin>

这样配置后,child将同时拷贝resouce和resource2中的资源. child也可以使用 combine.self=“override”,完全覆盖parent的属性

参考:https://www.cnblogs.com/formyjava/p/4629257.html

Maven的工作是插件完成的,插件自己也有自己的目的,并且还不是一个目的。以插件maven-dependency-plugin为例,它有十多个目标,如:dependency:list,dependency:analyze,dependency:tree等等。(这种写法是一种通用的写冒号前面是插件的前缀,后面是插件的目标)

Maven生命周期与插件目标互相绑定

例如项目编译这个任务,对应maven default生命周期的compile阶段。而maven-compiler-plugin有一个目标compile能够完成这个任务。那么只要将他们绑定,就能够完成任务了。

内置绑定

好了,那么我们应该执行命令: mvn compiler:compile来进行编译了。可是那样子得写一段比较长的命令。还好maven有一些内置绑定,我们直接写生命周期的某个阶段,maven自己知道要调用哪个插件,执行到哪个目标。如下的内置绑定:

clean生命周期内只有一个阶段有绑定: clean阶段绑定了 maven-clean-plugin:clean。 那么我们写mvn clean时,maven才知道要调用maven-clean-plugin:clean

site生命周期有两个:site阶段绑定maven-site-plugin:site ;site-deploy阶段绑定maven-site-plugin:deploy

default生命周期比较复杂,还要根据打包类型来决定绑定那个插件的那个目标

https://gitee.com/lienhui68/picStore/raw/master/null/20200903103452.png

那么我们现在在回过头来再看命令 mvn clean deploy ,就会后更深的解释了:首先还是告诉maven,我要执行到clean阶段,那么maven会找内置绑定,发现clean是与 maven-clean-plugin:clean绑定的,那么maven就会调用maven-clean-plugin:clean;接下来告诉maven,我要执行到deploy阶段,还是一样,maven发现该阶段与maven-deploy-plugin:deploy绑定了,那么maven就会调用该插件了。

如果maven找不到绑定,那就会什么都不干。

如果你是个牛逼的程序员,觉得maven-clean-plugin这个插件写的太挫了,自己写了个插件,怎么使用呢?就是接下来的自定义绑定了。

自定义绑定

先写个插件,那是必须的了。接下来在pom.xml文件中,build的子元素plugins中配置插件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
					<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.1.1</version>
                <executions> <!--自定义绑定阶段和目标-->
                    <execution>
                        <phase>verify</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

意思是 verify阶段绑定到 maven-source-plugin:jar-no-fork目标。那么执行 mvn verify是就会执行 maven-source-plugin:jar-no-fork

上述配置有插件的坐标声明、还有excutions下面每个excution子元素配置的执行的一个个任务、通过phase指定与生命周期的那个阶段绑定、在通过goals指定执行绑定插件的哪些目标。

当插件的目标绑定到不同的生命周期阶段的时候、插件目标的执行顺序是有生命周期阶段的顺序决定的、当多个插件目标绑定到同一生命周期阶段的时候、顺序是按照插件声明的顺序来决定目标的执行顺序。

命令行配置插件参数

eg:mvn test -Dmaven.test.skip=true

记住 -Dxxx是java设置参数的方式。

全局设置

并不是所有插件都适合从命令行配置,有些参数的值从项目创建到发布都不会改变,或者很少改变,对于这种情况,在POM文件中一次性配置就显然比重复在命令行中输入要方便了。

用户可以在生命插件的时候,对插件进行一个全局的设置。例如,我们通常会需要配置maven-compile-plugin告诉它编译Java 1.7版本的源代码,生成与JVM 1.7兼容的字节码文件,

这样不管绑定到compile阶段的maven-compile-plugin:compile任务,还是绑定的到test-compile阶段的maven-compile-plugin:testCompile任务,就都能使用该全局配置,

基于Java1.7版本进行编译。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<build>
    <plugins>
        <!-- 插件定义 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.1</version>
            <!-- 对插件进行全局设置,不管此插件绑定到什么阶段都使用同样的配置 -->
            <configuration>
                <!-- 编译1.7版本的源文件 -->
                <source>1.7</source>
                <!-- 生成与JVM 1.7 兼容的字节码文件 -->
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

根据类名找依赖

findjar