本文能够帮助你加深对Maven的总体认识,不是一篇基础文章。若是你如今尚未用 Maven 跑过 HelloWorld,那么本文可能不适合你。html
Maven 官网: https://maven.apache.org
Maven 3.3.9版本文档: http://maven.apache.org/ref/3...
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。java
maven把项目的构建划分为不一样的生命周期(lifecycle)。粗略一点的话,它这个过程(phase)包括:mysql
maven中全部的执行动做(goal)都须要指明本身在这个过程当中的执行位置,而后maven执行的时候,就依照过程的发展依次调用这些goal进行各类处理。linux
这个也是maven的一个基本调度机制。通常来讲,位置稍后的过程都会依赖于以前的过程。固然,maven一样提供了配置文件,能够依照用户要求,跳过某些阶段。web
maven使用以下几个要素来惟必定位某一个输出物: groupId:artifactId:packaging:version 。好比org.springframework:spring:2.5 。每一个部分的解释以下:算法
version 一个项目的特定版本。发布的项目有一个固定的版本标识来指向该项目的某一个特定的版本。而正在开发中的项目能够用一个特殊的标识,这种标识给版本加上一个"SNAPSHOT"的标记。spring
<major version>.<minor version>.<incremental version>-<qualifier>
,好比1.2.3-beta-01。要说明的是,maven本身判断版本的算法是major,minor,incremental部分用数字比较,qualifier部分用字符串比较,因此要当心 alpha-2和alpha-15的比较关系,最好用 alpha-02的格式。maven在版本管理时候可使用几个特殊的字符串 SNAPSHOT ,LATEST ,RELEASE 。好比"1.0-SNAPSHOT"。各个部分的含义和处理逻辑以下说明:sql
项目结构图:数据库
parent ├─childA(model层) │ └─pom.xml(jar) ├─childB(web层) │ └─pom.xml(war) └─pom.xml(pom)
parent中执行mvn install
就能将 childA和childB 一块儿编译apache
parent的pom.xml作以下配置:
<groupId>com.song</groupId> <artifactId>parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <!-- pom表示它是一个被继承的模块 --> <modules> <module>childA</module> <!-- 不加module则不会被联合编译 --> <module>childB</module> </modules>
childA和childB的pom.xml都须要配置parent,防止引入的包冲突(若是不加parent,会分别去编译他们引入的依赖,会重复引入包):
<!-- childA 的 pom.xml--> <parent> <artifactId>parent</artifactId> <groupId>com.song</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>childA</artifactId> <packaging>jar</packaging> <!-- childB 的 pom.xml--> <parent> <artifactId>parent</artifactId> <groupId>com.song</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>childB</artifactId> <packaging>war</packaging>
<dependency> <groupId>com.module</groupId> <artifactId>childA</artifactId> <!--加上childA的依赖--> <version>1.0-SNAPSHOT</version> </dependency>
parent中加上<dependencyManagement>
,child项目就能够继承parent项目的依赖,而且在child中能够不用加version了。
<dependencyManagement> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> </dependencies> </dependencyManagement>
若是不显示执行 <scope> 属性时,默认 <scope>compile</scope>
。
scope 属性包括:
<dependency>
在全部的classpath中可用,同时它们也会被打包详细可参考: https://maven.apache.org/guid...
maven的依赖关系是有传递性的。如:A-->B,B-->C。但有时候,项目A可能不是必需依赖C,所以须要在项目A中排除对A的依赖。在maven的依赖管理中,有两种方式能够对依赖关系进行,分别是可选依赖(Optional Dependencies)以及依赖排除(Dependency Exclusions)。
当一个项目A依赖另外一个项目B时,项目A可能不多一部分功能用到了项目B,此时就能够在A中配置对B的可选依赖。举例来讲,一个相似hibernate的项目,它支持对mysql、oracle等各类数据库的支持,可是在引用这个项目时,咱们可能只用到其对mysql的支持,此时就能够在这个项目中配置可选依赖。
配置可选依赖的缘由:一、节约磁盘、内存等空间;二、避免license许可问题;三、避免类路径问题,等等。
<dependency> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> <version>1.0</version> <scope>compile</scope> <optional>true</optional> </dependency>
假设以上配置是项目A的配置,即:Project-A --> Project-B。在编译项目A时,是能够正常经过的。
若是有一个新的项目X依赖A,即:Project-X -> Project-A。此时项目X就不会依赖项目B了。若是项目X用到了涉及项目B的功能,那么就须要在pom.xml中从新配置对项目B的依赖。
当一个项目A依赖项目B,而项目B同时依赖项目C,若是项目A中由于各类缘由不想引用项目C,在配置项目B的依赖时,能够排除对C的依赖。
示例(假设配置的是A的pom.xml,依赖关系为:A --> B; B --> C):
<dependency> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> <version>1.0</version> <scope>compile</scope> <exclusions> <exclusion> <groupId>sample.ProjectC</groupId> <artifactId>Project-C</artifactId> </exclusion> </exclusions> </dependency>
固然,对于多重依赖,配置也很简单,参考以下示例:
Project-A -> Project-B -> Project-D -> Project-E <! -- This dependency should be excluded --> -> Project-F -> Project C
A对于E至关于有多重依赖,咱们在排除对E的依赖时,只须要在配置B的依赖中进行便可:
<dependency> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>sample.ProjectE</groupId> <artifactId>Project-E</artifactId> </exclusion> </exclusions> </dependency>
不配置Plugin时,Maven默认会使用如下插件。若是针对各个 plugin 有特殊配置的话,须要显示指定 plugin 和 属性配置。
plugin | function | life cycle phase |
---|---|---|
maven-clean-plugin | 清理上一次执行建立的target文件 | clean |
maven-resources-plugin | 处理资源文件 | resources,testResources |
maven-compiler-plugin | 编译Java代码 | compile、testCompile |
maven-surefire-plugin | 执行单元测试文件 | test |
maven-jar-plugin | 建立 jar | package |
maven-install-plugin | 拷贝jar到本地的maven仓库 .m2/repository 下面 | install |
maven-deploy-plugin | 发布 jar | deploy |
maven-site-plugin | 生成文档 | site |
maven-site-plugin:将工程全部文档生成网站,生成的网站界面默认和apache的项目站点相似,可是其文档用doxia格式写的,目前不支持docbook,须要用其余插件配合才能支持。须要指出的是,在maven 2.x系列中和maven3.x的site命令处理是不一样的,在旧版本中,用 mvn site 命令能够生成reporting节点中的全部报表,可是在maven3中,reporting过期了,要把这些内容做为 maven-site-plugin的configuration的内容才行。详细内容能够参考 http://www.wakaleo.com/blog/2...
<build> <!-- resources 是 maven-resources-plugin 的--> <resources> <resource> <directory>src/main/java</directory> <filtering>true</filtering> <!-- filtering 用来表示资源文件中的占位符是否须要被profiles中的属性动态替换,true为须要替换。 --> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*.properties</include> <include>*.xml</include> <include>*.dic</include> <include>*.txt</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <includes> <include>*.p12</include> </includes> </resource> </resources> <plugins> <!-- maven-compiler-plugin编译源代码。 指定maven编译的jdk版本,若是不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 windows默认使用GBK编码,java项目常常编码为utf8,也须要在compiler插件中指出,不然中文乱码可能会出现编译错 --> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- maven-resources-plugin用来处理资源文件,默认的主资源文件目录是src/main/resources。 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build>
当使用SpringBoot开发项目的时候,会使用到spring-boot-maven-plugin
插件
官方文档: https://docs.spring.io/spring...
Spring Boot Maven plugin有5个Goals:
命令 | 说明 |
---|---|
spring-boot:repackage | 默认goal。在mvn package以后,再次打包可执行的jar/war,<br/>并将mvn package生成的软件包重命名为*.original |
spring-boot:run | 运行Spring Boot应用 |
spring-boot:start | 在mvn integration-test阶段,进行Spring Boot应用生命周期的管理 |
spring-boot:stop | 在mvn integration-test阶段,进行Spring Boot应用生命周期的管理 |
spring-boot:build-info | 生成Actuator使用的构建信息文件build-info.properties |
其中比较重要的命令是:
mvn package spring-boot:repackage
执行后会看到生成的两个jar文件,一个是*.jar
,另外一个是*.jar.original
。
这是因为在执行上述命令的过程当中,Maven首先在package
阶段打包生成*.jar
文件;而后执行spring-boot:repackage
从新打包
咱们也能够跳过repackage
阶段:
clean deploy -D spring-boot.repackage.skip=true
加上-D spring-boot.repackage.skip=true
参数便可,此时只会生成一个普通的jar包
maven-source-plugin提供项目自动将源码打包并发布的功能,在须要发布源码项目的pom.xml文件中添加以下代码便可:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <configuration> </configuration> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin>
执行 mvn install
,maven会自动将source install到repository 。
执行 mvn deploy
,maven会自动将source deploy到remote-repository 。
执行 mvn source:jar
,单独打包源码。
注意:在多项目构建中,将source-plugin置于顶层或parent的pom中并不会发挥做用,必须置于具体项目的pom中。
tomcat插件有两种:tomcat-maven-plugin 和 tomcat7-maven-plugin,使用方式基本相同。
tomcat7-maven-plugin 插件使用
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> <port>8080</port> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin>
命令:
tomcat7:deploy --部署一个web war包 tomcat7:reload --从新加载web war包 tomcat7:start --启动tomcat tomcat7:stop --中止tomcat tomcat7:undeploy --中止一个war包 tomcat7:run --启动嵌入式tomcat ,并运行当前项目
tomcat-maven-plugin 插件使用
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <version>1.1</version> <configuration> <path>/helloworld</path> <port>8080</port> <uriEncoding>UTF-8</uriEncoding> <url>http://localhost:8080/manager/html</url> <server>tomcat6</server> <systemProperties> <JAVA_OPTS>-Xms256m -Xmx512m -XX:MaxPermSize=512m</JAVA_OPTS> </systemProperties> </configuration> </plugin>
命令:
tomcat:deploy --部署一个web war包 tomcat:reload --从新加载web war包 tomcat:start --启动tomcat tomcat:stop --中止tomcat tomcat:undeploy --中止一个war包 tomcat:run --启动嵌入式tomcat ,并运行当前项目
配置参数:
path:是访问应用的路径
port:是tomcat 的端口号
uriEncoding:URL按UTF-8进行编码,这样就解决了中文参数乱码。
Server:指定tomcat名称。
自动部署包含三个步骤:
编译打包、上传到服务器、在服务器上执行linux命令
Maven项目可以使用 mvn install 指令打包,打包完成后包位于target目录下,要想在远程服务器上部署,首先要将包上传到服务器。
首先在本地的setting.xml中配置server的信息,包括id,用户名,密码。(固然也能够在pom.xml里面配置)
<servers> <server> <id>linux_server</id> <username>user</username> <password>password</password> </server> </servers>
pom.xml
<build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> <version>2.8</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>wagon-maven-plugin</artifactId> <version>1.0</version> <configuration> <serverId>linux_server</serverId> <fromFile>target/test.war</fromFile> <url>scp://user:password@192.168.20.128/home/tomcat7/webapps</url> </configuration> </plugin> </plugins> </build>
<serverId>linux_server</serverId>
: 在setting.xml中配置的server的id名字<fromFile>target/test.war</fromFile>
:是要上传到服务器的文件,通常来讲是jar或者war包 <url>scp://user:password@192.168.20.128/home/tomcat7/webapps</url>
:配置服务器的用户、密码、地址以及文件上传的目录
命令:
# 对项目进行打包和上传操做 mvn clean install wagon:upload-single
若是觉的wagon命令太长,能够设置 excutions 来配置phase和goals来简化命令。
<!-- 若是运行的命令中没有“-D maven.deploy.skip=true”不配置distributionManagement 则会报错:-DaltDeploymentRepository=id::layout::url parameter 由于不加maven.deploy.skip=true,则会使用maven的deploy,又使用wagon的deploy。而maven的deploy是须要配置distributionManagement的 <distributionManagement> <repository> <id>${serverid}</id> <url>scp://192.168.20.128/home/java/exe</url> </repository> </distributionManagement> --> <build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> <version>2.8</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>wagon-maven-plugin</artifactId> <version>1.0</version> <configuration> <fromFile>target/test.jar</fromFile> <url>scp://user:password@192.168.20.128/home/java/exe</url> <commands> <command>pkill -f /home/java/exe/test.jar</command> <!-- 杀死原来的进程,-f 是用来查找命令参数,禁止使用pkill java来杀死进程,也能够是 pkill -f test.jar --> <command>nohup java -jar /home/java/exe/test.jar > /home/java/exe/$(date +%Y%m%d-%H%M%S).log & </command> <!-- 从新启动test.jar,& 是xml的转义字符,表示 &--> </commands> <displayCommandOutputs>true</displayCommandOutputs> <!-- 显示运行命令的输出结果 --> </configuration> </plugin> </plugins> </build>
命令
<!--install、wagon:upload-single、wagon:sshexec 分别对项目进行打包、上传、运行command命令的操做--> mvn clean install wagon:upload-single wagon:sshexec
<build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> <version>2.8</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>wagon-maven-plugin</artifactId> <version>1.0</version> <configuration> <fromFile>target/javawebdeploy.war</fromFile> <url>scp://user:password@192.168.20.128/home/tomcat7/webapps</url> <commands> <!-- 重启Tomcat --> <command>sh /home/tomcat7/bin/shutdown.sh</command> <command>rm -rf /home/tomcat7/webapps/test</command> <command>sh /home/tomcat7/bin/startup.sh</command> </commands> <displayCommandOutputs>true</displayCommandOutputs> </configuration> </plugin> </plugins> </build>
命令
mvn clean install wagon:upload-single wagon:sshexec
若是以为 mvn clean package wagon:upload-single wagon:sshexec
命令太长了很差记,那么能够配置execution,在运行deploy的同时运行upload-single和sshexec。
<build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> <version>2.8</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>wagon-maven-plugin</artifactId> <version>1.0</version> <executions> <execution> <id>upload-deploy</id> <!-- 运行deploy命令时同时运行upload-single和sshexec --> <phase>deploy</phase> <goals> <goal>upload-single</goal> <goal>sshexec</goal> </goals> <configuration> <fromFile>target/test.war</fromFile> <url>scp://user:password@192.168.20.128/home/tomcat7/webapps</url> <commands> <command>sh /home/tomcat7/bin/shutdown.sh</command> <command>rm -rf /coder/tomcat7/webapps/test</command> <command>sh /coder/tomcat7/bin/startup.sh</command> </commands> <displayCommandOutputs>true</displayCommandOutputs> </configuration> </execution> </executions> </plugin> </plugins> </build>
部署命令
<!-- 便可使用mvn clean package来代替mvn clean package wagon:upload-single wagon:sshexec --> <!-- 必须加 -D maven.deploy.skip=true ,表示跳过maven自身的deploy使用wagon的deploy。不然报错“-DaltDeploymentRepository=id::layout::url parameter” --> mvn clean deploy -D maven.deploy.skip=true
首先在本地的setting.xml中配置server的信息,包括id,用户名,密码。(固然也能够在pom.xml里面配置)
<servers> <server> <id>linux_server</id> <username>user</username> <password>password</password> </server> </servers>
pom.xml
<build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> <version>2.8</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>wagon-maven-plugin</artifactId> <version>1.0</version> <configuration> <serverId>linux_server</serverId> <url>scp://192.168.20.128/home/tomcat7/webapps</url> <displayCommandOutputs>true</displayCommandOutputs> <!-- 显示运行命令的输出结果 --> </configuration> <executions> <!-- 将war包上传到服务器并重启服务器 --> <execution> <id>upload-war-to-server</id> <phase>deploy</phase> <goals> <goal>upload-single</goal> <goal>sshexec</goal> </goals> <configuration> <fromFile>target/test.war</fromFile> <commands> <command>datefilename=$(date +%Y%m%d-%H%M%S);cp /home/tomcat7/webapps/test.war /home/tomcat7/webapps/test.war.$datefilename</command> <!--备份旧的war包--> <command>ps -ef | grep /home/tomcat7/ | grep -v grep | awk {'print $2'} | sed -e "s/^/kill -9 /g" | sh</command> <!-- 关闭tomcat7 --> <command>rm -rf /home/tomcat7/webapps/test</command> <!-- 删除test项目 --> <command>export JAVA_HOME=/home/jdk/jdk1.8.0_91;sh /home/tomcat7/bin/startup.sh</command> <!-- 启动tomcat --> </commands> </configuration> </execution> </plugin> </plugins> </build>
部署命令
# 必须加 -D maven.deploy.skip=true ,表示跳过maven自身的deploy使用wagon的deploy。不然报错“-DaltDeploymentRepository=id::layout::url parameter” mvn clean deploy -D maven.deploy.skip=true
Maven打包时能够对web.xml
中的spring.profiles.active
值进行替换。
先web.xml
中配置一个占位符${profiles.active}
:
<context-param> <param-name>spring.profiles.active</param-name> <param-value>${profiles.active}</param-value> </context-param>
在pom.xml
配置maven-war-plugin
:
<!-- 打war包时替换占位符 --> <build> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> <configuration> <!-- 过滤Deployment Descriptor并将文件中的占位符替换为pom.xml中对应的<properties>值 --> <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> </configuration> </plugin> </build> <!-- 默认的maven profile --> <properties> <profiles.active>dev</profiles.active> </properties> <profiles> <profile> <id>dev</id> <properties> <profiles.active>dev</profiles.active> </properties> </profile> <profile> <id>release</id> <properties> <profiles.active>release</profiles.active> </properties> </profile> </profiles>
以上配置完成后,再经过mvn package -Pdev
或mvn package -Preelase
打包后,${profiles.active}<
占位符就被替换为dev
或release
<profiles> <profile> <!-- 本地开发环境 --> <id>dev</id> <properties> <profiles.active>dev</profiles.active> </properties> <activation> <!-- 设置默认激活这个配置 --> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <!-- 发布环境 --> <id>release</id> <properties> <profiles.active>release</profiles.active> </properties> </profile> <profile> <!-- 测试环境 --> <id>beta</id> <properties> <profiles.active>beta</profiles.active> </properties> </profile> </profiles> <build> <finalName>helloworld</finalName> <resources> <!-- 先所有不包含 --> <resource> <directory>src/main/resources</directory> <excludes> <exclude>config/</exclude> </excludes> </resource> <!-- 再指定须要包含的文件夹 --> <resource> <directory>src/main/resources/config/${profiles.active}</directory> <targetPath>.</targetPath> </resource> </resources> </build>
id表明这个环境的惟一标识,在 mvn install -Pdev 来指定。
此properties定义了三个环境,分别是dev(开发环境)、beta(测试环境)、release(发布环境)
activeByDefault=true表明若是不指定某个固定id的profile,那么就使用这个环境
使用 mvn install -Pdev
会将 id 为 dev 的 profile 中的<properties>
定义的属性profiles.active
自动替换${profiles.active}
占位符的变量。最终build到classpath的资源文件由maven-resources-plugin来指定,为src/main/resources/config/dev文件下的全部文件。
若是想要整合Maven profile和Spring Framework profile,Maven打包时能够对web.xml
中的spring.profiles.active
值进行替换。
先web.xml
中配置一个占位符${profiles.active}
:
<context-param> <param-name>spring.profiles.active</param-name> <param-value>${profiles.active}</param-value> </context-param>
在pom.xml
配置maven-war-plugin
:
<!-- 打war包时替换占位符 --> <build> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> <configuration> <!-- 过滤Deployment Descriptor并将文件中的占位符替换为pom.xml中对应的<properties>值 --> <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> </configuration> </plugin> </build> <!-- 默认的maven profile --> <properties> <profiles.active>dev</profiles.active> </properties> <profiles> <profile> <id>dev</id> <properties> <profiles.active>dev</profiles.active> </properties> </profile> <profile> <id>release</id> <properties> <profiles.active>release</profiles.active> </properties> </profile> </profiles>
以上配置完成后,再经过mvn package -Pdev
或mvn package -Preelase
打包后,${profiles.active}<
占位符就被替换为dev
或release
全部pom中的元素均可以用 project. 前缀进行引用,如下是部分经常使用的
全部用的的 settings.xml 中的设定均可以经过 settings. 前缀进行引用
系统的环境变量经过 env. 前缀引用
全部JVM中定义的java系统属性.
<project> ... <properties> <project.build.finalName>hellowolrld</project.build.finalName> </properties> ... </project>
则引用 ${project.build.finalName} 就会获得值 hellowolrld
parent工程的pom.xml中的变量用前缀 ${project.parent}
引用. 上级工程的版本也能够这样引用: ${parent.version }
.
参考文章:
https://blog.csdn.net/wwbmyos...
https://blog.csdn.net/j080624...
http://xxgblog.com/2015/10/23...
https://blog.csdn.net/java_an...
https://blog.csdn.net/xiao__g...