實用技巧
Maven 提速
多線程
# 用 4 個線程構建变秦,以及根據(jù) CPU 核數(shù)每個核分配 1 個線程進行構建
$ mvn -T 4 clean install
$ mvn -T 1C clean install
跳過測試
-DskipTests # 不執(zhí)行測試用例氓仲,但編譯測試用例類生成相應的 class 文件至 target/test-classes 下
-Dmaven.test.skip=true # 不執(zhí)行測試用例躏嚎,也不編譯測試用例類
# 結合上文的`并行執(zhí)行`
$ 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 之類帶有幾十個子項目的工程,如果從頭編譯所有的模塊瞭吃,會很耗功夫
# 通過指定之前失敗的模塊名碌嘀,可以繼續(xù)之前的編譯
$ mvn -rf :moduleName clean install
跳過失敗的模塊,編譯到最后再報錯
$ mvn clean install --fail-at-end
使用 Nexus 本地私服
可參考 Maven 學習(四):使用 Nexus 搭建 Maven 私服
使用 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>
創(chuàng)建 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)
}
}
Tips: Full code is here.
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歪架,否則會出現(xiàn)問題 -->
<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>
Tips: Full code is here.
導出依賴 Jar
如何利用 Maven 將依賴的 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
Tips: Full code is here.
日志級別
-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
Maven Dependency
Pre-download
$ mvn dependency:go-offline
Version-compare
# 在開發(fā)一些 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"
配置文件
$ vim $MAVEN_HOME/conf/settings.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 插件
創(chuàng)建 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>
Tips: Full code is here.
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>
踩過的坑
Error creating shaded jar: Error in ASM processing class
描述
Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:2.1:shade (default) on project base-k2d-flow: Error creating shaded jar: Error in ASM processing class com/yuzhouwan/bigdata/k2d/K2DPartitioner.class: 52264 -> [Help 1]
解決
升級 maven-shade-plugin
版本到 2.4.x
通過 Shade 將問題解決后塔淤,部署上線后,依賴沖突復現(xiàn)
解決
因為官方明確指出 java.io.File.listFiles()
方法返回的文件序列順序矫付,是不做保證的凯沪。所以,上線后運行環(huán)境發(fā)生變化买优,加載 lib
目錄下的 jar 包
順序妨马,可能會發(fā)生變化。這時候杀赢,就需要利用不同 lib
目錄烘跺,并修改 classpath 的方式,將 jar 包
加載順序確定下來
例如脂崔,在整合 Druid 這類依賴樹比較龐大的工程滤淳,就遇到了這么一種情況。Druid 中 com.sun.jersey (1.19) 和 Dataflow 中 org.glassfish.jersey (2.25.1) 發(fā)生沖突砌左。增加了上述實例二中的 Shade 操作仍然會在線上環(huán)境脖咐,復現(xiàn)依賴沖突铺敌。這時,我們可以通過增加一個 lib_jersey
目錄屁擅,存放 javax.ws.rs-api-2.1.jar
偿凭,并修改 classpath 為 lib_jersey/*:lib/*
。以此派歌,保證了 lib_jersey
中的依賴得以優(yōu)先加載弯囊,從而解決沖突
參考
Assembly 插件
不同模塊的依賴,打包到不同的目錄下
具體步驟
第一步胶果,先在負責打包分發(fā)的 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>
第二步,創(chuàng)建好對應的 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 包羊赵,將只能保留其中一個版本趟佃,且具體保留哪個版本是不確定的
參考
- Apache Maven Doc
- Maven: The Complete Reference
- 《Maven 權威指南》12.5.5.4 字節(jié)碼選擇
- 通過開發(fā)插件了解 Maven
常見問題
如何使用其他語言編譯出來的 Jar
Clojar
如果需要在 Maven 中,添加新的 Repository昧捷,這里以 Clojar 為例闲昭,配置如下:
<repositories>
<repository>
<id>clojars.org</id>
<url>http://clojars.org/repo</url>
</repository>
</repositories>
本地緩存
Maven 中出現(xiàn) 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>
下載問題
已 download序矩,未 import
如果發(fā)現(xiàn) pom.xml
中的 依賴雖然在 .m2
中被下載了,但是沒有被 import
到項目中
嘗試在 Intellij Idea 的 setting 中 找到 Maven -> Ignored Files
跋破,看看對應的 pom.xml
有沒有被勾選
<div class="note info">如果仍然無法解決簸淀,也有可能是 Intellij Idea 自身的問題,可嘗試通過 Just Restart 來解決</div>
編譯問題
JDK 版本不一致
描述
Error:java: Compilation failed: internal java compiler error
解決
調整 compiler 的級別毒返,并在 pom.xml
中添加 build 標簽租幕,規(guī)定 compiler 的級別
<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 (offline)
$ 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
之前需要先執(zhí)行 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 參數(shù)以調整 JVM -->
<argLine>-Xmx2048m -Xms1024m -XX:MaxPermSize=512m -XX:-UseGCOverheadLimit</argLine>
<forkMode>always</forkMode>
</configuration>
</plugin>
詳見:Eagle-RP-897
Fatal error compiling: 無效的目標發(fā)行版: 1.8
需要在 IDE 的 Project Structure(Ctrl+Alt+Shift+S)
里設置 Project JDK
為 jdk1.8
贾富,并在 Settings(Ctrl+Alt+S)
里設置 Java Compiler
的 bytecode version
為 1.8
Assembly 插件報錯 java.lang.StackOverflowError
解決
# 調大默認的堆棧大小
export MAVEN_OPTS=-Xss2m
補充
-Xms:jvm 進程啟動時分配的內存
-Xmx:jvm 進程運行過程中最大能分配到的內存
-Xss:jvm 進程中啟動線程歉眷,為每個線程分配的內存大小
依賴問題
Maven 中央倉庫找不到對應版本的依賴
如何將其他項目的 jar 安裝到 maven 倉庫中
利用命令安裝
$ 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 的方式導入
利用插件安裝
<!-- 注意:${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 或者一個容器已提供該依賴之后才使用霍骄。它們不是傳遞性的,也不會被打包淡溯。適用于在實現(xiàn)了公共 common 模塊读整,其中有很多依賴,但是只有在其他依賴了 common 模塊的子模塊中咱娶,重新聲明依賴米间,才會真正被打包到子模塊中。這樣膘侮,既可以保證 common 模塊的正常編譯屈糊,又可以減少子模塊中的依賴包大小
# runtime(運行時范圍)
runtime 范圍在運行和測試系統(tǒng)的時候需要,但在編譯的時候不需要琼了。例如逻锐,在編譯的時候,如果只需要 JDBC API Jar雕薪,但只有在運行的時候才需要 JDBC 驅動的具體實現(xiàn)
# test(測試范圍)
test 范圍在一般的編譯和運行時都不需要昧诱,它們只有在測試編譯和測試運行階段可用。常用于 JUnit 的依賴
# system(系統(tǒng)范圍)
system 范圍與 provided 類似所袁,但是必須顯式的提供一個對于本地系統(tǒng)中 Jar 文件的路徑盏档。這么做是為了允許基于本地對象編譯(systemPath),而這些對象是系統(tǒng)類庫的一部分燥爷。這樣的構件應該是一直可用的蜈亩,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>