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>