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 国内镜像

可以大大提高编译下载速度


  alimaven
  aliyun maven
  http://maven.aliyun.com/nexus/content/groups/public/
  central

指定 Repository 目录


D:\apps\maven\repository

如何使用 Maven 编译指定 module

$ mvn install -pl  -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


  org.codehaus.mojo
  build-helper-maven-plugin
  
    
      generate-sources
      
        add-source
      
      
        
          src/main/scala
        
      
    
  

Using Scala UnitTest by Maven

安装 Scala

Maven 依赖


  org.scalatest
  scalatest_2.10
  2.2.1

创建 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 配置

1.7.12
1.1.3


  ch.qos.logback
  logback-core
  ${logback.version}



  ch.qos.logback
  logback-classic
  ${logback.version}
  
    
      ch.qos.logback
      logback-core
    
    
      org.slf4j
      slf4j-api
    
  



  org.slf4j
  slf4j-api
  ${slf4j.version}



  org.slf4j
  jcl-over-slf4j
  ${slf4j.version}
  
    
      org.slf4j
      slf4j-api
    
  



  org.slf4j
  log4j-over-slf4j
  ${slf4j.version}
  
    
      org.slf4j
      slf4j-api
    
  



  org.slf4j
  jul-to-slf4j
  ${slf4j.version}
  
    
      org.slf4j
      slf4j-api
    
  

logback.xml in resources directory



  
  

  
  
    
    ${pattern}
    
  

  
    
  

编码

示例
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]
解决


  org.apache.curator
  curator-recipes
  ${apache.curator.version}
  
    
      org.slf4j
      slf4j-log4j12
    
  

导出依赖 Jar


  
    
    org.apache.maven.plugins
    maven-dependency-plugin
    2.10
    
      ${project.build.directory}/lib
      false
      false
    
    
  
$ 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

  
    

    
      socks-proxy
      true
      socks5
      127.0.0.1
      1080
      *.yuzhouwan.com
    
  

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 类


  1.7.7



  
  
    org.apache.avro
    avro
    ${apache.avro.version}
  



  
    
      org.apache.avro
      avro-maven-plugin
      ${apache.avro.version}
      
        
          generate-sources
          
            schema
          
          
            ${project.basedir}/src/main/resources/avsc/
            ${project.basedir}/src/main/java/
          
        
      
    
  

Shade 插件解决 Jar 多版本共存

适用场景

在整合大型项目时,可能都依赖 commons-collections 此类的工具包,但是也可能 commons-collections 的版本却因为不一致,导致冲突。可以通过 Shade 插件的 relocation 方法进行重定向,此时冲突的依赖 package 名,会被重命名,并且依赖该 jar 的程序,都会被自动替换为新的 package 名

基本用法

实例一


    2.4.3


    org.apache.maven.plugins
    maven-shade-plugin
    2.4.3
    
        
            package
            
                shade
            
            
                false
                true
                
                    
                        org.mapdb.*
                    
                
                
                    
                        org.apache.commons.collections
                        com.yuzhouwan.org.apache.commons.collections
                    
                
            
        
    

实例二


    org.apache.maven.plugins
    maven-shade-plugin
    ${maven.shade.plugin.version}
    
        
            package
            
                shade
            
            
                true
                all
                true
                
                    
                    
                    
                        org.glassfish.*
                    
                
                
                    
                        javax.ws
                        shade.javax.ws
                    
                    
                        org.apache.curator
                        shade.org.apache.curator
                    
                    
                
            
        
    

通过 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 文件


    2.3


pom


    
        com.yuzhouwan
        core
    
    
        com.yuzhouwan
        ai
    
    
        com.yuzhouwan
        bigdata
    



    
        
            maven-assembly-plugin
            ${maven.assembly.plugin.version}
            
                
                    assemble
                    package
                    
                        single
                    
                    
                        
                            src/assembly/bin.xml
                            src/assembly/src.xml
                        
                        gnu
                    
                
            
        
    

第二步,创建好对应的 bin.xml 和 src.xml



    bin

    
        dir
        tar.gz
    

    yuzhouwan-${project.version}-bin

    
        
            ../

            
                **/target/**
                **/.classpath
                **/.project
                **/.settings/**
                lib/**
                conf/**
            

            
                README
                LICENSE
                NOTICE
                CHANGELOG
                RELEASE-NOTES
                conf/
            
        

        
            ../
            
                bin/yuzhouwan-cli.sh
            
            0777
            0755
        
    

    
        
            false
            true
            
                com.yuzhouwan:yuzhouwan-core
            
            
                com.yuzhouwan:ai
                com.yuzhouwan:bigdata
            
            
                lib/core
                false
                
                    
                        false
                        true
                        false
                        
                            com.yuzhouwan:ai
                            com.yuzhouwan:bigdata
                        
                    
                
            
        

        
            false
            true
            
                com.yuzhouwan:ai
            
            
                com.yuzhouwan:bigdata
            
            
                lib/plugins/ai
                false
                
                    
                        false
                        true
                        false
                        
                            com.yuzhouwan:bigdata
                        
                    
                
            
        

        
            false
            true
            
                com.yuzhouwan:bigdata
            
            
                com.yuzhouwan:ai
            
            
                lib/plugins/bigdata
                false
                
                    
                        false
                        true
                        false
                        
                            com.yuzhouwan:ai
                        
                    
                
            
        
    


    src

    
        dir
        tar.gz
    

    yuzhouwan-${project.version}-src

    
        
            ../

            
                **/target/**
                **/.classpath
                **/.project
                **/*.iml
                **/.settings/**
                lib/**
            

            
                .ci
                .gitignore
                DEVNOTES
                README
                LICENSE
                NOTICE
                CHANGELOG
                RELEASE-NOTES
                bin/**
                conf/**
                native/**
                pom.xml
                dev-conf/**
                yuzhouwan-core/**
                yuzhouwan-ai/**
                yuzhouwan-bigdata/**
            
        
    


构建完成之后,即可看到 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:


  
    clojars.org
    http://clojars.org/repo
  

本地缓存

Maven 中出现 Repository 被缓存在本地,则可以添加下面属性


  clojars.org
  http://clojars.org/repo
  
    true
    always
  
  
    true
    always
  

编译问题

JDK 版本不一致

描述:

Error:java: Compilation failed: internal java compiler error

解决:


  elastic-netflow-v5

  
    
      org.apache.maven.plugins
      maven-compiler-plugin
      2.3.2
      
        1.7
        1.7
      
    

    
      org.apache.maven.plugins
      maven-release-plugin
      2.4.1
    
  

Scala 版本不一致

描述:

[ERROR] error: error while loading , 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 模块)的 1.0 中的具体版本号(如 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?

解决


  org.apache.maven.plugins
  maven-surefire-plugin
  ${maven-surefire.version}
  
    
    -Xmx2048m -Xms1024m -XX:MaxPermSize=512m -XX:-UseGCOverheadLimit
    always
  

Assembly 插件报错 java.lang.StackOverflowError

解决:

# 调大默认的堆栈大小
export MAVEN_OPTS=-Xss2m

补充:

-Xms:jvm 进程启动时分配的内存
-Xmx:jvm 进程运行过程中最大能分配到的内存
-Xss:jvm 进程中启动线程,为每个线程分配的内存大小

依赖问题

Maven 中央仓库找不到对应版本的依赖
如何将其他项目的 jar 安装到 maven 仓库中
1,利用命令安装

$ mvn install:install-file -Dfile= -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,利用插件安装



    
        
            
                org.apache.maven.plugins
                maven-install-plugin
                2.5.2
                
                    
                        install-external
                        clean
                        
                            ${project.basedir}/lib/flume-hdfs-sink-${flume.version}.jar
                            default
                            org.apache.flume.flume-ng-sinks
                            flume-hdfs-sink
                            ${flume.version}
                            jar
                            true
                        
                        
                            install-file
                        
                    
                
            
        
    

控制 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.
解决:

2.11
0.9.0.1


    org.apache.kafka
    kafka_${spark.scala.version}
    ${apache.kafka.version}
    
        
            org.slf4j
            slf4j-log4j12
        
        
            log4j
            log4j
        
    

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

转载于:https://www.cnblogs.com/hit-zb/p/10884457.html

你可能感兴趣的:(maven 高级玩法)