maven 学习笔记:20241024

时间:2024-10-30 11:39:24

Maven 是java项目的构建和管理工具,主流版本3.x.x,而4.x.x也已更新。五个核心概念:坐标、依赖和仓库,生命周期,插件。

1,基本使用,
    学习使用maven还是自己动手从零开始构建,使用集成开发环境会忽略很多细节,导致云里雾里,不知所以。
    1.1 创建pom.xml,格式如下:

<?xml version="1.0" encoding="UTF-8"?>

<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.hello</groupId>
  <artifactId>hello-world</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>hello-world</name>
  
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<java.version>11</java.version>
	<maven.compiler.source>${java.version}</maven.compiler.source>
	<maven.compiler.target>${java.version}</maven.compiler.target>
  </properties>

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

  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.hello.App</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
  </build>

</project>


    1.2 编写代码:

    maven约定项目的根目录是pom.xml 文件所在的目录,所以我们在该目录里面创建 :
    src/main/java 文件夹来存放java原文件, 注意添加package目录。
    src/main/resources 存放配置文件,    
    src/test/java 存放测试文件
    target 存放编译之后的文件。
    1.3 mvn clean package 直接编译。编译之后会生成一个jar包,但是jar包不能直接运行,还需要一个插件,来表明main方法入口的位置 需要借助Apache Maven Shade Plugin(https://maven.apache.org/plugins/maven-shade-plugin/usage.html)来完成。
    另外可以使用 mvn archetype:generate 来自动生成项目目录结构(骨架),又叫脚手架,有多种项目结构可以选择,根据需要和提示就可以自动生成相应的目录。在运行mvn archetype:generate时,实际上是在运行maven-archetype-plugin插件。插件在maven里面是很重要的概念。
 

2,maven仓库。

      存放依赖包的地方,通过maven坐标(生成项目时定义的groupId,artifactId,version等)来寻找相应的依赖包,分为本地仓库和远程仓库,项目的依赖包maven会首先在本地仓库寻找,如果本地仓库有就直接使用,没有就到远程仓库寻找,并下载到本地仓库使用。
  本地仓库的配置在 ~/.m2/setting 中有个标签,标记本地仓库的位置。

<localRepository>~/.m2/repository</localRepository>


  远程仓库又分为 *仓库,私服,和其他的公共仓库。maven 有个默认的*仓库:https://repo.maven.apache.org/maven2 。远程仓库的配置,可以在 setting.xml 也可以在pom.xml。

<project>
    ......

    <!-- 配置远程仓库 -->
    <repositories>
        <repository>
            <id>jboss</id>
            <name>JBoss Repository</name>
            <url>http://repository.jboss.com/maven2/</url>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>daily</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
                <checksumPolicy>warn</checksumPolicy>
            </snapshots>
            <layout>default</layout>
        </repository>
    </repositories>
    ......
</project>

但是如果需要认证的话 建议配置在本地的setting文件中: 只需要server.id 与 repository.id 对应的上就可以。

<servers>
    <server>
        <id>deploymentRepo</id>
        <username>repouser</username>
        <password>repopwd</password>
    </server>
</servers>

还可以将自己开发的项目部署到远程仓库:

<project>
    ......
    <distributionManagement>
        <repository>
            <id>releases</id>
            <name>public</name>
            <url>http://59.50.95.66:8081/nexus/content/repositories/releases</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <name>Snapshots</name>
            <url>http://59.50.95.66:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
    </distributionManagement>
    ......
</project>

这里面的 snapshots与 releases跟项目的版本号相关,,如果项目版本号标记为snapshots,每次编译代码时会自动比对远程仓库代码的时间戳,不一致的话 会更新本地仓库依赖,方便协同开发,此所谓快照。
还有一个很重要的概念称之为镜像,如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。也就是说,任何一个可以从仓库Y获得的依赖包,都能够从它的镜像中获取。比如http://maven.aliyun.com/nexus/content/groups/public是阿里提供的*仓库的镜像,
配置在setting.xml 中:

<mirrors>
    <mirror>
        <id>alimaven</id>  
        <name>aliyun maven</name>  
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  
        <mirrorOf>central</mirrorOf>    
    </mirror> 
</mirrors>

mirrorOf的值为central,表示该配置为*仓库的镜像,任何对于*仓库的请求都会转至该镜像。这里的东西比较多,需要使用的话,可以参考文档或者直接搜索引擎解决。

3,maven 生命周期 ,Maven生命周期就是为了对所有的构建过程进行抽象和统一,开发了一套高度完善的、易扩展的生命周期。这个生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有构建步骤。这是一个抽象的概念,可以理解成为整个项目工作的所有阶段(phase)的一个抽象。

4,maven插件,前面说maven的生命周期就是整个项目工作的所有阶段,而且呢它是个抽象的概念,不干活,活就是由插件干的,而且想要干活的话你得跟这个生命周期绑定起来。所以执行 mvn clean 这个生命周期其实是执行的生命周期背后的clean插件,而 mvn clean:clean 也可以实现编译文件全清楚就是这个原因,第一个clean是插件的前缀,而冒号之后的是插件的目标,一个插件可能有多个目标。有些插件是默认绑定在生命周期阶段上的,称之为内置绑定,也可以手动绑定,比如,一下shade插件绑定在 package生命周期上:
 

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration> <!--这个主要是插件的属性配置,跟-D传递参数的效果一样-->
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>com.jellythink.HelloWorld.App</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
</build>

仔细看phase标签是绑定在package这个阶段(生命周期)上的。还有个命令可以查看maven插件的各种信息:

 mvn help:describe -Dplugin=org.apache.maven.plugins:maven-shade-plugin:3.2.1 -Ddetail 

5,在maven中,为了支持多环境构建场景,内置了三大特性,即属性、Profile和资源过滤。
  5.1 maven属性: 
    内置属性:${basedir}表示项目根目录,即包含pom.xml文件的目录,${version}表示项目版本。
    POM属性:可以使用POM属性引用POM文件中对应元素的值,比如${project.artifactId}就对应了<project><artifactId>元素的值
    自定义属性:<properties>标签中定义
    Settings属性:可以使用${settings.localRepository}来引用用户本地仓库的地址。
    Java系统属性:比如${user.home}指向用户的目录
    环境变量属性:所有环境变量都可以使用以env.开头的Maven属性引用。比如${env.JAVA_HOME}指向了JAVA_HOME环境变量的值。我们可以使用mvn help:system查看所有的Java系统属性
  5.2 资源过滤,可以将目录里面所有文件的 ${} 占位符替换掉,配置如下:

<build>
    <!-- 为主资源目录开启过滤 -->
    <resources>
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    
    <!-- 为测试资源目录开启过滤 -->
    <testResources>
        <testResource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
        </testResource>
    </testResources>
 </build>  

  5.3 profile 可以通过 mvn package -Pdev 来激活dev环境对应的配置:

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <db.driver>com.mysql.jdbc.driverClass</db.driver>
            <db.url>jdbc:mysql://localhost:3306/dev</db.url>
            <db.username>develop</db.username>
            <db.password>develop-password</db.password>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <db.driver>com.mysql.jdbc.driverClass</db.driver>
            <db.url>jdbc:mysql://localhost:3306/test</db.url>
            <db.username>test</db.username>
            <db.password>test-password</db.password>
        </properties>
    </profile>
</profiles>

6,漏掉了一个maven依赖配置:

<project>
    ...
    <dependencies>
        <dependency>
            <groupId>...</groupId>
            <artifactId>...</artifactId>
            <version>...</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>
                <exclusion>
                ...
                </exclusion>
            </exclusions>
        </dependency>
        ...
    </dependencies>
    ...
</project>

有几个标签值得一记:
scope:(依赖的范围)
              compile(默认),
              test      (只对于测试有效),
              provided(对于编译和测试有效,但在运行时无效。最典型的例子是servlet-api),
              runtime (对于测试和运行有效,但在编译主代码时无效。最典型的例子就是JDBC驱动实                              现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行                               项目的时候才需要具体JDBC驱动) 
              system (此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定)

optional:标记依赖是否可选,
exclusions:用来排除传递性依赖,