Maven一个项目的构建和管理工具
相关配置
项目级:定义在项目的POM文件pom.xml中
用户级:%USER_HOME%/.m2/settings.xml
全局:%M2_HOME%/conf/settings.xml
父POM:%M2_HOME%/lib/maven-model-builder-3.6.2.jar中的pom文件(这个文件一般不会改动)
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>
<!--父工程的相关配置 -->
<parent>
<groupId>com.xxx</groupId>
<artifactId>pdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!--文档名 -->
<artifactId>demo</artifactId>
<!--包类型 -->
<packaging>war</packaging>
<!--依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
</dependencies>
<!--工程的构建过程 -->
<build>
<!--maven插件 -->
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>9002</port>
</configuration>
</plugin>
</plugins>
</build>
</project>
settings.xml:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 本地仓库 -->
<localRepository>/path/to/local/repo</localRepository>
<!-- Maven是否需要和用户交互以获得输入 -->
<interactiveMode>true</interactiveMode>
<!-- 是否启动离线模式 -->
<offline>false</offline>
<!-- 插件的组织ID,使用插件时在这个list里面搜索,比如什么都不配,有默认的org.apache.maven.plugins -->
<pluginGroups>com.your.plugins</pluginGroups>
<!-- 代理,就是代理自己去访问远程服务器,远程仓库 -->
<proxies>
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
</proxies>
<!-- 服务器授权信息 -->
<servers>
<server>
<id>nexus-releases</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
</servers>
<!-- 镜像,即对repository重定向 -->
<mirrors>
<mirror>
<id>mirrorId</id>
<!-- 镜像对应的远程仓库,需和仓库的ID匹配,使用逗号分隔多个远程仓库 -->
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
</mirrors>
<!-- 分发管理 。比如我需要把开发的工程打包到远程仓库里做管理-->
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Release Repository</name>
<url>http://127.0.0.1:8080/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<name>Nexus Snapshot Repository</name>
<url>http://127.0.0.1:8080/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<!-- 配置信息 -->
<profiles>
<profile>
<id>jdk-1.4</id>
<activation>
<jdk>1.4</jdk>
</activation>
<!-- 远程仓库列表 -->
<repositories>
<repository>
<id>jdk14</id>
<name>Repository for JDK 1.4 builds</name>
<url>http://www.myhost.com/maven/jdk14</url>
<layout>default</layout>
</repository>
</repositories>
</profile>
</profiles>
</settings>
理解repository,mirror,server
-
repository
存放各种jar包和maven插件。当向仓库请求插件或依赖的时候,会先检查local repository,如果local repository有则直接返回,否则会向remote repository请求,并缓存到local repository -
mirror
把请求里的remote repository地址,重定向到mirror里配置的地址。
比如有A,B两个repository都可以找到对应资源,A为公服,B是私服。我把A作为repository,B作为mirror,实际访问的时候会到B,这样提升了下载速度。并且如果环境变化,我也可以很灵活的在repository或mirror中做切换 -
server
访问有的repository或mirror的服务器需配置一些授权信息
profile
理解profile
- 可以解决项目在不同环境下,用不同的配置信息做构建,或者在不同环境采用不同的构建方式来构建
- profile在settings.xml,pom.xml里都可以做配置,如果settings.xml有profile,pom.xml里没有,则所有项目都会使用settings.xml里的profile,如果pom.xml里有,项目就会使用自己的profile。
配置profile
-
不同环境,使用不同的配置文件构建项目
定义profile的相关参数:<profiles> <profile> <!-- 本地开发环境 --> <打包的时候根据该id指定:mvn package -P dev> <id>dev</id> <properties> <!-- 对应了src/main/resources/dev --> <profiles.active>dev</profiles.active> </properties> <activation> <!-- 默认激活 --> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <!-- 测试环境 --> <id>test</id> <properties> <!-- 对应了src/main/resources/test--> <profiles.active>test</profiles.active> </properties> </profile> </profiles>
根据上述参数配置资源的构建过程:
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>test/*</exclude> <exclude>pro/*</exclude> <exclude>dev/*</exclude> </excludes> </resource> <resource> <directory>src/main/resources/${profiles.active}</directory> </resource> </resources> </build>
-
同一配置文件,通过替换占位符,被赋予不同的值
定义profile的相关参数:<profiles> <profile> <id>dev</id> <properties> <db.url>localhost</database.host> </properties> </profile> <profile> <id>test</id> <properties> <db.url>192.168.142.154</database.host> </properties> </profile> <profiles>
构建资源的配置:
<build> <resources> <resource> <directory>src/main/resources</directory> <!-- 开启替换占位符 --> <filtering>true</filtering> </resource> </resources> </build>
配置文件:
src/main/resources/db.propertiesdatabase.pool.url=${db.url}
-
不同环境,用不同的构建方式做构建
只需要把build的相关内容写到profile里面即可
Maven项目主要构建过程(build)
- clean(清除)
- default-validate(缺省验证)
- initialize(初始化)
- generate-sources, process-sources, generate-resources, process-resources(加载运行资源)
- compile(编译)
- test(执行测试用例)
- package(打包)
- verify(验证)
- install(安装)
- deploy(部署)
常用指令
-
mvn clean
清除历史打的包(即删除target文件夹,不影响本地的maven库) -
mvn compile
项目编译(就是生成class文件) -
mvn package
项目编译打包 -
mvn xxx -Dmaven.skip.test=true
跳过测试,对测试用例不编译也不执行 -
mvn xxx -DskipTests
跳过测试,对测试用例不执行但会编译 -
mvn install
项目编译打包并安装到本地maven库(解决项目间的依赖问题) -
mvn install:install-file -DgroupId=org.freemarker -DartifactId=freemarker -Dversion=2.3.23 -Dpackaging=jar -Dfile=J:\freemarker-2.3.23.jar
手动加入文档到maven库里(解决引入在中央仓库里没有的jar包问题) -
mvn clean install -e -U :-e详细异常,-U强制更新
-
mvn clean package -Ptest :按profile为test的配置打包
Maven的打包规则
jar
-
默认规则
项目路径下的target目录为maven的项目构建目录
src/main/java 里面的*.java文件会被编译,并将生成的*.class放到target/classes目录下
src/main/java 里面的其他文件,不会做任何操作
src/main/resources里面的文件,会被直接拷贝到target/classes目录下
src/test/java 里面的*.java文件会被编译,并将生成的*.class放到target/test-classes目录下
src/test/java 里面的其他文件,不会做任何操作
src/test/resources里面的文件,会被直接拷贝到target/test-classes目录下
target/classes目录下的文件会被最终打到jar包里 -
通过Maven插件,自定义打包规则
war
- 默认规则
项目路径下的target目录为maven的项目构建目录
src/main/java的处理规则同jar包
src/main/resources的处理规则同jar包
src/test/java的处理规则同jar包
src/test/resources的处理规则同jar包
webapp里面的的文件,会被直接拷贝到与最终打出的war包同名的一个文件夹下
target/classes目录下的文件会被直接拷贝到与最终打出的war包同名的一个文件夹下的WEB-INF/classes目录下
项目的相关依赖会被拷贝到与最终打出的war包同名的一个文件夹下的WEB-INF/lib目录下
与最终打出的war包同名的文件夹下的文件会被打包成war包 - 通过Maven插件,自定义打包规则
使用maven插件
Maven生命周期的阶段(phase)默认绑定的插件目标
冒号后面即是绑定的插件目标,冒号前面是插件的前缀(prefix)
关于插件的前缀(prefix),比如我们平常写的:
<!-- maven-${prefix}-plugin-->
<artifactId>maven-compiler-plugin</artifactId>
<!-- ${prefix}-maven-plugin-->
<artifactId>tomcat7-maven-plugin</artifactId>
关于插件目标(goal):为了能够复用代码,它往往能够完成多个任务, 这些功能聚集在一个插件里,每个功能就是一个目标。
配置插件所绑定的生命周期(Maven默认绑定的插件不需要配置)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<!--id:就是个唯一标识,随便写-->
<id>copy</id>
<!--phase:即绑定的生命周期-->
<phase>install</phase>
<goals>
<!--goal:即执行的插件目标-->
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
常用插件
-
tomcat7-maven-plugin:Maven内置的tomcat
-
maven-compiler-plugin:Maven编译时用的插件
-
maven-resources-plugin:Maven处理项目资源文件并拷贝到输出(构建)目录的插件
-
maven-dependency-plugin:Maven的依赖插件,负责将maven的相关依赖输出到指定目录
-
maven-jar-plugin:Maven用来打jar包的插件。可指明jar包生成位置,jar的入口类
-
maven-assembly-plugin:与maven-jar-plugin类似
-
maven-shade-plugin:Maven用来打jar的插件。可做更多详细的配置,比如:将部分jar包添加或排除,将jar包内部资源添加或排除,将依赖的类重命名并打包进来,修改包的后缀名:
-
maven-war-plugin:Maven用来打war的插件。可以配置具体哪些资源被打到什么位置等
-
maven-source-plugin:把源码也打到包里
插件使用综合实例
-
使用Maven内置的tomcat启动服务
相关指令: tomcat7:run ,tomcat7:exec-war , tomcat7:exec-war-only<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <!-- 指定端口 --> <port>9090</port> <!-- 请求路径 --> <path>/</path> </configuration> </plugin>
-
指定编译的JDK版本和编码格式
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin>
-
以com.alibaba.dubbo.container.Main作为启动类打jar包
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <classesDirectory>target/classes/</classesDirectory> <archive> <manifest> <mainClass>com.alibaba.dubbo.container.Main</mainClass> <useUniqueVersions>false</useUniqueVersions> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> <manifestEntries> <Class-Path>.</Class-Path> </manifestEntries> </archive> </configuration> </plugin>
-
打jar包时,把依赖拷贝到构建目录下
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy</id> <phase>install</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> </configuration> </execution> </executions> </plugin>
报错
- 项目启动报错
Invalid byte 3 of 3-byte UTF-8 sequence
解决:
maven-resources-plugin不指定的话,maven默认使用平台的编码格式<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin>