maven


Maven

理论

参考自:

https://www.runoob.com/maven/maven-tutorial.html

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

Maven 环境配置

Maven 是一个基于 Java 的工具,所以要做的第一件事情就是安装 JDK。

之后需要下载Maven,解压到本地,再配置环境变量。

MAVEN_HOME

PATH

Maven pom

POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。


<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">
    
    <!--父项目的坐标。
    如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 
    坐标包括group ID,artifact ID和 version。 -->
    <parent>

        <!--被继承的父项目的构件标识符 -->
        <artifactId />

        <!--被继承的父项目的全球唯一标识符 -->
        <groupId />

        <!--被继承的父项目的版本 -->
        <version />

        <!-- 父项目的pom.xml文件的相对路径。
        相对路径允许你选择一个不同的路径。
        默认值是../pom.xml。
        Maven首先在构建当前项目的地方寻找父项目的pom,
        其次在文件系统的这个位置(relativePath位置),
        然后在本地仓库,最后在远程仓库寻找父项目的pom。 -->
        <relativePath />

    </parent>


    <!--声明项目描述符遵循哪一个POM模型版本。
    模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,
    这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
    <modelVersion>4.0.0</modelVersion>

    <!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。
    并且构建时生成的路径也是由此生成,
    如com.mycompany.app生成的相对路径为:/com/mycompany/app -->
    <groupId>asia.banseon</groupId>

    <!-- 构件的标识符,它和group ID一起唯一标识一个构件。
    换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;
    在某个特定的group ID下,artifact ID也必须是唯一的。
    构件是项目产生的或使用的一个东西,
    Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。 -->
    <artifactId>banseon-maven2</artifactId>

    <!--项目产生的构件类型,例如jar、war、ear、pom。
    插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
    <packaging>jar</packaging>

    <!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
    <version>1.0-SNAPSHOT</version>

    <!--项目的名称, Maven产生的文档用 -->
    <name>banseon-maven</name>

    <!--项目主页的URL, Maven产生的文档用 -->
    <url>http://www.baidu.com/banseon</url>

    <!-- 项目的详细描述, Maven 产生的文档用。
    当这个元素能够用HTML格式描述时
    (例如,CDATA中的文本会被解析器忽略,就可以包含HTML标签),
    不鼓励使用纯文本描述。
    如果你需要修改产生的web站点的索引页面,
    你应该修改你自己的索引页文件,而不是调整这里的文档。 -->
    <description>A maven project to study maven.</description>

    <!--描述了这个项目构建环境中的前提条件。 -->
    <prerequisites>

        <!--构建该项目或使用该插件所需要的Maven的最低版本 -->
        <maven />

    </prerequisites>


    <!--项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)
    的名称和URL,本例为 jira -->
    <issueManagement>

        <!--问题管理系统(例如jira)的名字, -->
        <system>jira</system>

        <!--该项目使用的问题管理系统的URL -->
        <url>http://jira.baidu.com/banseon</url>

    </issueManagement>


    <!--项目持续集成信息 -->
    <ciManagement>

        <!--持续集成系统的名字,例如continuum -->
        <system />

        <!--该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。 -->
        <url />

        <!--构建完成时,需要通知的开发者/用户的配置项。
        包括被通知者信息和通知条件(错误,失败,成功,警告) -->
        <notifiers>

            <!--配置一种方式,当构建中断时,以该方式通知用户/开发者 -->
            <notifier>

                <!--传送通知的途径 -->
                <type />

                <!--发生错误时是否通知 -->
                <sendOnError />

                <!--构建失败时是否通知 -->
                <sendOnFailure />

                <!--构建成功时是否通知 -->
                <sendOnSuccess />

                <!--发生警告时是否通知 -->
                <sendOnWarning />

                <!--不赞成使用。通知发送到哪里 -->
                <address />

                <!--扩展配置项 -->
                <configuration />

            </notifier>


        </notifiers>

        
    </ciManagement>


    <!--项目创建年份,4位数字。当产生版权信息时需要使用这个值。 -->
    <inceptionYear />

    <!--项目相关邮件列表信息 -->
    <mailingLists>

        <!--该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。 -->
        <mailingList>

            <!--邮件的名称 -->
            <name>Demo</name>

            <!--发送邮件的地址或链接,
            如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
            <post>[email protected]</post>

            <!--订阅邮件的地址或链接,
            如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
            <subscribe>[email protected]</subscribe>

            <!--取消订阅邮件的地址或链接,
            如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
            <unsubscribe>[email protected]</unsubscribe>

            <!--你可以浏览邮件信息的URL -->
            <archive>http:/hi.baidu.com/banseon/demo/dev/</archive>

        </mailingList>


    </mailingLists>


    <!--项目开发者列表 -->
    <developers>

        <!--某个项目开发者的信息 -->
        <developer>

            <!--SCM里项目开发者的唯一标识符 -->
            <id>HELLO WORLD</id>

            <!--项目开发者的全名 -->
            <name>banseon</name>

            <!--项目开发者的email -->
            <email>[email protected]</email>

            <!--项目开发者的主页的URL -->
            <url />

            <!--项目开发者在项目中扮演的角色,角色元素描述了各种角色 -->
            <roles>
                <role>Project Manager</role>
                <role>Architect</role>
            </roles>

            <!--项目开发者所属组织 -->
            <organization>demo</organization>

            <!--项目开发者所属组织的URL -->
            <organizationUrl>http://hi.baidu.com/banseon</organizationUrl>

            <!--项目开发者属性,如即时消息如何处理等 -->
            <properties>
                <dept>No</dept>
            </properties>

            <!--项目开发者所在时区, -11到12范围内的整数。 -->
            <timezone>-5</timezone>

        </developer>


    </developers>


    <!--项目的其他贡献者列表 -->
    <contributors>
        <!--项目的其他贡献者。参见developers/developer元素 -->
        <contributor>

            <name />

            <email />

            <url />

            <organization />

            <organizationUrl />

            <roles />

            <timezone />

            <properties />

        </contributor>
    </contributors>


    <!--该元素描述了项目所有License列表。 
    应该只列出该项目的license列表,不要列出依赖项目的 license列表。
    如果列出多个license,用户可以选择它们中的一个而不是接受所有license。 -->
    <licenses>

        <!--描述了项目的license,用于生成项目的web站点的license页面,
        其他一些报表和validation也会用到该元素。 -->
        <license>

            <!--license用于法律上的名称 -->
            <name>Apache 2</name>

            <!--官方的license正文页面的URL -->
            <url>http://www.baidu.com/banseon/LICENSE-2.0.txt</url>

            <!--项目分发的主要方式: repo,可以从Maven库下载 manual, 
            用户必须手动下载和安装依赖 -->
            <distribution>repo</distribution>

            <!--关于license的补充信息 -->
            <comments>A business-friendly OSS license</comments>

        </license>


    </licenses>


    <!--SCM(Source Control Management)标签允许你配置你的代码库,
    供Maven web站点和其它插件使用。 -->
    <scm>

        <!--SCM的URL,该URL描述了版本库和如何连接到版本库。
        欲知详情,请看SCMs提供的URL格式和列表。该连接只读。 -->
        <connection>
            scm:svn:http://svn.baidu.com/banseon/maven
            /banseon/banseon-maven2-trunk(dao-trunk)
        </connection>

        <!--给开发者使用的,类似connection元素。即该连接不仅仅只读 -->
        <developerConnection>
            scm:svn:http://svn.baidu.com
            /banseon/maven/banseon/dao-trunk
        </developerConnection>

        <!--当前代码的标签,在开发阶段默认为HEAD -->
        <tag />

        <!--指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。 -->
        <url>http://svn.baidu.com/banseon</url>

    </scm>

    <!--描述项目所属组织的各种属性。Maven产生的文档用 -->
    <organization>

        <!--组织的全名 -->
        <name>demo</name>

        <!--组织主页的URL -->
        <url>http://www.baidu.com/banseon</url>

    </organization>

    <!--构建项目需要的信息 -->
    <build>

        <!--该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。
        该路径是相对于pom.xml的相对路径。 -->
        <sourceDirectory />

        <!--该元素设置了项目脚本源码目录,该目录和源码目录不同:
        绝大多数情况下,
        该目录下的内容会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。 -->
        <scriptSourceDirectory />

        <!--该元素设置了项目单元测试使用的源码目录,
        当测试项目的时候,构建系统会编译目录里的源码。
        该路径是相对于pom.xml的相对路径。 -->
        <testSourceDirectory />

        <!--被编译过的应用程序class文件存放的目录。 -->
        <outputDirectory />

        <!--被编译过的测试class文件存放的目录。 -->
        <testOutputDirectory />

        <!--使用来自该项目的一系列构建扩展 -->
        <extensions>

            <!--描述使用到的构建扩展。 -->
            <extension>

                <!--构建扩展的groupId -->
                <groupId />

                <!--构建扩展的artifactId -->
                <artifactId />

                <!--构建扩展的版本 -->
                <version />

            </extension>
            
        </extensions>


        <!--当项目没有规定目标(Maven2 叫做阶段)时的默认值 -->
        <defaultGoal />

        <!--这个元素描述了项目相关的所有资源路径列表,
        例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。 -->
        <resources>

            <!--这个元素描述了项目相关或测试相关的所有资源路径 -->
            <resource>

                <!-- 描述了资源的目标路径。
                该路径相对target/classes目录(例如${project.build.outputDirectory})。
                举个例子,如果你想资源在特定的包里(org.apache.maven.messages),
                你就必须该元素设置为org/apache/maven/messages。
                然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。 -->
                <targetPath />

                <!--是否使用参数值代替参数名。
                参数值取自properties元素或者文件里配置的属性,
                文件在filters元素里列出。 -->
                <filtering />

                <!--描述存放资源的目录,该路径相对POM路径 -->
                <directory />

                <!--包含的模式列表,例如**/*.xml. -->
                <includes />

                <!--排除的模式列表,例如**/*.xml -->
                <excludes />

            </resource>

        </resources>


        <!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。 -->
        <testResources>

            <!--这个元素描述了测试相关的所有资源路径,
            参见build/resources/resource元素的说明 -->
            <testResource>

                <targetPath />

                <filtering />

                <directory />

                <includes />

                <excludes />

            </testResource>

        </testResources>

        <!--构建产生的所有文件存放的目录 -->
        <directory />

        <!--产生的构件的文件名,默认值是${artifactId}-${version}。 -->
        <finalName />

        <!--当filtering开关打开时,使用到的过滤器属性文件列表 -->
        <filters />

        <!--子项目可以引用的默认插件信息。
        该插件配置项直到被引用时才会被解析或绑定到生命周期。
        给定插件的任何本地配置都会覆盖这里的配置 -->
        <pluginManagement>

            <!--使用的插件列表 。 -->
            <plugins>

                <!--plugin元素包含描述插件所需要的信息。 -->
                <plugin>

                    <!--插件在仓库里的group ID -->
                    <groupId />

                    <!--插件在仓库里的artifact ID -->
                    <artifactId />

                    <!--被使用的插件的版本(或版本范围) -->
                    <version />

                    <!--是否从该插件下载Maven扩展(例如打包和类型处理器),
                    由于性能原因,只有在真需要下载时,该元素才被设置成enabled。 -->
                    <extensions />

                    <!--在构建生命周期中执行一组目标的配置。
                    每个目标可能有不同的配置。 -->
                    <executions>

                        <!--execution元素包含了插件执行需要的信息 -->
                        <execution>

                            <!--执行目标的标识符,用于标识构建过程中的目标,
                            或者匹配继承过程中需要合并的执行目标 -->
                            <id />

                            <!--绑定了目标的构建生命周期阶段,
                            如果省略,目标会被绑定到源数据里配置的默认阶段 -->
                            <phase />

                            <!--配置的执行目标 -->
                            <goals />

                            <!--配置是否被传播到子POM -->
                            <inherited />

                            <!--作为DOM对象的配置 -->
                            <configuration />

                        </execution>
                        
                    </executions>

                    <!--项目引入插件所需要的额外依赖 -->
                    <dependencies>

                        <!--参见dependencies/dependency元素 -->
                        <dependency>
                            ......
                        </dependency>

                    </dependencies>

                    <!--任何配置是否被传播到子项目 -->
                    <inherited />

                    <!--作为DOM对象的配置 -->
                    <configuration />

                </plugin>

            </plugins>

        </pluginManagement>

        <!--使用的插件列表 -->
        <plugins>

            <!--参见build/pluginManagement/plugins/plugin元素 -->
            <plugin>

                <groupId />

                <artifactId />

                <version />

                <extensions />

                <executions>

                    <execution>

                        <id />

                        <phase />

                        <goals />

                        <inherited />

                        <configuration />

                    </execution>

                </executions>

                <dependencies>

                    <!--参见dependencies/dependency元素 -->
                    <dependency>
                        ......
                    </dependency>

                </dependencies>

                <goals />

                <inherited />

                <configuration />

            </plugin>


        </plugins>


    </build>

    <!--在列的项目构建profile,如果被激活,会修改构建处理 -->
    <profiles>

        <!--根据环境参数或命令行参数激活某个构建处理 -->
        <profile>

            <!--构建配置的唯一标识符。
            即用于命令行激活,也用于在继承时合并具有相同标识符的profile。 -->
            <id />

            <!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。
            profile的力量来自于它 能够在某些特定的环境中自动使用某些特定的值;
            这些环境通过activation元素指定。
            activation元素并不是激活profile的唯一方式。 -->
            <activation>

                <!--profile默认是否激活的标志 -->
                <activeByDefault />

                <!--当匹配的jdk被检测到,profile被激活。
                例如,1.4激活JDK1.4,1.4.0_2,
                而!1.4激活所有版本不是以1.4开头的JDK。 -->
                <jdk />

                <!--当匹配的操作系统属性被检测到,profile被激活。
                os元素可以定义一些操作系统相关的属性。 -->
                <os>

                    <!--激活profile的操作系统的名字 -->
                    <name>Windows XP</name>

                    <!--激活profile的操作系统所属家族(如 'windows') -->
                    <family>Windows</family>

                    <!--激活profile的操作系统体系结构 -->
                    <arch>x86</arch>

                    <!--激活profile的操作系统版本 -->
                    <version>5.1.2600</version>

                </os>

                <!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),
                其拥有对应的名称和值,Profile就会被激活。如果值 字段是空的,
                那么存在属性名称字段就会激活profile,
                否则按区分大小写方式匹配属性值字段 -->

                <property>

                    <!--激活profile的属性的名称 -->
                    <name>mavenVersion</name>

                    <!--激活profile的属性的值 -->
                    <value>2.0.3</value>

                </property>

                <!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。
                missing检查文件是否存在,如果不存在则激活 profile。
                另一方面,exists则会检查文件是否存在,如果存在则激活profile。 -->
                <file>

                    <!--如果指定的文件存在,则激活profile。 -->
                    <exists>
                    /usr/local/hudson/hudson-home/jobs
                    /maven-guide-zh-to-production/workspace/
                    </exists>

                    <!--如果指定的文件不存在,则激活profile。 -->
                    <missing>
                    /usr/local/hudson/hudson-home/jobs
                    /maven-guide-zh-to-production/workspace/
                    </missing>

                </file>

            </activation>

            <!--构建项目所需要的信息。参见build元素 -->
            <build>

                <defaultGoal />

                <resources>

                    <resource>

                        <targetPath />

                        <filtering />

                        <directory />

                        <includes />

                        <excludes />

                    </resource>

                </resources>

                <testResources>

                    <testResource>

                        <targetPath />

                        <filtering />

                        <directory />

                        <includes />

                        <excludes />

                    </testResource>

                </testResources>

                <directory />

                <finalName />

                <filters />

                <pluginManagement>

                    <plugins>

                        <!--参见build/pluginManagement/plugins/plugin元素 -->
                        <plugin>

                            <groupId />

                            <artifactId />

                            <version />

                            <extensions />

                            <executions>

                                <execution>

                                    <id />

                                    <phase />

                                    <goals />

                                    <inherited />

                                    <configuration />

                                </execution>

                            </executions>

                            <dependencies>

                                <!--参见dependencies/dependency元素 -->
                                <dependency>
                                    ......
                                </dependency>

                            </dependencies>

                            <goals />

                            <inherited />

                            <configuration />

                        </plugin>

                    </plugins>

                </pluginManagement>

                <plugins>

                    <!--参见build/pluginManagement/plugins/plugin元素 -->
                    <plugin>

                        <groupId />

                        <artifactId />

                        <version />

                        <extensions />

                        <executions>

                            <execution>

                                <id />

                                <phase />

                                <goals />

                                <inherited />

                                <configuration />

                            </execution>

                        </executions>

                        <dependencies>

                            <!--参见dependencies/dependency元素 -->
                            <dependency>
                                ......
                            </dependency>

                        </dependencies>

                        <goals />

                        <inherited />
                        
                        <configuration />

                    </plugin>

                </plugins>

            </build>

            <!--模块(有时称作子项目) 被构建成项目的一部分。
            列出的每个模块元素是指向该模块的目录的相对路径 -->
            <modules />

            <!--发现依赖和扩展的远程仓库列表。 -->
            <repositories>

                <!--参见repositories/repository元素 -->
                <repository>

                    <releases>

                        <enabled />

                        <updatePolicy />

                        <checksumPolicy />

                    </releases>


                    <snapshots>

                        <enabled />

                        <updatePolicy />

                        <checksumPolicy />

                    </snapshots>


                    <id />

                    <name />

                    <url />

                    <layout />

                </repository>


            </repositories>


            <!--发现插件的远程仓库列表,这些插件用于构建和报表 -->
            <pluginRepositories>

                <!--包含需要连接到远程插件仓库的信息.
                参见repositories/repository元素 -->
                <pluginRepository>

                    <releases>

                        <enabled />
                        
                        <updatePolicy />

                        <checksumPolicy />

                    </releases>

                    <snapshots>

                        <enabled />

                        <updatePolicy />

                        <checksumPolicy />

                    </snapshots>

                    <id />

                    <name />
                    
                    <url />

                    <layout />

                </pluginRepository>


            </pluginRepositories>


            <!--该元素描述了项目相关的所有依赖。
            这些依赖组成了项目构建过程中的一个个环节。
            它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。 -->
            <dependencies>

                <!--参见dependencies/dependency元素 -->
                <dependency>
                    ......
                </dependency>

            </dependencies>

            <!--不赞成使用. 现在Maven忽略该元素. -->
            <reports />

            <!--该元素包括使用报表插件产生报表的规范。
            当用户执行"mvn site",这些报表就会运行。 
            在页面导航栏能看到所有报表的链接。参见reporting元素 -->
            <reporting>
                ......
            </reporting>

            <!--参见dependencyManagement元素 -->
            <dependencyManagement>

                <dependencies>
                    <!--参见dependencies/dependency元素 -->
                    <dependency>
                        ......
                    </dependency>
                </dependencies>
                
            </dependencyManagement>

            <!--参见distributionManagement元素 -->
            <distributionManagement>
                ......
            </distributionManagement>

            <!--参见properties元素 -->
            <properties />

        </profile>


    </profiles>


    <!--模块(有时称作子项目) 被构建成项目的一部分。
    列出的每个模块元素是指向该模块的目录的相对路径 -->
    <modules />

    <!--发现依赖和扩展的远程仓库列表。 -->
    <repositories>

        <!--包含需要连接到远程仓库的信息 -->
        <repository>

            <!--如何处理远程仓库里发布版本的下载 -->
            <releases>

                <!--true或者false
                表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
                <enabled />

                <!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。
                这里的选项是:
                always(一直),
                daily(默认,每日),
                interval:X(这里X是以分钟为单位的时间间隔),或者
                never(从不)。 -->
                <updatePolicy />

                <!--当Maven验证构件校验文件失败时该怎么做:
                ignore(忽略),fail(失败),或者warn(警告)。 -->
                <checksumPolicy />

            </releases>


            <!-- 如何处理远程仓库里快照版本的下载。
            有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,
            为每种类型的构件采取不同的 策略。
            例如,可能有人会决定只为开发目的开启对快照版本下载的支持。
            参见repositories/repository/releases元素 -->
            <snapshots>

                <enabled />

                <updatePolicy />

                <checksumPolicy />

            </snapshots>

            <!--远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库 -->
            <id>banseon-repository-proxy</id>

            <!--远程仓库名称 -->
            <name>banseon-repository-proxy</name>

            <!--远程仓库URL,按protocol://hostname/path形式 -->
            <url>http://192.168.1.169:9999/repository/</url>

            <!-- 用于定位和排序构件的仓库布局类型
            -可以是default(默认)或者legacy(遗留)。
            Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。
            我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->
            <layout>default</layout>

        </repository>


    </repositories>


    <!--发现插件的远程仓库列表,这些插件用于构建和报表 -->
    <pluginRepositories>

        <!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素 -->
        <pluginRepository>
            ......
        </pluginRepository>

    </pluginRepositories>


    <!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。
    它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。 -->
    <dependencies>

        <dependency>

            <!--依赖的group ID -->
            <groupId>org.apache.maven</groupId>

            <!--依赖的artifact ID -->
            <artifactId>maven-artifact</artifactId>

            <!--依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。 -->
            <version>3.8.1</version>

            <!-- 依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。
            一个类型可以被映射成另外一个扩展名或分类器。
            类型经常和使用的打包方式对应, 尽管这也有例外。
            一些类型的例子:jar,war,ejb-client和test-jar。
            如果设置extensions为 true,就可以在 plugin里定义新的类型。
            所以前面的类型的例子不完整。 -->
            <type>jar</type>

            <!-- 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。
            分类器名被附加到文件名的版本号后面。
            例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4编译器,
            另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。 -->
            <classifier></classifier>

            <!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。
            欲知详情请参考依赖机制。 
            - compile :默认范围,用于编译 
            - provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath 
            - runtime: 在执行时需要使用
            - test: 用于test任务时使用
            - system: 需要外在提供相应的元素。通过systemPath来取得 
            - systemPath: 仅用于范围为system。提供相应的路径 
            - optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用 -->
            <scope>test</scope>

            <!--仅供system范围使用。
            注意,不鼓励使用这个元素,并且在新的版本中该元素可能被覆盖掉。
            该元素为依赖规定了文件系统上的路径。
            需要绝对路径而不是相对路径。
            推荐使用属性匹配绝对路径,例如${java.home}。 -->
            <systemPath></systemPath>

            <!--当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。
            即告诉maven你只依赖指定的项目,不依赖项目的依赖。
            此元素主要用于解决版本冲突问题 -->
            <exclusions>

                <exclusion>

                    <artifactId>spring-core</artifactId>

                    <groupId>org.springframework</groupId>

                </exclusion>

            </exclusions>

            <!--可选依赖,如果你在项目B中把C依赖声明为可选,
            你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。
            可选依赖阻断依赖的传递性。 -->
            <optional>true</optional>

        </dependency>

    </dependencies>

    <!--不赞成使用. 现在Maven忽略该元素. -->
    <reports></reports>
    
    <!--该元素描述使用报表插件产生报表的规范。当用户执行"mvn site",这些报表就会运行。
    在页面导航栏能看到所有报表的链接。 -->
    <reporting>

        <!--true,则,网站不包括默认的报表。这包括"项目信息"菜单中的报表。 -->
        <excludeDefaults />

        <!--所有产生的报表存放到哪里。默认值是${project.build.directory}/site。 -->
        <outputDirectory />

        <!--使用的报表插件和他们的配置。 -->
        <plugins>

            <!--plugin元素包含描述报表插件需要的信息 -->
            <plugin>

                <!--报表插件在仓库里的group ID -->
                <groupId />

                <!--报表插件在仓库里的artifact ID -->
                <artifactId />

                <!--被使用的报表插件的版本(或版本范围) -->
                <version />

                <!--任何配置是否被传播到子项目 -->
                <inherited />

                <!--报表插件的配置 -->
                <configuration />

                <!--一组报表的多重规范,每个规范可能有不同的配置。
                一个规范(报表集)对应一个执行目标 。
                例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,
                对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标 -->
                <reportSets>

                    <!--表示报表的一个集合,以及产生该集合的配置 -->
                    <reportSet>

                        <!--报表集合的唯一标识符,POM继承时用到 -->
                        <id />

                        <!--产生报表集合时,被使用的报表的配置 -->
                        <configuration />

                        <!--配置是否被继承到子POMs -->
                        <inherited />

                        <!--这个集合里使用到哪些报表 -->
                        <reports />

                    </reportSet>


                </reportSets>


            </plugin>


        </plugins>


    </reporting>


    <!-- 继承自该项目的所有子项目的默认依赖信息。
    这部分的依赖信息不会被立即解析,
    而是当子项目声明一个依赖(必须描述group ID和 artifact ID信息),
    如果group ID和artifact ID以外的一些信息没有描述,
    则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。 -->
    <dependencyManagement>

        <dependencies>

            <!--参见dependencies/dependency元素 -->
            <dependency>
                ......
            </dependency>
        </dependencies>

    </dependencyManagement>

    <!--项目分发信息,在执行mvn deploy后表示要发布的位置。
    有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。 -->
    <distributionManagement>

        <!--部署项目产生的构件到远程仓库需要的信息 -->
        <repository>

            <!--是分配给快照一个唯一的版本号(由时间戳和构建流水号)?
            还是每次都使用相同的版本号?参见repositories/repository元素 -->
            <uniqueVersion />

            <id>banseon-maven2</id>

            <name>banseon maven2</name>

            <url>file://${basedir}/target/deploy</url>

            <layout />

        </repository>


        <!--构件的快照部署到哪里?
        如果没有配置该元素,默认部署到repository元素配置的仓库,
        参见distributionManagement/repository元素 -->
        <snapshotRepository>

            <uniqueVersion />

            <id>banseon-maven2</id>

            <name>Banseon-maven2 Snapshot Repository</name>

            <url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>

            <layout />

        </snapshotRepository>


        <!--部署项目的网站需要的信息 -->
        <site>

            <!--部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置 -->
            <id>banseon-site</id>

            <!--部署位置的名称 -->

            <name>business api website</name>

            <!--部署位置的URL,按protocol://hostname/path形式 -->
            <url>
                scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web
            </url>

        </site>

        <!--项目下载页面的URL。如果没有该元素,用户应该参考主页。
        使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。 -->
        <downloadUrl />

        <!--如果构件有了新的group ID和artifact ID(构件移到了新的位置),
        这里列出构件的重定位信息。 -->
        <relocation>

            <!--构件新的group ID -->
            <groupId />

            <!--构件新的artifact ID -->
            <artifactId />

            <!--构件新的版本号 -->
            <version />

            <!--显示给用户的,关于移动的额外信息,例如原因。 -->
            <message />

        </relocation>

        <!-- 给出该构件在远程仓库的状态。
        不得在本地项目中设置该元素,因为这是工具自动更新的。
        有效的值有:
        none(默认),
        converted(仓库管理员从 Maven 1 POM转换过来),
        partner(直接从伙伴Maven 2仓库同步过来),
        deployed(从Maven 2实例部 署),
        verified(被核实时正确的和最终的)。 -->
        <status />


    </distributionManagement>


    <!--以值替代名称,Properties可以在整个POM中使用,
    也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。
    格式是<name>value</name>。 -->
    <properties />

</project>

Maven 构建生命周期

  1. validate

  2. compile

  3. test

  4. package

  5. verify

  6. install 本地仓库

  7. deploy 远程仓库

Maven 有以下三个标准生命周期:

  • clean :项目清理的处理

  • default(或 build):项目部署的处理

  • site :项目站点文档创建的处理

23个阶段:

  1. validate

  2. initialize

  3. generate-sources

  4. process-sources

  5. generate-resources

  6. process-resources

  7. complie

  8. process-classes

  9. generate-test-sources

  10. process-test-sources

  11. generate-test-resources

  12. process-test-resources

  13. test-compile

  14. process-test-classes

  15. test

  16. prepare-package

  17. package

  18. pre-integration-test

  19. integration-test

  20. post-integration-test

  21. verify

  22. install

  23. deploy

Maven 构建配置文件

构建配置文件是一系列的配置项的值,可以用来设置或者覆盖 Maven 构建默认值。

使用构建配置文件,你可以为不同的环境,比如说生产环境(Production)和开发(Development)环境,定制构建方式。

配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。

配置文件在构建时修改 POM,并且用来给参数设定不同的目标环境
(比如说,开发(Development)、测试(Testing)和生产环境(Production)中数据库服务器的地址)。

构建配置文件的类型

类型 在哪定义
项目级 (Per Project) 定义在项目的POM文件 pom.xml 中
用户级 (Per User) 定义在Maven的设置xml文件中 (%USER_HOME%/.m2/settings.xml)
全局(Global) 定义在 Maven 全局的设置 xml 文件中 (%M2_HOME%/conf/settings.xml)
  • 通过命令来激活配置文件

mvn [subCommand] -P[profileId]

  • 通过配置来激活配置文件
<settings 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/settings-1.0.0.xsd">
   ...
   <activeProfiles>
      <activeProfile>test</activeProfile>
   </activeProfiles>
</settings>
  • 通过环境变量来激活配置文件
...
<profiles>
    <profile>
        <id>test</id>
        <activation>
          <property>
             <name>env</name>
             <value>test</value>
          </property>
        </activation>
    </profile>
    ...
 </profiles>
 ...

mvn test -Denv=test

  • 通过操作系统来激活配置文件

<profile>
   <id>test</id>
   <activation>
      <os>
         <name>Windows XP</name>
         <family>Windows</family>
         <arch>x86</arch>
         <version>5.1.2600</version>
      </os>
   </activation>
</profile>

mvn test

  • 通过文件的存在或缺失来激活配置文件

<profile>
   <id>test</id>
   <activation>
      <file>
         <missing>target/generated-sources/axistools/wsdl2java/
         com/companyname/group</missing>
      </file>
   </activation>
</profile>

mvn test

Maven 仓库

在 Maven 的术语中,仓库是一个位置(place)。

Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库。

在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。

Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。

Maven 仓库有三种类型:

  • 本地(local)

    Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。

    运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。

    默认情况下,不管Linux还是 Windows,每个用户在自己的用户目录下都有一个路径名为 .m2/repository/ 的仓库目录。

    Maven 本地仓库默认被创建在 %USER_HOME% 目录下。

    要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。

    <localRepository>%USER_HOME%/.m2/repository</localRepository>

  • 中央(central)

    Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。

    中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。

    中央仓库的关键概念:

    • 这个仓库由 Maven 社区管理。

    • 不需要配置。

    • 需要通过网络才能访问。

      要浏览中央仓库的内容,maven 社区提供了一个 URL:http://search.maven.org/#browse。

      使用这个仓库,开发人员可以搜索所有可以获取的代码库。

  • 远程(remote)

    如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。

    为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。

    举例说明,使用下面的 pom.xml,Maven 将从远程仓库中下载该 pom.xml 中声明的所依赖的(在中央仓库中获取不到的)文件。

<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.companyname.projectgroup</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<dependencies>
    <dependency>
        <groupId>com.companyname.common-lib</groupId>
        <artifactId>common-lib</artifactId>
        <version>1.0.0</version>
    </dependency>
<dependencies>
<repositories>
    <repository>
        <id>companyname.lib1</id>
        <url>http://download.companyname.org/maven2/lib1</url>
    </repository>
    <repository>
        <id>companyname.lib2</id>
        <url>http://download.companyname.org/maven2/lib2</url>
    </repository>
</repositories>
</project>

Maven 依赖搜索顺序

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。

Maven 阿里云(Aliyun)仓库

Maven 仓库默认在国外, 国内使用难免很慢,我们可以更换为阿里云的仓库。

修改 maven 根目录下的 conf 文件夹中的 settings.xml 文件,在 mirrors 节点上,添加内容如下:

<mirror>
  <id>aliyunmaven</id>
  <mirrorOf>*</mirrorOf>
  <name>阿里云公共仓库</name>
  <url>https://maven.aliyun.com/repository/public</url>
</mirror>

如果想使用其它代理仓库,可在 节点中加入对应的仓库使用地址。以使用 spring 代理仓为例:

<repository>
  <id>spring</id>
  <url>https://maven.aliyun.com/repository/spring</url>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
</repository>

在你的 pom.xml 文件 <denpendencies></denpendencies> 节点中加入你要引用的文件信息:

<dependency>
  <groupId>[GROUP_ID]</groupId>
  <artifactId>[ARTIFACT_ID]</artifactId>
  <version>[VERSION]</version>
</dependency>

执行拉取命令:mvn install

Maven 插件

Maven 插件

Maven 有以下三个标准的生命周期:

  • clean:项目清理的处理
  • default(或 build):项目部署的处理
  • site:项目站点文档创建的处理

每个生命周期中都包含着一系列的阶段(phase)。这些 phase 就相当于 Maven 提供的统一的接口,然后这些 phase 的实现由 Maven 的插件来完成。

我们在输入 mvn 命令的时候 比如 mvn clean,clean 对应的就是 Clean 生命周期中的 clean 阶段。但是 clean 的具体操作是由 maven-clean-plugin 来实现的。

所以说 Maven 生命周期的每一个阶段的具体实现都是由 Maven 插件实现的。

Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。Maven 插件通常被用来:

  • 创建 jar 文件
  • 创建 war 文件
  • 编译代码文件
  • 代码单元测试
  • 创建工程文档
  • 创建工程报告

插件通常提供了一个目标的集合,并且可以使用下面的语法执行:

<code>mvn [plugin-name]:[goal-name]</code>

例如,一个 Java 工程可以使用 maven-compiler-plugin 的 compile-goal 编译,使用以下命令:

<code>mvn compiler:compile</code>

插件类型

Maven 提供了下面两种类型的插件:

类型 描述
Build plugins 在构建时执行,并在 pom.xml 的 元素中配置。
Reporting plugins 在网站生成过程中执行,并在 pom.xml 的 元素中配置。

下面是一些常用插件的列表:

插件 描述
clean 构建之后清理目标文件。删除目标目录。
compiler 编译 Java 源文件。
surefile 运行 JUnit 单元测试。创建测试报告。
jar 从当前工程中构建 JAR 文件。
war 从当前工程中构建 WAR 文件。
javadoc 为工程生成 Javadoc。
antrun 从构建过程的任意一个阶段中运行一个 ant 任务的集合。

上面的例子展示了以下关键概念:

  • 插件是在 pom.xml 中使用 plugins 元素定义的。
  • 每个插件可以有多个目标。
  • 你可以定义阶段,插件会使用它的 phase 元素开始处理。我们已经使用了 clean 阶段。
  • 你可以通过绑定到插件的目标的方式来配置要执行的任务。我们已经绑定了 echo 任务到 maven-antrun-plugin 的 run 目标。
  • 就是这样,Maven 将处理剩下的事情。它将下载本地仓库中获取不到的插件,并开始处理。

Maven 构建Java项目

Maven 构建 Java 项目
Maven 使用原型 archetype 插件创建项目。要创建一个简单的 Java 应用,我们将使用 maven-archetype-quickstart 插件。

在下面的例子中,我们将在 C:\MVN 文件夹下创建一个基于 maven 的 java 应用项目。

命令格式如下:

mvn archetype:generate "-DgroupId=com.companyname.bank" "-DartifactId=consumerBanking" "-DarchetypeArtifactId=maven-archetype-quickstart" "-DinteractiveMode=false"

参数说明:

  • -DgroupId: 组织名,公司网址的反写 + 项目名称
  • -DartifactId: 项目名-模块名
  • -DarchetypeArtifactId: 指定 ArchetypeId,maven-archetype-quickstart,创建一个简单的 Java 应用
  • -DinteractiveMode: 是否使用交互模式

Maven 构建 & 项目测试

<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>com.companyname.bank</groupId>
  <artifactId>consumerBanking</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>consumerBanking</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>
</project>

mvn clean package

执行完后,我们已经构建了自己的项目并创建了最终的 jar 文件,下面是要学习的关键概念:

  • 我们给了 maven 两个目标,首先清理目标目录(clean),然后打包项目构建的输出为 jar(package)文件。
  • 打包好的 jar 文件可以在 consumerBanking\target 中获得,名称为 consumerBanking-1.0-SNAPSHOT.jar。
  • 测试报告存放在 consumerBanking\target\surefire-reports 文件夹中。
  • Maven 编译源码文件,以及测试源码文件。
  • 接着 Maven 运行测试用例。
  • 最后 Maven 创建项目包。

Maven 引入外部依赖

<dependencies>
    <!-- 在这里添加你的依赖 -->
    <dependency>
        <groupId>ldapjdk</groupId>  <!-- 库名称,也可以自定义 -->
        <artifactId>ldapjdk</artifactId>    <!--库名称,也可以自定义-->
        <version>1.0</version> <!--版本号-->
        <scope>system</scope> <!--作用域-->
        <systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath> <!--项目根目录下的lib文件夹下-->
    </dependency> 
</dependencies>

Maven 项目模板

mvn archetype:generate

Maven 项目文档

修改 pom.xml,添加以下配置(如果没有的话):

<project>
  ...
<build>
<pluginManagement>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.3</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>2.7</version>
        </plugin>
    </plugins>
    </pluginManagement>
</build>
 ...
</project>

mvn site

Maven 快照(SNAPSHOT)

一个大型的软件应用通常包含多个模块,并且通常的场景是多个团队开发同一应用的不同模块。

举个例子,设想一个团队开发应用的前端,项目为 app-ui(app-ui.jar:1.0),而另一个团队开发应用的后台,使用的项目是 data-service(data-service.jar:1.0)。

现在可能出现的情况是开发 data-service 的团队正在进行快节奏的 bug 修复或者项目改进,并且他们几乎每隔一天就要发布库到远程仓库。 现在如果 data-service 团队每隔一天上传一个新版本,那么将会出现下面的问题:

data-service 团队每次发布更新的代码时都要告知 app-ui 团队。

app-ui 团队需要经常地更新他们 pom.xml 文件到最新版本。

为了解决这种情况,快照的概念派上了用场。

什么是快照?

快照是一种特殊的版本,指定了某个当前的开发进度的副本。

不同于常规的版本,Maven 每次构建都会在远程仓库中检查新的快照。

现在 data-service 团队会每次发布更新代码的快照到仓库中,比如说 data-service:1.0-SNAPSHOT 来替代旧的快照 jar 包。

项目快照 vs 版本

对于版本,如果 Maven 以前下载过指定的版本文件,比如说 data-service:1.0,Maven 将不会再从仓库下载新的可用的 1.0 文件。若要下载更新的代码,data-service 的版本需要升到1.1。

快照的情况下,每次 app-ui 团队构建他们的项目时,Maven 将自动获取最新的快照(data-service:1.0-SNAPSHOT)。

app-ui 项目的 pom.xml 文件
app-ui 项目使用的是 data-service 项目的 1.0 快照。

<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>app-ui</groupId>
   <artifactId>app-ui</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <name>health</name>
   <url>http://maven.apache.org</url>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
   <dependencies>
      <dependency>
      <groupId>data-service</groupId>
         <artifactId>data-service</artifactId>
         <version>1.0-SNAPSHOT</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
</project>

data-service 项目的 pom.xml 文件
data-service 项目为每次小的改动发布 1.0 快照。

<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>data-service</groupId>
   <artifactId>data-service</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>health</name>
   <url>http://maven.apache.org</url>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
</project>

虽然,快照的情况下,Maven 在日常工作中会自动获取最新的快照, 你也可以在任何 maven 命令中使用 -U 参数强制 maven 下载最新的快照构建。

mvn clean package -U

Maven 自动化部署

自动化构建定义了这样一种场景: 在一个项目成功构建完成后,其相关的依赖工程即开始构建,这样可以保证其依赖项目的稳定。

比如一个团队正在开发一个项目 bus-core-api, 并且有其他两个项目 app-web-ui 和 app-desktop-ui 依赖于这个项目。

app-web-ui 项目使用的是 bus-core-api 项目的 1.0 快照:

<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>app-web-ui</groupId>
   <artifactId>app-web-ui</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <dependencies>
      <dependency>
      <groupId>bus-core-api</groupId>
         <artifactId>bus-core-api</artifactId>
         <version>1.0-SNAPSHOT</version>
      </dependency>
   </dependencies>
</project>

app-desktop-ui 项目使用的是 bus-core-api 项目的 1.0 快照:

<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>app-desktop-ui</groupId>
   <artifactId>app-desktop-ui</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <dependencies>
      <dependency>
      <groupId>bus-core-api</groupId>
         <artifactId>bus-core-api</artifactId>
         <version>1.0-SNAPSHOT</version>
      </dependency>
   </dependencies>
</project>

bus-core-api 项目:

<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>bus-core-api</groupId>
   <artifactId>bus-core-api</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>   
</project>

现在 app-web-ui 和 app-desktop-ui 项目的团队要求不管 bus-core-api 项目何时变化,他们的构建过程都应当可以启动。

使用快照可以确保最新的 bus-core-api 项目被使用,但要达到上面的要求,我们还需要做一些额外的工作。

可以使用两种方式:

  • 在 bus-core-api 项目的 pom 文件中添加一个 post-build 目标操作来启动 app-web-ui 和 app-desktop-ui 项目的构建。
  • 使用持续集成(CI) 服务器,比如 Hudson,来自行管理构建自动化。

使用 Maven

修改 bus-core-api 项目的 pom.xml 文件。

<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>bus-core-api</groupId>
   <artifactId>bus-core-api</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <build>
   <plugins>
   <plugin>
      <artifactId>maven-invoker-plugin</artifactId>
      <version>1.6</version>
      <configuration>
         <debug>true</debug>
         <pomIncludes>
            <pomInclude>app-web-ui/pom.xml</pomInclude>
            <pomInclude>app-desktop-ui/pom.xml</pomInclude> 
         </pomIncludes>
      </configuration>
      <executions>
         <execution>
            <id>build</id>
            <goals>
               <goal>run</goal>
            </goals>
         </execution>
      </executions>
   </plugin>
   </plugins>
   </build>
</project>

打开命令控制台,切换到 C:\ > MVN > bus-core-api 目录下,然后执行以下命令。

C:\MVN\bus-core-api>mvn clean package -U

执行完命令后,Maven 将开始构建项目 bus-core-api。

bus-core-api 构建成功后,Maven 将开始构建 app-web-ui 项目。

app-web-ui 构建成功后,Maven 将开始构建 app-desktop-ui 项目。

使用持续集成服务器(CI)

如果使用 CI 服务器更,我们每次的一个新项目,比如说实例中的 app-mobile-ui,添加为依赖 bus-core-api 项目时,开发者就不需要更新 bus-core-api 项目的 pom。Hudson 将会借助 Maven 的依赖管理功能实现工程的自动化创建。

Hudson 把每个项目构建当成一次任务。在一个项目的代码提交到 SVN (或者任何映射到 Hudson 的代码管理工具)后,Hudson 将开始项目的构建任务,并且一旦此构建任务完成,Hudson 将自动启动其他依赖的构建任务(其他依赖项目的构建)。

在上面的例子中,当 bus-core-ui 源代码在 SVN 更新后,Hudson 开始项目构建。一旦构建成功,Hudson 自动地查找依赖的项目,然后开始构建 app-web-ui 和 app-desktop-ui 项目。

Maven 依赖管理

Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。

可传递性依赖发现

一种相当常见的情况,比如说 A 依赖于其他库 B。如果,另外一个项目 C 想要使用 A ,那么 C 项目也需要使用库 B。

Maven 可以避免去搜索所有所需库的需求。Maven 通过读取项目文件(pom.xml),找出它们项目之间的依赖关系。

我们需要做的只是在每个项目的 pom 中定义好直接的依赖关系。其他的事情 Maven 会帮我们搞定。

通过可传递性的依赖,所有被包含的库的图形会快速的增长。当有重复库时,可能出现的情形将会持续上升。Maven 提供一些功能来控制可传递的依赖的程度。

功能 功能描述
依赖调节 决定当多个手动创建的版本同时出现时,哪个依赖版本将会被使用。 如果两个依赖版本在依赖树里的深度是一样的时候,第一个被声明的依赖将会被使用。
依赖管理 直接的指定手动创建的某个版本被使用。例如当一个工程 C 在自己的依赖管理模块包含工程 B,即 B 依赖于 A, 那么 A 即可指定在 B 被引用时所使用的版本。
依赖范围 包含在构建过程每个阶段的依赖。
依赖排除 任何可传递的依赖都可以通过 “exclusion” 元素被排除在外。举例说明,A 依赖 B, B 依赖 C,因此 A 可以标记 C 为 “被排除的”。
依赖可选 任何可传递的依赖可以被标记为可选的,通过使用 “optional” 元素。例如:A 依赖 B, B 依赖 C。因此,B 可以标记 C 为可选的, 这样 A 就可以不再使用 C。

依赖范围

传递依赖发现可以通过使用如下的依赖范围来得到限制:

范围 描述
编译阶段 该范围表明相关依赖是只在项目的类路径下有效。默认取值。
供应阶段 该范围表明相关依赖是由运行时的 JDK 或者 网络服务器提供的。
运行阶段 该范围表明相关依赖在编译阶段不是必须的,但是在执行阶段是必须的。
测试阶段 该范围表明相关依赖只在测试编译阶段和执行阶段。
系统阶段 该范围表明你需要提供一个系统路径。
导入阶段 该范围只在依赖是一个 pom 里定义的依赖时使用。同时,当前项目的POM 文件的 部分定义的依赖关系可以取代某特定的 POM。

Maven 自动化部署

项目开发过程中,部署的过程包含需如下步骤:

  • 将所的项目代码提交到 SVN 或者代码库中并打上标签。
  • 从 SVN 上下载完整的源代码。
  • 构建应用。
  • 存储构建输出的 WAR 或者 EAR 文件到一个常用的网络位置下。
  • 从网络上获取文件并且部署文件到生产站点上。
  • 更新文档并且更新应用的版本号。

问题描述

通常情况下上面的提到开发过程中会涉及到多个团队。一个团队可能负责提交代码,另一个团队负责构建等等。很有可能由于涉及的人为操作和多团队环境的原因,任何一个步骤都可能出错。比如,较旧的版本没有在网络机器上更新,然后部署团队又重新部署了较早的构建版本。

解决方案

通过结合以下方案来实现自动化部署:

  • 使用 Maven 构建和发布项目
  • 使用 SubVersion, 源码仓库来管理源代码
  • 使用远程仓库管理软件(Jfrog或者Nexus) 来管理项目二进制文件。

发布自己的jar到中央仓库

不知道为何,我的jar发布到了

https://repo1.maven.org/maven2/com/yuhuizhao/

搜索也可以搜索
https://search.maven.org/search?q=yuhuizhao

但这个地方就是搜不到
https://mvnrepository.com/search?q=yuhuizhao

等可以搜到了再写部分的内容吧

问题解决:

repo1.maven.orgsearch.maven.org 才是中央仓库, 而 mvnrepository.com 不是中央仓库。

mvnrepository.com 只能算是一个搜索引擎,更新频率比较低。

只要 repo1.maven.orgsearch.maven.org 可以搜到就好了。

而且在即使更新之后 mvnrepository.com 使用 yuhuizhao 还是搜不到,需要使用 com.yuhuizhao

search.maven.org 使用 yuhuizhao 是可以搜到的。

而且 mvnrepository.com 还有验证,太烦了。

推荐使用:search.maven.orgrepo1.maven.org

https://stackoverflow.com/questions/62882189/difference-between-search-maven-org-and-mvnrepository-com

todo 如何搭建maven私服

链接

仓库

中央仓库

https://repo1.maven.org/

阿里云仓库

https://developer.aliyun.com/mvn/guide

搜索

maven搜索_中央仓库

https://search.maven.org/

maven搜索_源码阅读网

https://mvn.coderead.cn/

maven搜索_国外搜索引擎

https://mvnrepository.com/


文章作者: [email protected]
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 [email protected] !
评论
  目录