Maven

What is Maven?

  flowchart TB
	MR[Maven Repos]
	LR[Local Repos]
	RR[Remote Repos]
	CR[Central Repos]
	PR[Private Repos]
	ORR[Others Remote Repos]

	MR --> LR
	MR ------>|if local repos doesn't have lib| RR

	RR ----> CR
	RR ----> PR
	RR ----> ORR
  1. Project Management Tool
  2. Build Management and Dependencies(管理多個 jar)

Maven Repository

  flowchart LR
	subgraph Center
		C[(Maven)]
		end

	subgraph Left
	direction TB
		subgraph App
		Spring
		Hibernate
		Commons_Logging
		JSON
		...
		end
	end

	subgraph Right
	direction TB
		subgraph Maven_Central_Repository_Remote_Internet
		Spring_JAR_files
		Hibernate_JAR_files
		ApacheCommons_JAR_files
		JSON_JAR_files
		end
	end

	Left <====> Center <====> Right

settings.xml

用於設定 Maven 全局配置:

<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
                          https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository/>
  <interactiveMode/>
  <usePluginRegistry/>
  <offline/>
  <pluginGroups/>
  <servers/>
  <mirrors/>
  <proxies/>
  <profiles/>
  <activeProfiles/>
</settings>

LocalRepository

設置本地倉庫的路徑。預設:~/.m2/repository

<localRepository>${user.home}/.m2/repository</localRepository>

InteractiveMode

Maven 是否需和用戶交互以獲得輸入:

<interactiveMode>true</interactiveMode>

Offline

表示 Maven 是否需要離線模式下運行。由於網路或資安因素,服務器不能連接遠程倉庫時,此配置十分有用。

<offline>false</offline>

Servers

類似 username、password 等訊息不應該在 pom.xml,這些訊息可配置在 settings.xml

<servers>
  <server>
    <id>server001</id>
    <username>my_login</username>
    <password>my_password</password>
    <privateKey>${usr.home}/.ssh/id_dsa</privateKey>
    <passphrase>some_passphrase</passphrase>
    <filePermissions>664</filePermissions>
    <directoryPermissions>775</directoryPermissions>
  </server>
</servers>

Mirrors

為倉庫列表配置的下載鏡像列表:

<mirrors>
  <mirror>
    <id>planetmirror.com</id>
    <name>PlanetMirror Australia</name>
    <url>http://downloads.planetmirror.com/pub/maven2</url>
    <mirrorOf>central</mirrorOf>
  </mirror>
</mirrors>

Proxies

用來配置代理:

<proxies>
  <proxy>
    <id>myproxy</id>
    <active>true</active>
    <protocol>http</protocol>
    <host>proxy.somewhere.com</host>
    <port>8080</port>
    <username>proxyuser</username>
    <password>somepassword</password>
    <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
  </proxy>
</proxies>

Dependency

從遠程倉庫下載 jar 到本地,jar 檔之間依賴傳遞。

Scope

Scope說明部署時打包
compile預設值,此 jar 是所有階段需要的
test只有在測試時需要使用,如 junit
runtime只有在運行時需要使用,如 jdbc
provided期望由 JDK、Tomcat 等來提供,如 servlet.jar
system由系統提供,需配合 systemPath 使用-

Plugins

maven-compiler-plugin

直接打包,不打包依賴,僅打包 source code 到 JAR 包中:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>UTF-8</encoding>
        <skipTests>true</skipTests>
        <verbose>true</verbose>
        <showWarnings>true</showWarnings>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
    </configuration>
</plugin>

maven-jar-plugin

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<configuration>
		<archive>
			<manifest>
				<addClasspath>true</addClasspath>
				<classpathPrefix>lib/</classpathPrefix>
				<mainClass>net.arplanets.arc.RSApplication</mainClass>
			</manifest>
		</archive>
	</configuration>
</plugin>

maven-dependency-plugin

複製 Project 依賴的所有 jar 包:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
	<executions>
		<execution>
			<id>copy</id>
			<phase>package</phase>
			<goals>
				<goal>copy-dependencies</goal>
			</goals>
			<configuration>
				<outputDirectory>${project.build.directory}/lib</outputDirectory>
				<overWriteReleases>false</overWriteReleases>
				<overWriteSnapshots>false</overWriteSnapshots>
				<overWriteIfNewer>true</overWriteIfNewer>
			</configuration>
		</execution>
	</executions>
</plugin>

maven-shade-plugin

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.2.4</version>
  <configuration>
	<createDependencyReducedPom>false</createDependencyReducedPom>
	<shadedArtifactAttached>true</shadedArtifactAttached>
  </configuration>
  <executions>
	<execution>
	  <phase>package</phase>
	  <goals>
		<goal>shade</goal>
	  </goals>
	  <configuration>
		<minimizeJar>true</minimizeJar>
	  </configuration>
	</execution>
  </executions>
</plugin>

maven-assembly-plugin

<plugin>
	<artifactId>maven-assembly-plugin</artifactId>
	<executions>
		<execution>
			<phase>package</phase>
			<goals>
				<goal>single</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<descriptorRefs>
			<descriptorRef>jar-with-dependencies</descriptorRef>
		</descriptorRefs>
	</configuration>
</plugin>

Descriptor 選項:

選項說明
bin類似於預設打包,會將 bin 目錄下的文件打到包中
jar-with-dependencies會將所有依賴都解壓打包到生成物中
src只將源碼目錄下的文件打包
project將整個 project 資源打包

maven-surefire-plugin

跳過測試,等同於 mvn package -Dmaven.test.skip

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

maven-resources-plugin

設置資源文件的編碼方式:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
        <encoding>${project.build.sourceEncoding}</encoding>
    </configuration>
</plugin>

Build

<build>
	<resources>
	    <resource>
	        <directory>src/main/resources</directory>
	        <filtering>true</filtering>
	        <excludes>
	            <exclude>**/banner.txt</exclude>
	            <exclude>**/**/spring.factories</exclude>
	            <exclude>**/*.properties</exclude>
	            <exclude>**/logback-spring.xml</exclude>
	            <exclude>**/*.yml</exclude>
	        </excludes>
	    </resource>
	</resources>
</build>

Maven Custom Plugin

package com.example.maven.plugin;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;

@Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
	@Parameter(defaultValue = "${project}", required = true, readonly = true)
	MavenProject project;
	@Parameter(property = "scope")
	String scope;

	@Override
    public void execute() throws MojoExecutionException, MojoFailureeException {
        List<Dependency> dependencies = project.getDependencies();
        long numDependencies = dependencies.stream()
            .filter(d -> (scope == null || scope.isEmpty()) || scope.equals(d.getScope()))
            .count();
		getLog().info("Number of dependencies: " + numDependencies);
    }
}

執行 mvn install 後,在 pom.xml 中加入 plugin:

<build>
	<plugins>
		<plugin>
			<groupId>com.app</groupId>
			<artifactId>counter-maven-plugin</artifactId>
			<version>1.0</version>
			<executions>
				<execution>
					<goals>
						<goal>dependency-counter</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<scope>test</scope>
			</configuration>
		</plugin>
	</plugins>
</build>

Maven Scan Extension

生成類似 gradle scan 的報告:

<extensions>
	<extension>
		<groupId>com.gradle</groupId>
		<artifactId>gradle-enterprise-maven-extension</artifactId>
		<version>1.11.1</version>
	</extension>
</extensions>

Private Repository Server

  • JFrog Artifactory
  • Sonatype Nexus
  • Apache Archiva

Benefits

  1. 新開發人員加入專案更容易
  2. 容易找到 code、properties files、unit tests、web files 等
  3. Maven 專案具有可攜性

Deploy

類型部署方式
jar部署到私有 Nexus Server
war使用 Maven Cargo 部署到 Tomcat Server,或使用 Jenkins(更強大)