maven 高級玩法


maven 高級玩法

標簽(空格分隔): maven


實用技巧

Maven 提速

多線程

# 用 4 個線程構建,以及根據 CPU 核數每個核分配 1 個線程進行構建
$ mvn -T 4 clean install
$ mvn -T 1C clean install

跳過測試

-DskipTests               # 不執行測試用例,但編譯測試用例類生成相應的 class 文件至 target/test-classes 下
-Dmaven.test.skip=true    # 不執行測試用例,也不編譯測試用例類

# 結合上文的`並行執行`
$ mvn -T 1C clean install -Dmaven.test.skip=true

# 如果還是阻塞: 資源管理器 - shutdown all java app

# 如果 jar 包過大,可以下載按照路徑放在 repository 中,之后可能還需要 mvn clean 來下載 groovy-all-2.3.11.pom 文件 (mvnrepository.com)
D:\apps\maven\repository\org\codehaus\groovy\groovy-all\2.3.11\groovy-all-2.3.11.jar

編譯失敗后,接着編譯

# 如果是 Apache Eagle 之類帶有幾十個子項目的工程,如果從頭編譯所有的模塊,會很耗功夫
# 通過指定之前失敗的模塊名,可以繼續之前的編譯
$ mvn -rf :moduleName clean install

跳過失敗的模塊,編譯到最后再報錯

$ mvn clean install --fail-at-end

使用 Nexus 本地私服

http://www.cnblogs.com/quanyongan/archive/2013/04/24/3037589.html

使用 Aliyun 國內鏡像

可以大大提高編譯下載速度

<mirror>
  <id>alimaven</id>
  <name>aliyun maven</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
  <mirrorOf>central</mirrorOf>
</mirror>

指定 Repository 目錄

<!-- Default: ~/.m2/repository  -->
<localRepository>D:\apps\maven\repository</localRepository>

如何使用 Maven 編譯指定 module

$ mvn install -pl <module_name> -am

  -pl, --projects      (Build specified reactor projects instead of all project)
  -am, --also-make     (If project list is specified, also build projects required by the list)
  -amd, --also-make-dependents    (If project list is specified, also build projects that depend on)

Maven 標准目錄結構

src/main/java             Application/Library sources
src/main/resources        Application/Library resources
src/main/filters          Resource filter files
src/main/webapp           Web application sources
src/test/java             Test sources
src/test/resources        Test resources
src/test/filters          Test resource filter files
src/it                    Integration Tests (primarily for plugins)
src/assembly              Assembly descriptors
src/site                  Site
LICENSE.txt               Project's license
NOTICE.txt                Notices and attributions required by libraries that the project depends on
README.txt                Project's readme

如何在 Maven 中使用多個 source

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>add-source</goal>
      </goals>
      <configuration>
        <sources>
          <source>src/main/scala</source>
        </sources>
      </configuration>
    </execution>
  </executions>
</plugin>

Using Scala UnitTest by Maven

安裝 Scala

Maven 依賴

<dependency>
  <groupId>org.scalatest</groupId>
  <artifactId>scalatest_2.10</artifactId>
  <version>2.2.1</version>
</dependency>

創建 unittest 需要的 trait

import org.scalatest._
abstract class UnitTestStyle extends FlatSpec
with Matchers with OptionValues with Inside with Inspectors

編寫測試

import spark.streaming.detect.SendNetflow
class SendNetflowTest extends UnitTestStyle {

  "Clean method" should "output a string" in {

    val s = "0,tcp,http,SF,229,9385,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,9,9,0.00,0.00,0.00,0.00,1.00,0.00,0.00,9,90,1.00,0.00,0.11,0.04,0.00,0.00,0.00,0.00,normal."
    SendNetflow.clean(s) should be("0,229,9385,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,9,9,0.00,0.00,0.00,0.00,1.00,0.00,0.00,9,90,1.00,0.00,0.11,0.04,0.00,0.00,0.00,0.00\tnormal.")
  }

  it should "throw Exception if an empty string is inputted" in {
    val emptyS = ""
    a[RuntimeException] should be thrownBy {
    SendNetflow.clean(emptyS)
  }
}

Using slf4j by Maven

Maven 配置

<slf4j.version>1.7.12</slf4j.version>
<logback.version>1.1.3</logback.version>

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>${logback.version}</version>
</dependency>

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>${logback.version}</version>
  <exclusions>
    <exclusion>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>${slf4j.version}</version>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>${slf4j.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>log4j-over-slf4j</artifactId>
  <version>${slf4j.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jul-to-slf4j</artifactId>
  <version>${slf4j.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

logback.xml in resources directory

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <!-- %p:Level %m:Message %c.%M:Package+Method %F:%L:File+Line -->
  <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} | %p | %m | %c.%M | %F:%L %n"/>

  <!-- Print in Console -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder charset="UTF-8">
    <pattern>${pattern}</pattern>
    </encoder>
  </appender>

  <root level="ALL">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

編碼

示例
private static final Logger log = LoggerFactory.getLogger(ZKEventWatch.class);
log.info(state);
遇到的坑
SLF4J multi bindings
遇到的坑
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/apps/maven/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/apps/maven/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]

解決
<!-- 使用 Apache Curator 需要 exclusion slf4j-log4j12,否則會出現問題 -->
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-recipes</artifactId>
  <version>${apache.curator.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
  </exclusions>
</dependency>

導出依賴 Jar

<build>
  <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.10</version>
    <configuration>
      <outputDirectory>${project.build.directory}/lib</outputDirectory>
      <excludeTransitive>false</excludeTransitive>
      <stripVersion>false</stripVersion>
    </configuration>
    </plugin>
  </plugins>
</build>
$ mvn clean dependency:copy-dependencies

# 將 yuzhouwan-flume 依賴的 jars 都 導出到一個文件夾
# 用相對路徑,不能是 絕對路徑,否則 maven 會報錯:Unknown lifecycle phase "Java"
$ mvn dependency:copy-dependencies -f yuzhouwan-flume/pom.xml -DoutputDirectory=yuzhouwan-flume/target/lib
$ mvn dependency:copy-dependencies -f yuzhouwan-api/yuzhouwan-admin-api/pom.xml -DoutputDirectory=target/lib

Profiles

日志級別

-Dorg.slf4j.simpleLogger.defaultLogLevel=error

Generate Code for Antlr

 mvn clean install -T 1C -DskipTests=true -Dorg.slf4j.simpleLogger.defaultLogLevel=error -B

Maven Properties

mvn clean install -Dmy.property=propertyValue

Maven Check Style

 mvn clean install -Dcheckstyle.skip

Maven Update

$ mvn clean install -U
# -U means force update of dependencies.

Maven License Check

參考http://code.mycila.com/license-maven-plugin/

Maven Dependency

Pre-download

$ mvn dependency:go-offline

Version-compare

# 在開發一些 Coprocessor 的時候,需要保證和 HBase 集群的依賴 jar 版本一致,可以使用該方法
$ mvn versions:compare-dependencies -DremotePom=org.apache.hbase:hbase:0.98.8-hadoop2 -DreportOutputFile=depDiffs.txt

Maven Proxy

命令行設置

# Linux (bash)
$ export MAVEN_OPTS="-DsocksProxyHost=10.10.10.10 -DsocksProxyPort=8080"
# Windows
$ set MAVEN_OPTS="-DsocksProxyHost=10.10.10.10 -DsocksProxyPort=8080"

配置文件 maven setting.xml

  <proxies>
    <!--<proxy>
      <id>http-proxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>10.10.10.10</host>
      <port>8888</port>
      <nonProxyHosts>*.yuzhouwan.com</nonProxyHosts>
    </proxy>-->

    <proxy>
      <id>socks-proxy</id>
      <active>true</active>
      <protocol>socks5</protocol>
      <host>127.0.0.1</host>
      <port>1080</port>
      <nonProxyHosts>*.yuzhouwan.com</nonProxyHosts>
    </proxy>
  </proxies>

Avro 插件

創建 avsc 文件

{
  "namespace": "com.yuzhouwan.hacker.avro",
  "type": "record",
  "name": "User",
  "fields": [
    {
      "name": "name",
      "type": "string"
    },
    {
      "name": "favorite_number",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "favorite_color",
      "type": [
        "string",
        "null"
      ]
    }
  ]
}

使用 avro-tools 工具生成 Avro 類

# 下載 avro-tools
# https://mvnrepository.com/artifact/org.apache.avro/avro-tools/1.8.1
# http://archive.apache.org/dist/avro/avro-1.8.1/java/                    (better)
$ wget http://archive.apache.org/dist/avro/avro-1.8.1/java/avro-tools-1.8.1.jar -c avro-tools-1.8.1.jar

# 利用 avsc 文件中的 Schema 生成 Avro 類
$ java -jar avro-tools-1.8.1.jar compile schema user.avsc .

使用 avro-plugin 插件生成 Avro 類

<properties>
  <apache.avro.version>1.7.7</apache.avro.version>
</properties>

<dependencies>
  <!-- apache avro -->
  <dependency>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro</artifactId>
    <version>${apache.avro.version}</version>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro-maven-plugin</artifactId>
      <version>${apache.avro.version}</version>
      <executions>
        <execution>
          <phase>generate-sources</phase>
          <goals>
            <goal>schema</goal>
          </goals>
          <configuration>
            <sourceDirectory>${project.basedir}/src/main/resources/avsc/</sourceDirectory>
            <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Shade 插件解決 Jar 多版本共存

適用場景

在整合大型項目時,可能都依賴 commons-collections 此類的工具包,但是也可能 commons-collections 的版本卻因為不一致,導致沖突。可以通過 Shade 插件的 relocation 方法進行重定向,此時沖突的依賴 package 名,會被重命名,並且依賴該 jar 的程序,都會被自動替換為新的 package 名

基本用法

實例一

<properties>
    <maven.shade.plugin.version>2.4.3</maven.shade.plugin.version>
</properties>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.4.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <createSourcesJar>true</createSourcesJar>
                <artifactSet>
                    <excludes>
                        <exclude>org.mapdb.*</exclude>
                    </excludes>
                </artifactSet>
                <relocations>
                    <relocation>
                        <pattern>org.apache.commons.collections</pattern>
                        <shadedPattern>com.yuzhouwan.org.apache.commons.collections</shadedPattern>
                    </relocation>
                </relocations>
            </configuration>
        </execution>
    </executions>
</plugin>

實例二

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>${maven.shade.plugin.version}</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <shadedClassifierName>all</shadedClassifierName>
                <createSourcesJar>true</createSourcesJar>
                <artifactSet>
                    <!-- 因為 org.glassfish 里面存在類似 public static class Builder implements javax.ws.rs.client.Invocation.Builder 全限定名的寫法 -->
                    <!-- 所以只能用 shade 去隱藏 com.sun.jersey -->
                    <excludes>
                        <exclude>org.glassfish.*</exclude>
                    </excludes>
                </artifactSet>
                <relocations>
                    <relocation>
                        <pattern>javax.ws</pattern>
                        <shadedPattern>shade.javax.ws</shadedPattern>
                    </relocation>
                    <relocation>
                        <pattern>org.apache.curator</pattern>
                        <shadedPattern>shade.org.apache.curator</shadedPattern>
                    </relocation>
                    <!--<relocation>
                        <pattern>org.glassfish</pattern>
                        <shadedPattern>shade.org.glassfish</shadedPattern>
                    </relocation>
                    <relocation>
                        <pattern>com.sun.jersey</pattern>
                        <shadedPattern>shade.com.sun.jersey</shadedPattern>
                    </relocation>-->
                </relocations>
            </configuration>
        </execution>
    </executions>
</plugin>

通過 Shade 將問題解決后,部署上線后,依賴沖突復現

 因為官方明確指出 java.io.File.listFiles() 方法返回的文件序列順序,是不做保證的。所以,上線后運行環境發生變化,加載 lib 目錄下的 jar 包順序,可能會發生變化。這時候,就需要利用不同 lib 目錄,並修改 classpath 的方式,將 jar 包加載順序確定下來

 例如,在整合 Druid 這類依賴樹比較龐大的工程,就遇到了這么一種情況。Druid 中 com.sun.jersey (1.19) 和 Dataflow 中 org.glassfish.jersey (2.25.1) 發生沖突。增加了上述實例二中的 Shade 操作仍然會在線上環境,復現依賴沖突。這時,我們可以通過增加一個 lib_jersey 目錄,存放 javax.ws.rs-api-2.1.jar,並修改 classpath 為 lib_jersey/*:lib/*。以此,保證了 lib_jersey 中的依賴得以優先加載,從而解決沖突

參考

http://maven.apache.org/plugins/maven-shade-plugin/

Assembly 插件

不同模塊的依賴,打包到不同的目錄下

具體步驟

第一步,先在負責打包分發的 distribution 模塊中,設置 pom.xml 文件

<properties>
    <maven.assembly.plugin.version>2.3</maven.assembly.plugin.version>
</properties>

<packaging>pom</packaging>

<dependencies>
    <dependency>
        <groupId>com.yuzhouwan</groupId>
        <artifactId>core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yuzhouwan</groupId>
        <artifactId>ai</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yuzhouwan</groupId>
        <artifactId>bigdata</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>${maven.assembly.plugin.version}</version>
            <executions>
                <execution>
                    <id>assemble</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptors>
                            <descriptor>src/assembly/bin.xml</descriptor>
                            <descriptor>src/assembly/src.xml</descriptor>
                        </descriptors>
                        <tarLongFileMode>gnu</tarLongFileMode>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

第二步,創建好對應的 bin.xml 和 src.xml

<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

    <id>bin</id>

    <formats>
        <format>dir</format>
        <format>tar.gz</format>
    </formats>

    <baseDirectory>yuzhouwan-${project.version}-bin</baseDirectory>

    <fileSets>
        <fileSet>
            <directory>../</directory>

            <excludes>
                <exclude>**/target/**</exclude>
                <exclude>**/.classpath</exclude>
                <exclude>**/.project</exclude>
                <exclude>**/.settings/**</exclude>
                <exclude>lib/**</exclude>
                <exclude>conf/**</exclude>
            </excludes>

            <includes>
                <include>README</include>
                <include>LICENSE</include>
                <include>NOTICE</include>
                <include>CHANGELOG</include>
                <include>RELEASE-NOTES</include>
                <include>conf/</include>
            </includes>
        </fileSet>

        <fileSet>
            <directory>../</directory>
            <includes>
                <include>bin/yuzhouwan-cli.sh</include>
            </includes>
            <fileMode>0777</fileMode>
            <directoryMode>0755</directoryMode>
        </fileSet>
    </fileSets>

    <moduleSets>
        <moduleSet>
            <includeSubModules>false</includeSubModules>
            <useAllReactorProjects>true</useAllReactorProjects>
            <includes>
                <include>com.yuzhouwan:yuzhouwan-core</include>
            </includes>
            <excludes>
                <exclude>com.yuzhouwan:ai</exclude>
                <exclude>com.yuzhouwan:bigdata</exclude>
            </excludes>
            <binaries>
                <outputDirectory>lib/core</outputDirectory>
                <unpack>false</unpack>
                <dependencySets>
                    <dependencySet>
                        <useProjectArtifact>false</useProjectArtifact>
                        <useTransitiveDependencies>true</useTransitiveDependencies>
                        <unpack>false</unpack>
                        <excludes>
                            <exclude>com.yuzhouwan:ai</exclude>
                            <exclude>com.yuzhouwan:bigdata</exclude>
                        </excludes>
                    </dependencySet>
                </dependencySets>
            </binaries>
        </moduleSet>

        <moduleSet>
            <includeSubModules>false</includeSubModules>
            <useAllReactorProjects>true</useAllReactorProjects>
            <includes>
                <include>com.yuzhouwan:ai</include>
            </includes>
            <excludes>
                <exclude>com.yuzhouwan:bigdata</exclude>
            </excludes>
            <binaries>
                <outputDirectory>lib/plugins/ai</outputDirectory>
                <unpack>false</unpack>
                <dependencySets>
                    <dependencySet>
                        <useProjectArtifact>false</useProjectArtifact>
                        <useTransitiveDependencies>true</useTransitiveDependencies>
                        <unpack>false</unpack>
                        <excludes>
                            <exclude>com.yuzhouwan:bigdata</exclude>
                        </excludes>
                    </dependencySet>
                </dependencySets>
            </binaries>
        </moduleSet>

        <moduleSet>
            <includeSubModules>false</includeSubModules>
            <useAllReactorProjects>true</useAllReactorProjects>
            <includes>
                <include>com.yuzhouwan:bigdata</include>
            </includes>
            <excludes>
                <exclude>com.yuzhouwan:ai</exclude>
            </excludes>
            <binaries>
                <outputDirectory>lib/plugins/bigdata</outputDirectory>
                <unpack>false</unpack>
                <dependencySets>
                    <dependencySet>
                        <useProjectArtifact>false</useProjectArtifact>
                        <useTransitiveDependencies>true</useTransitiveDependencies>
                        <unpack>false</unpack>
                        <excludes>
                            <exclude>com.yuzhouwan:ai</exclude>
                        </excludes>
                    </dependencySet>
                </dependencySets>
            </binaries>
        </moduleSet>
    </moduleSets>
</assembly>
<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

    <id>src</id>

    <formats>
        <format>dir</format>
        <format>tar.gz</format>
    </formats>

    <baseDirectory>yuzhouwan-${project.version}-src</baseDirectory>

    <fileSets>
        <fileSet>
            <directory>../</directory>

            <excludes>
                <exclude>**/target/**</exclude>
                <exclude>**/.classpath</exclude>
                <exclude>**/.project</exclude>
                <exclude>**/*.iml</exclude>
                <exclude>**/.settings/**</exclude>
                <exclude>lib/**</exclude>
            </excludes>

            <includes>
                <include>.ci</include>
                <include>.gitignore</include>
                <include>DEVNOTES</include>
                <include>README</include>
                <include>LICENSE</include>
                <include>NOTICE</include>
                <include>CHANGELOG</include>
                <include>RELEASE-NOTES</include>
                <include>bin/**</include>
                <include>conf/**</include>
                <include>native/**</include>
                <include>pom.xml</include>
                <include>dev-conf/**</include>
                <include>yuzhouwan-core/**</include>
                <include>yuzhouwan-ai/**</include>
                <include>yuzhouwan-bigdata/**</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>


構建完成之后,即可看到 yuzhouwan-ai 和 yuzhouwan-bigdata 模塊的依賴,分別被打包到了 plugins/ai 和 plugins/bigdata 目錄下

# 需要預先安裝 tree 命令(yum install tree -y)
$ tree
  .
  ├── bin
  │   └── yuzhouwan-cli.sh
  └── lib
      ├── core
      └── plugins
          ├── ai
          └── bigdata

踩過的坑

模塊間存在版本沖突的 jar 包
問題描述

Currently, inclusion of module dependencies may produce unpredictable results if a version conflict occurs

解決:
如果上述 yuzhouwan-ai 和 yuzhouwan-bigdata 模塊,與 yuzhouwan-common 模塊存在版本沖突的 jar 包,則需要將 bin.xml 拆解成 bin-common.xml、bin-ai.xml 和 bin-bigdata.xml 三個 assembly 配置文件,依次進行構建(此時需要將 id 設置成一樣的,不然會被構建到不同的目錄下)。否則,版本沖突的 jar 包,將只能保留其中一個版本,且具體保留哪個版本是不確定的

常見問題

Maven Archetype 的選擇

Maven web 項目

選擇 Archetype 的時候,選擇 maven-archetype-webapp

其他語言編譯出來的 Jar

Clojar

如果需要在 Maven 中,添加不是 Maven 中央倉庫的 Repository,例如 Clojar:

<repositories>
  <repository>
    <id>clojars.org</id>
    <url>http://clojars.org/repo</url>
  </repository>
</repositories>

本地緩存

Maven 中出現 Repository 被緩存在本地,則可以添加下面屬性

<repository>
  <id>clojars.org</id>
  <url>http://clojars.org/repo</url>
  <releases>
    <enabled>true</enabled>
    <updatePolicy>always</updatePolicy>
  </releases>
  <snapshots>
    <enabled>true</enabled>
    <updatePolicy>always</updatePolicy>
  </snapshots>
</repository>

編譯問題

JDK 版本不一致

描述:

Error:java: Compilation failed: internal java compiler error

解決:

<build>
  <finalName>elastic-netflow-v5</finalName>

  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.2</version>
      <configuration>
        <source>1.7</source>
        <target>1.7</target>
      </configuration>
    </plugin>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-release-plugin</artifactId>
      <version>2.4.1</version>
    </plugin>
  </plugins>
</build>

Scala 版本不一致

描述:

[ERROR] error: error while loading <root>, Error accessing D:\.m2\repository\org\apache\curator\curator-client\2.4.0\curator-client-2.4.0.jar
[ERROR] error: scala.reflect.internal.MissingRequirementError: object java.lang.Object in compiler mirror not found.

解決:

查看 pom 文件中指定的 scala 版本,切換到對應的版本,進行編譯即可

存在沒有下載好的依賴

描述:

Error creating properties files for forking; nested exception is java.io.IOException: No such file or directory

解決:

mvn dependency::tree

離線build

$ mvn install -o

本地 mvn clean install 到 .m2/repository 中的 jar 和 倉庫中的不一致時

描述:

"Class not found 'xxxx' Empty test suite" in java unittest, after change the modules' names

解決:

Maven ->Reimport->Generte Source and Update Folder
Ctrl + F9->Make Project

打包存在臟程序:

war:war 之前需要先執行 mvn clean install。否則,會因為 profiles 的緣故,導致 war 包中 缺少文件

語法問題

Maven 中無法識別 ${project.version}

需要將所有(除了 root / parent 模塊)的 <version>1.0</version> 中的具體版本號(如 1.0.0)全部替換成 "${project.version}"

插件問題

xxx module must not contain source root. the root already belongs to module xxx

解決:

Artifacts Setting  ->  Modules -> Sourc tab
delete the fold by clicking on the X icon to the right of it

ExecutionException The forked VM terminated without properly saying goodbye

描述:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project eagle-app-streamproxy: ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?

解決

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>${maven-surefire.version}</version>
  <configuration>
    <!-- 增加 argLine 參數以調整 JVM -->
    <argLine>-Xmx2048m -Xms1024m -XX:MaxPermSize=512m -XX:-UseGCOverheadLimit</argLine>
    <forkMode>always</forkMode>
  </configuration>
</plugin>

Assembly 插件報錯 java.lang.StackOverflowError

解決:

# 調大默認的堆棧大小
export MAVEN_OPTS=-Xss2m

補充:

-Xms:jvm 進程啟動時分配的內存
-Xmx:jvm 進程運行過程中最大能分配到的內存
-Xss:jvm 進程中啟動線程,為每個線程分配的內存大小

依賴問題

Maven 中央倉庫找不到對應版本的依賴
如何將其他項目的 jar 安裝到 maven 倉庫中
1,利用命令安裝

$ mvn install:install-file -Dfile=<jar 包的位置> -DgroupId=<上面的 groupId> -DartifactId=<上面的 artifactId> -Dversion=<上面的 version> -Dpackaging=jar -DgeneratePom=true -DpomFile=<指定一個 pom.xml 添加進去>

$ mvn install:install-file -Dfile=G:\ES\yuzhouwan_netflow-rest\lib\ite-esmanage-0.7.2-SNAPSHOT.jar -DgroupId=ite -DartifactId=esmanage -Dversion=0.7.2-SNAPSHOT -Dpackaging=jar -DgeneratePom=true -DpomFile=C:\yuzhouwan\Maven\pom.xml

# -DgeneratePom 沒有成功
# 原因是 這個第三方的 jar 中,pom.xml 路徑不對,必須手動 copy 出來,並用 -DpomFile 的方式導入

2,利用插件安裝

<!-- 注意:${project.basedir} 是當前模塊的根目錄,需要把依賴包,放對位置 -->
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
                <executions>
                    <execution>
                        <id>install-external</id>
                        <phase>clean</phase>
                        <configuration>
                            <file>${project.basedir}/lib/flume-hdfs-sink-${flume.version}.jar</file>
                            <repositoryLayout>default</repositoryLayout>
                            <groupId>org.apache.flume.flume-ng-sinks</groupId>
                            <artifactId>flume-hdfs-sink</artifactId>
                            <version>${flume.version}</version>
                            <packaging>jar</packaging>
                            <generatePom>true</generatePom>
                        </configuration>
                        <goals>
                            <goal>install-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

控制 Scope 范圍

# compile(編譯范圍)
 compile 范圍是默認的。編譯范圍依賴在所有的 classpath 中可用,同時它們也會被打包

# provided(已提供范圍)
 provided 范圍只有在當 JDK 或者一個容器已提供該依賴之后才使用。它們不是傳遞性的,也不會被打包。適用於在實現了公共 common 模塊,其中有很多依賴,但是只有在其他依賴了 common 模塊的子模塊中,重新聲明依賴,才會真正被打包到子模塊中。這樣,既可以保證 common 模塊的正常編譯,又可以減少子模塊中的依賴包大小

# runtime(運行時范圍)
 runtime 范圍在運行和測試系統的時候需要,但在編譯的時候不需要。例如,在編譯的時候,如果只需要 JDBC API Jar,但只有在運行的時候才需要 JDBC 驅動的具體實現

# test(測試范圍)
 test 范圍在一般的編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。常用於 JUnit 的依賴

# system(系統范圍)
 system 范圍與 provided 類似,但是必須顯式的提供一個對於本地系統中 Jar 文件的路徑。這么做是為了允許基於本地對象編譯(systemPath),而這些對象是系統類庫的一部分。這樣的構件應該是一直可用的,Maven 也不會在倉庫中去尋找它(不推薦使用)

引入某一個本身依賴樹很龐大的 Dependency

# 依賴列表
$ mvn dependency:list

# 依賴樹(這里推薦直接用 Intellij Idea 中自帶的 "Show Dependencies" 功能,可視化地展示依賴樹 和 對應依賴沖突,並能夠直接對 依賴樹進行修剪)
$ mvn dependency:tree

# 依賴分析
$ mvn dependency:analyze
  Unused declared dependencies  表示項目中未使用的,但顯示聲明的依賴
  Used undeclared dependencies  表示項目中使用到的,但是沒有顯示聲明的依賴

Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError.
解決:

<spark.scala.version>2.11</spark.scala.version>
<apache.kafka.version>0.9.0.1</apache.kafka.version>

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka_${spark.scala.version}</artifactId>
    <version>${apache.kafka.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

原本文鏈接: https://yuzhouwan.com/posts/2254/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM