需求:lib升级管理不方便,转为maven项目,方便管理。
解决方案:maven提倡的是"约定优于配置",而目前项目的目录结构不符合maven约定,在不进行大的代码改动的情况下转成maven项目,需要增加一些额外的自定义配置,在后期的实践中再慢慢移除。
注意:新建的maven项目,一定要遵守 maven 的约定,可以节省大量的配置。
将当前项目转为maven项目的几个步骤:
- 增加pom.xml文件
- 根据已有项目目录,使用pom.xml进行自定义配置
- 根据原来的ant的build.xml打包脚本,使用maven打包
maven总结
项目坐标
任何一个构件在maven中都有自己唯一的坐标.
<groupId>com.github.sso</groupId>
<artifactId>sso</artifactId>
<version>1.0</version>
<packaging>war</packaging>
- groupId 当前maven项目隶属的实际项目.通常为公司域名道写+所在项目组
- artifactId 定义实际项目中的一个maven项目(模块).通常使用实际项目(模块)名称
- version 当前项目版本号
- packaging maven项目的打包方式,默认为jar
依赖的配置
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>avalon-framework</groupId>
<artifactId>avalon-framework</artifactId>
</exclusion>
</exclusions>
</dependency>
- groupId,artifactId,version 依赖的基本坐标
- type 依赖的类型,对应于项目坐标中的packaging,默认为jar
- scope 依赖的范围
- optional 标记依赖是否可选
- exclusions 用来排除依赖性传递
依赖范围
maven中有三个classpath
- 编译项目主代码的时候使用一套classpath
- 编译和执行测试时使用一套classpath
- 编译和执行测试时使用一套classpath
依赖范围就是用来控制依赖与这三种classpath的关系.maven中有如下几种依赖关系:
- compile 编译依赖范围,默认使用.对编译,测试,运行classpath都有效
- test 测试依赖范围.只对测试classpath有效,例如:JUnint
- provided 编译和测试classpath有效,运行时无效.例如:servlet-api
- runtime 运行时有效.例如:mysql的JDBC驱动实现包
-
system 和provided依赖范围一样.但是,system的使用必须和systemPath配合.
<dependency> <groupId>jcifs</groupId> <artifactId>jcifs</artifactId> <scope>system</scope> <systemPath>${project.basedir}/lib/jcifs-1.2.15.jar</systemPath> <version>1.2.15</version> </dependency>
- import
依赖传递性
A --> B --> C 假设A依赖于B,B依赖于C,那么我们说
- A对于B是第一直接依赖
- B对于C是第二直接依赖
- A对于C是递性性依赖
依赖传递规律:
- 当第二直接依赖是compile时,传递性依赖和第一直接依赖相同
- 当第二直接依赖是test时,依赖不会传递
- 当第二直接依赖是provided时,只有道第一直接依赖也是provided时,传递性依赖也为provided,其余情况不传递
- 当第二直接依赖为runtime时,传递性依赖与第一直接依赖相同;但compile例外,此时传递性依赖为runtime
第一依赖\第二依赖 | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | - | - | runtimr |
test | test | - | - | test |
provided | provided | - | provided | provided |
runtime | runtime | - | - | runtime |
依赖调解两个原则
- 路径最近者优先
- 第一声明者优先
查看依赖
- mvn dependency:tree 命令查看maven项目的依赖
- IntelliJ IDEA工具的Maven Projects窗口,选择要分析的maven module,右击show dependencies,会出来该module的全部依赖关系图
仓库和坐标
任何一个构件都有唯一的坐标,根据这个坐标可以确定其在仓库中的唯一存储路径.
该路径与坐标的大致对应关系为groupId/artifactId/version/artifactId-version.jar
例如:log4j:log4j:1.2.15这一依赖,其对应仓库的路径为:/log4j/log4j/1.2.15/log4j-1.2.15.jar.
配置settings.xml
maven可以选择配置 $M2_HOME/config/settings.xml 或者 ~/.m2/settings.xml
前者是全局范围的,后者是用户范围的.推荐使用后者.若后者文件不存在,可以直接拷贝全局配置到用户配置中,然后进行修改.
本地仓库
如果用户想要自定义本地仓库目录地址,可以在settis.xml文件中设置 localRepository 元素值,默认在 ~/.m2/repository 目录下
<localRepository>~/java/repository</localRepository>
远程仓库
很多情况下,默认的中央仓库无法满足项目的需求,可能需要从别的仓库下载构件.
这时,可以在 pom.xml 中配置所需的仓库.
<repositories>
<repository>
<id>nexus</id>
<name>nexus-aliyun</name>
<url>>http://maven.aliyun.com/nexus/content/groups/public</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</releases>
<layout>default</layout>
</repository>
</repositories
id : 任何一个仓库的id必须唯一,并且maven自带中央仓库id为central,若其他仓库使用该id就会覆盖中央仓库的配置
-
updatePolicy : maven从远程仓库检查更新的频率
- daily 默认值.每天检查一次
- never 从不检查更新
- always 每次构建都检查更新
- interval:X 每隔X分钟检查一次
-
checksumPolicy 在下载构件时,maven会校验这些文件
- warn 默认值.构建时输出警告信息
- fail 遇到校验错误就构建失败
- ignore 完全忽略校验和错误
远程仓库认证
对于一些远程仓库的访问,我们可能需要进行身份认证.
注意:仓库配置信息可以直接配置在pom.xml中,但是认证信息必须配置在settings.xml文件中.
<servers>
<server>
<id>nexus</id>
<username>your username</username>
<password>your pwd</password>
</server>
<servers>
server元素的id必须和pom文件中需要认证的repository元素的id相同.
部署至远程仓库
在开发中,我们的项目可能需要部署到仓库中,供其他团队成员使用.这时,可以在 pom.xml 中配置distributionManagement元素.
<distributionManagement>
<repository>
<id>deploy_releases</id>
<url>http://192.168.1.101/nexus/content/repositories/releases/</url>
</repository>
</distributionManagement>
如果往仓库需要身份认证,可以参看上文的认证方式.
镜像配置
如果仓库A可以提供仓库B存储的所有内容,那么就可以认为A是B的一个镜像.
可以在 settings.xml 文件中,配置所要使用的镜像.
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!repo.jenkins-ci.org,!local-nexus,!maven-nexus</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
- <mirrorOf></mirrorOf>元素值说明
- * 该镜像匹配所有远程仓库
- external:* 匹配所有不在本机上的远程仓库
- repo1,repo2 匹配仓库repo1和repo2
- *,!repo1 匹配除了repo1仓库外的所有远程仓库
注意:由于镜像仓库完全屏蔽了被镜像的仓库,所有当镜像仓库停止服务的时候,maven无法访问镜像仓库,因而无法下载构件
生命周期
maven的生命周期是抽象的,其实际行为都由插件来完成.maven有三套相互独立的生命周期:
- clean 生命周期: 清理项目
- default 生命周期: 构件项目
- site 生命周期: 建立项目站点
每个生命周期都包含一些阶段,这些阶段都是有序的,并且后面的阶段依赖于前面的阶段.
clean 生命周期
Clean生命周期一共包含了三个阶段:
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
Default生命周期
Default生命周期是Maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中.
生命周期阶段 | 描述 |
---|---|
validate | 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到。 |
initialize | 初始化构建状态,例如设置属性。 |
generate-sources | 生成编译阶段需要包含的任何源码文件。 |
process-sources | 复制并处理资源文件输出至classpath目录 |
generate-resources | 生成工程包中需要包含的资源文件。 |
process-resources | 拷贝和处理资源文件到目的目录中,为打包阶段做准备。 |
compile | 编译项目源代码 |
process-classes | 处理编译生成的文件,例如 Java Class 字节码的加强和优化。 |
generate-test-sources | 生成编译阶段需要包含的任何测试源代码。 |
process-test-sources | 复制并处理测试资源文件输出至目标测试目录 |
test-compile | 编译测试源代码到测试目的目录。 |
process-test-classes | 处理测试代码文件编译后生成的文件。 |
test | 使用适当的单元测试框架(例如JUnit)运行测试,这些测试代码不会被打包或部署 |
prepare-package | 在真正打包之前,为准备打包执行任何必要的操作。 |
package | 获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR。 |
pre-integration-test | 在集成测试执行之前,执行所需的操作。例如,设置所需的环境变量。 |
integration-test | 处理和部署必须的工程包到集成测试能够运行的环境中。 |
post-integration-test | 在集成测试被执行后执行必要的操作。例如,清理环境。 |
verify | 运行检查操作来验证工程包是有效的,并满足质量要求。 |
install | 将包安装至本地仓库,以让其它项目依赖 。 |
deploy | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。 |
注意:当一个阶段通过 Maven 命令调用时,例如 mvn compile
,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。不同的 maven 目标将根据打包的类型(JAR / WAR),被绑定到不同的 Maven 生命周期阶段。
Site生命周期
- pre-site 执行一些需要在生成站点文档之前完成的工作
- site 生成项目的站点文档
- post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上
命令和生命周期
- mvn clean 调用clean声明周期的clean阶段.实际执行的是pre-clean 和clean阶段
- mvn test 调用default生命周期的test阶段.
- mvn clean install 调用clean声明周期的clean阶段和default生命周期的install阶段
注意:运行任何一个阶段的时候,它前面的所有阶段都会被运行.
常用插件
- maven-compiler-plugin ,注意修改编译版本.默认为1.5
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
- tomcat7-maven-plugin
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
- maven-surefire-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--表明在构建项目的时候跳过测试,也可以使用启动参数的方式来进行配置:mvn install -Dmaven.test.skip=true ,其本质就是重用了java的启动参数-->
<skip>true</skip>
</configuration>
</plugin>
- maven-antrun-plugin ,可以用来执行ant脚本
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>process-resources-online</id>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo> execute ant </echo>
</tasks>
</configuration>
</execution>
</plugin>
- maven-war-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<warName>project</warName>
<warSourceExcludes>
/WEB-INF/web-online.xml,
/WEB-INF/web-test.xml,
/WEB-INF/web.xml
</warSourceExcludes>
</configuration>
</plugin>
maven属性
在maven中一共有六类属性:
- 内置属性.常用属性: ${basedir} 表示项目根目录,即pom.xml所有目录.
- pom属性,可以使用该属性引用pom文件中对应的元素值.常用属性:
- ${project.build.sourceDirectory} 项目主源码目录
- ${project.build.directory} 项目构建输出目录,默认为 target/
- ${project.build.outputDirectory} 项目主代码编译输出目录,默认为 target/classes
- 自定义属性.可以在pom的 <properties> 元素下定义maven属性,通过 ${xx} 来引用属性值,可以消除重复.例如:
<properties> <jdk.version>1.8</jdk.version> <org.springframework.version>4.0</org.springframework.version> <com.fasterxml.jackson.version>2.6.3</com.fasterxml.jackson.version> </properties>
- setting属性.以 setting. 开头的属性引用settings.xml文件中的xml属性值.常用如: ${setting.localRepository}
- java系统属性.所有java系统属性都可以在maven中应用.例如: ${user.home} 指向了用户目录.
- 环境变量属性.所有的环境变量属性可以使用 env. 开头的maven属性引用.例如 ${env.JAVA_HOME} 指代了JAVA_HOME环境变量的值.
不同环境的profile
典型的项目开发都会有开发环境,测试环境和产品环境,不同环境的构件也可能是不同的.maven引入了profile的概念,在不同的环境中,激活不同的profile.
<profiles>
<profile>
<id>online</id>
<!-- 线上环境的配置-->
</profile>
<profile>
<id>test</id>
<!-- 测试环境的配置-->
</profile>
</profiles>
激活profile
mvn clean install -P test
profile的种类及作用域
- pom.xml 只对当前项目有效
- 用户settings.xml 对本机此用户的所有项目有效
- maven全局setting.xml 对本机所有项目有效
web资源过滤(即wabapp中的资源)
<plugin>
<artifactId>maven-war-plugin</artifactId>
<!--注意,请使用2.6版本,不同版本似乎存在差异.-->
<version>2.6</version>
<configuration>
<!--webapp目录-->
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<!--需要过滤的web资源-->
<warSourceExcludes>
<!--
注意,这里的路径就要这样写,写绝对路径无效...
不同版本似乎存在差异,使用这个过滤在全局和profile中都设置了
-->
/WEB-INF/applicationContext-test.xml,
/WEB-INF/applicationContext.xml,
/WEB-INF/cas-test.properties,
/WEB-INF/cas.properties,
/WEB-INF/web-online.xml,
/WEB-INF/web-test.xml,
/WEB-INF/web.xml
</warSourceExcludes>
</configuration>
</plugin>