Maven实战读书笔记(15)

关于灵活的构建

一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建。

例如,典型的项目都会有开发环境、测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时候就需要能够识别所在的环境并使用正确的配置

还有一种常见的情况是,项目开发了大量的集成测试,这些测试运行起来非常耗时,不适合在每次构建项目的时候都运行,因此需要一种手段能让我们在特定的时候才激活这些集成测试,Maven为了支持构建的灵活性,内置了三大特性,即属性、Profile和资源过滤

Maven属性

使用Maven属性归类依赖

<properties>

<springframework.version>2.5.6</springframework.version>

</properties>

 

<dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${springframework.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>${springframework.version}</version>

</dependency>

...

</dependencies>

这可能是最常见的使用Maven属性的方式,通过<properties>元素用户可以自定义一个或多个Maven属性,然后再POM的其他地方使用${属性名称}的方式引用该属性,这种做法的最大意义在于消除重复

Maven的6类属性

1、内置属性,主要有两个常用内置属性——${basedir} 表示项目根目录,即包含pom.xml文件的目录;${version} 表示项目版本

2、POM属性,用户可以使用该类属性引用POM文件中对应元素的值,例如:

${project.artifactId}就对应了<project> <artifactId>元素的值,常用的POM属性包括:

n     ${project.build.sourceDirectory}:项目的主源码目录,默认为src/main/java/

n     ${project.build.testSourceDirectory}:项目的测试源码目录,默认为src/test/java/

n     ${project.build.directory}:项目构建输出目录,默认为target/

n     ${project.outputDirectory}:项目主代码编译输出目录,默认为target/classes/

n     ${project.testOutputDirectory}:项目测试代码编译输出目录,默认为target/testclasses/

n     ${project.groupId}:项目的groupId

n     ${project.artifactId}:项目的artifactId

n     ${project.version}:项目的version,与${version}等价

n     ${project.build.finalName}:项目打包输出文件的名称,默认为${project.artifactId}-

${project.version}

这些属性都对应了一个POM元素,它们中一些属性的默认值都是在超级POM中定义的

3、自定义属性,用户可以在POM的<properties>元素下自定义Maven属性

<project>

...

<properties>

<my.prop>hello</my.prop>

</properties>

...

</project>

然后在POM中其他地方使用${my.prop}的时候会被替换成hello

4、Settings属性,与POM属性同理,用户使用以settings.开头的属性引用settings.xml文件中xml元素的值,如常用的${settings.localRepository}指向用户本地仓库的地址

5、Java系统属性,所有Java系统属性都可以使用Maven属性引用,例如${user.home}指向了用户目录,用户可以使用mvn help:system查看所有的Java系统属性

6、环境变量属性,所有环境变量都可以使用以env.开头的Maven属性引用。例如${env.JAVA_HOME}指代了JAVA_HOME环境变量的值。用户可以使用mvn help:system查看所有的环境变量

使用POM属性配置依赖

<dependencies>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>account-email</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>account-persist</artifactId>

<version>${project.version}</version>

</dependency>

</dependencies>

使用Maven属性配置插件

修改测试报告目录

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<version>2.5</version>

<configuration>

<reportsDirectory>

${project.build.directory}/test-reports

</reportsDirectory>

</configuration>

</plugin>

构建环境的差异,考虑一下这种情况

在不同的环境中,项目的源码应该使用不同的方式进行构建,最常见的就是数据库配置了

例如在开发的过程中,有些项目会在src/main/resources/目录下放置带有如下内容的数据库配置文件:

database.jdbc.driverClass=com.mysql.jdbc.Driver

database.jdbc.connectionURL=jdbc:mysql://localhost:3306/test

database.jdbc.username=dev

database.jdbc.password=dev-pwd

这本没什么问题,可当测试人员想要构建项目产品并进行测试的时候,他们往往需要使用不同的数据库,这时的数据库配置文件可能是这样的:

database.jdbc.driverClass=com.mysql.jdbc.Driver

database.jdbc.connectionURL=jdbc:mysql://10.1.0.56:3306/test

database.jdbc.username=test

database.jdbc.password=test-pwd

连接数据库的URL、用户名和密码都发生了变化,类似地,当项目被发布到产品环境的时候,所使用的数据库配置又是另外一套了。这个时候,比较原始的做法是,使用与开发环境一样的构建,然后再测试或者发布产品之前再手动更改这些配置。这是可行的,也是比较常见的,但肯定不是最好的方法。本书已经不止一次强调,手动往往就意味着低效和错误,因此需要找到一种方法,使它能够自动对构建环境的差异

Maven的答案是针对不同的环境生成不同的构件。也就是说,在构建项目的过程中,Maven就已经将这种差异处理好了

资源过滤

为了应对环境的变化,首先需要使用Maven属性将这些将会发生变化的部分提取出来。

将上面的配置,用Maven属性取代

database.jdbc.driverClass=${db.driver}

database.jdbc.connectionURL=${db.url}

database.jdbc.username=${db.username}

database.jdbc.password=${db.password}

这里定义了4个Maven属性:db.driver、db.url、db.username和db.password

使用一个额外的profile包裹自定义Maven属性

针对开发环境的数据库配置

<profiles>

<profile>

<id>dev</id>

<properties>

<db.driver> com.mysql.jdbc.Driver </db.driver>

<db.url> jdbc:mysql://localhost:3306/test </db.url>

<db.username> dev </db.username>

<db.password> dev-pwd </db.password>

</properties>

</profile>

</profiles>

对上面这些配置进行解释

Maven属性定义与直接在POM的properties元素下定义没什么区别,只是使用了一个id为dev的profile,其目的是将开发环境下的配置与其他环境区分开

那么,有了属性定义,配置文件中也使用了这些属性,一切OK了吗?

还是不行,Maven属性默认只有在POM中才会被解析。也就是说,${db.username}放到POM中会变成test,但是如果放到src/main/resources目录下的文件中,构建的时候它将仍然还是${db.username},因此,需要让Maven解析资源文件中的Maven属性

资源文件的处理其实是maven-resources-plugin做的事情,它默认的行为只是将项目主资源文件复制到主代码编译输出目录中,将测试资源文件复制到测试代码编译输出目录中,不过只要通过一些简单的POM配置,该插件就能够解析资源文件中的Maven属性,即开启资源过程

Maven默认的主资源目录和测试资源目录

默认情况下是定义在超级POM中,要为资源目录开启过滤,只要在此基础上添加一行filtering配置即可

为主资源目录开启过滤

<resources>

<resource>

<directory>${project.basedir}/src/main/resources</directory>
              <filtering>true</filtering>

</resource>

</resources>

为测试资源目录开启过滤

<resources>

<resource>

<directory>${project.basedir}/src/test/resources</directory>
              <filtering>true</filtering>

</resource>

</resources>

配置多个资源目录

<resources>

<resource>

<directory>src/main/resources</directory>
              <filtering>true</filtering>

</resource>

</resources>

<resources>

<resource>

<directory>src/main/sql</directory>
              <filtering>false</filtering>

</resource>

</resources>

其中src/main/resources开启了过滤,而src/main/sql没有启用过滤

执行mvn clean install -Pdev命令

mvn的-P参数表示在命令行激活一个profile,这里激活了id为dev的profile。构建完成后,输出目录中的数据库配置就是开发环境的配置了

为了构建差异的jdbc配置,我们做了哪些配置?

1、数据库配置的变化部分提取成了Maven属性

2、在POM的profile中定义了这些属性的值

3、为资源目录开启了属性过滤

4、最后需要在命令行激活profile,Maven就能够在构建项目的时候使用profile中属性值替换数据库配置文件中的属性引用

激活profile,Maven支持很多种激活Profile的方式

1、命令行激活

使用mvn命令行参数-P加上profile的id来激活profile,多个id之间以逗号分隔

使用命令激活dev-x和dev-y两个profile

mvn clean install -Pdev-x,dev-y

2、settings文件显式激活

如果用户希望某个profile默认一直处于激活状态,就可以配置settings.xml文件的activeProfiles元素,表示其配置的profile对于所有项目都处于激活状态

settings文件显式激活profile

<settings>

...

<activeProfiles>

<activeProfile>dev-x</activeProfile>

</activeProfiles>

...

</settings>

3、系统属性激活

配置当某系统属性存在的时候,自动激活profile

当系统属性test存在时,激活此profile

<profiles>

<profile>

<activation>

<property>

<name>test</name>

</propety>

</activation>

...

</profile>

</profiles>

当系统属性test存在,且值等于x的时候激活profile

<profiles>

<profile>

<activation>

<property>

<name>test</name>

<value>x</value>

</propety>

</activation>

...

</profile>

</profiles>

上面的配置,不要忘了在命令行声明系统属性

mvn clean install -Dtest=x

因此,这其实也是一种从命令行激活profile的方法,而且多个profile完全可以使用同一个系统属性来激活

4、操作系统环境激活

Profile还可以自动根据操作系统环境激活,如果构建在不同的操作系统有差异,用户完全可以将这些差异写进profile,然后配置它们自动基于操作系统激活

基于操作系统环境激活profile

<profiles>

<profile>

<activation>

<os>

<name>Windows XP</name>

<family>Windows</family>

<arch>x86</arch>

<version>5.1.2600</version>

</os>

</activation>

...

</profile>

</profiles>

这里family的值包括Windows、UNIX和Mac等,而其他几项name、arch、version,用户可以通过查看环境中的系统属性os.name、os.arch、os.version获得

5、文件存在与否激活

Maven能够根据项目中某个文件存在与否来决定是否激活profile

基于文件存在与否激活profile

<profiles>

<profile>

<activation>

<file>

<missing>x.properties</missing>

<exists>y.properties</ exists >

</file>

</activation>

...

</profile>

</profiles>

6、默认激活

用户可以在定义profile的时候指定其默认激活

默认激活profile

<profiles>

<profile>

<id>dev</id>

<activation>

<activeByDefault>true</activeByDefault>

</activation>

...

</profile>

</profiles>

使用activeByDefault元素用户可以指定profile自动激活,不过需要注意的是,如果POM中有任何一个profile通过以上其他任意一种方式被激活了,所有的默认激活配置都会失效

项目中有很多profile,用户怎么知道哪个激活了?

maven-help-plugin提供一个目标帮助用户了解当前激活的profile

mvn help:active-profiles

maven-help-plugin还有另外一个目标用来列出当前所有的profile

mvn help:all-profiles

那么,profile的种类有哪些?或者说在哪里可以配置profile

1、pom.xml,很显然,pom.xml中声明的profile值对当前项目有效

2、用户settings.xml:用户目录下.m2/settings.xml中的profile对本机上该用户所有的Maven项目有效

3、全局settings.xml:Maven安装目录下conf/settings.xml中的profile对本机上所有的Maven项目有效

4、profiles.xml(Maven 2):还可以在项目根目录下使用一个额外的profiles.xml文件来声明profile,不过该特性已经在Maven 3中被移除。建议用户将这类profile移到settings.xml中

POM中的profile可使用的元素

因为profile可以伴随pom.xml一起存在,所以可以使用很多POM元素

<project>

<repositories></repositories>

<pluginRepositories></pluginRepositories>

<distributationManagement></distributationManagement>

<dependencyManagement></dependencyManagement>

<modules></modules>

<properties></properties>

<reporting></reporting>

<build>

<plugins></plugins>

<defaultGoal></defaultGoal>

<resources></resources>

<testResources></testResources>

<finalName></finalName>

</build>

</project>

POM外部的profile可使用的元素

由于无法保证外部的profile随着特定的pom.xml一起分发,所以外部的profile可使用的元素很少

<project>

<repositories></respositories>

<pluginRepositories></pluginRepositories>

<properties></properties>

</project>

外部的profile仅仅能影响项目的仓库和Maven属性

Web资源过滤

在Web项目中,资源文件同样位于src/main/resources目录下,它们经处理后会位于WAR包的WEB-INF/classes目录下,这也是Java代码编译打包后的目录。也就是说,这类资源文件在打包过后位于应用程序的classpath中。

Web项目中海油另外一类资源文件,默认它们的源码位置src/main/webapp/目录,经打包后位于WAR包的根目录。

例如,一个Web项目的css源码文件在src/main/webapp/css/目录,项目打包后可以在WAR包的css/目录下找到对应的css文件。这一类资源文件称作web资源文件,它们在打包过后不位于应用程序的classpath中

与一般的资源文件一样,web资源文件默认不会被过滤。开启一般资源文件的过滤也不会影响到web资源文件

不过有的时候,我们可能希望在构建项目的时候,为不同的客户使用不一样的资源文件(例如客户的logo图片不同,或者css主题不同)。这时可以在web资源文件中使用Maven属性,例如用 ${client.logo}表示客户的logo图片,用${client.theme}表示客户的css主题。然后使用profile分别定义这些Maven属性的值

针对不同客户web资源的profile

<profiles>

<profile>

<id>client-a</id>

<properties>

<client.logo>a.jpg</client.logo>

<client.theme>red</client.theme>

</properties>

</profile>

<profile>

<id>client-b</id>

<properties>

<client.logo>b.jpg</client.logo>

<client.theme>blue</client.theme>

</properties>

</profile>

</profiles>

为web资源目录src/main/webapp/开启过滤

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-war-plugin</artifactId>

<version>2.1-beta-1</version>

<configuration>

<resource>

<filtering>true</filtering>

<directory>src/main/webapp</directory>

<includes>

<include>**/*.css</include>

<include>**/*.js</include>

</includes>

</resource>

</configuration>

</plugin>

对上述配置进行解释

1、web资源目录src/main/webapp(这也是默认的web资源目录)

2、配置filtering开启过滤,并且使用includes指定要过滤的文件,这里是所有的css和js文件

3、激活某个profile进行构建,mvn clean install -Pclient-a,告诉web资源文件使用logo图片a.jpg,使用css主题red

在profile中激活集成测试?

 

什么是集成测试?

 

如何在Maven中使用TestNG

时间: 2024-10-12 23:47:58

Maven实战读书笔记(15)的相关文章

Maven实战读书笔记(8)

何为Maven的生命周期? 1.Maven从大量项目和构建工具中学习和反思,然后总结了一套高度完善的.易扩展的生命周期 2.这个生命周期包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有的构建步骤 3.Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,实际的任务(如编译源代码)都是交由插件来完成的 Maven的这种思想与设计模式的模板方法非常相似 模板方法模式在父类中定义算法的整体结构,子类可以通过实现或者重写父类的方法来控制实际的行为,这样

Maven实战读书笔记(6)

Maven的坐标和依赖是?构件的逻辑表示方式和物理表示方式是? 1.坐标和依赖是任何一个构件在Maven世界中的逻辑表示方式 2.文件是Maven构件的物理表示方式 3.Maven通过仓库来统一管理这些文件 那么,构件是什么东东? 1.任何一个依赖.插件或者项目构建的输出,都可以称为构件 2.依赖log4j-1.2.15.jar是一个构件 3.插件maven-compiler-plugin-2.0.2.jar是一个构件 4.account-email项目构建完成后输出account-email-

Maven实战读书笔记(四):Maven生命周期与插件

Maven的生命周期是对所有构建过程的抽象和统一.包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有构建步骤. Maven的生命周期是抽象的,其实际行为是由插件来完成的,生命周期和插件两者协同合作,密不可分. 这种思想与设计模式中的模板方法非常相似.模板方法模式在父类定义算法的整体结构,子类通过实现或者重写父类的方法来控制实际行为,这样既能保证算法有足够的可扩展性,又能严格控制算法的整体结构. 4.1 生命周期 Maven拥有3套独立的生命周期:clean.de

Maven实战读书笔记(3)

POM是什么? 1.像Make的Makefile.Ant的build.xml一样,Maven项目的核心是pom.xml 2.POM (Project Object Model, 项目对象模型) 定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等 如何编写一个Hello World的POM? 新建一个名为pom.xml的文件,输入内容如下: <?xml version="1.0" encoding="UTF-8"?> <project xm

Maven实战读书笔记(13)

WAR 1.基于Java的Web应用,其标准的打包方式是WAR 2.WAR与JAR类似,不过它包含更多的内容,如JSP文件.Servlet.Java类.web.xml配置文件.依赖JAR包.静态web资源(如HTML.CSS.JavaScript文件)等 一个典型的WAR文件的目录结构 - war / + META-INF / + WEB-INF / | + classes / | | + ServletA.class | | + config.properties | | + ... | |

maven实战读书笔记(1)

Maven这个词的中文翻译是? 可以翻译为"知识的积累",也可以翻译为"专家"或"内行" Maven是啥?干什么的? 1.一个跨平台的项目管理工具 2.Apache组织的一个颇为成功的开源项目 3.Maven主要服务于基于Java平台的项目构建.依赖管理和项目信息管理 4.适合小型的开源类项目.大型的企业级应用 5.适合传统的瀑布式开发.流行的敏捷模式开发 跨平台是指?Maven是跨平台的 无论是Windows.Linux或者Mac上,都可以使用

Maven实战读书笔记(14)

什么是版本管理? 版本管理是指项目整体版本的演变过程管理,如从1.0-SNAPSHOT到1.0再到1.1-SNAPSHOT 什么是版本控制? 版本控制是指借助版本控制工具(如Subversion)追踪代码的每一个变更 什么时候可以将快照版本更新为发布版本 1.所有自动化测试应当全部通过 2.项目没有配置任何快照版本的依赖 3.项目没有配置任何快照版本的插件 4.项目所包含的代码已经全部提交到版本控制系统中 Maven的版本号定义约束 可能有个版本号是这样的,1.3.4-beta-2 Maven的

Maven实战读书笔记(12)- Nexus

Nexus 简介 安装Nexus Nexus的仓库与仓库组 Nexus的索引与构件搜索 配置Maven从Nexus下载构件 部署构件至Nexus Nexus的权限管理 Nexus的调度任务 其他私服软件 小结

Maven实战读书笔记(18)

代码行统计插件的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/maven-v4_0_0.xsd"> <m