实际项目过程中,我们的工程往往是多个模块组合在一起,甚至相互之间也会有依赖关系,如何管理好这些依赖是一个很重要的技能。
举个简单的场景,web工程mavenWeb与java工程mavenJava都属于一个项目里的模块,而且mavenWeb依赖于mavenJava,通常,我们会建立一个父pom来管理这样的工程。
---------------------------->
绝大多数时候我都会直接用eclipse插件所提供的快速建maven工程来选择新建web或者java,但命令还是很重要的。创建过程中遇到了问题:
mvn archetype:create -DgroupId=com.changjiang.test -DartifactId=mavenJava -DpackageName=com.changjiang.test
但出现报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.4:create (default-cli) on project standalone-pom: Unable to pars e configuration of mojo org.apache.maven.plugins:maven-archetype-plugin:2.4:create for parameter #: Abstract class or interface 'org.apache.maven .artifact.repository.ArtifactRepository' cannot be instantiated -> [Help 1]
参照了网上的解决方案:
* JAVA_HOME没有设置或者设置有误、m2_home设置有误 * 删除/org/apache/maven/plugins/下的maven-archetype-plugin * archetype:create命令已经过期,需要使用 archetype:generate 来进行代替(方案可行) * maven-archetype-plugin 2.3版本的插件有问题,换其它版本进行创建(方案可行)
于是改用generate替代create(maven版本3.0.5),命令行交互mode出现,选择一些基本信息后,创建成功:
mvn archetype:generate -DgroupId=com.changjiang.test -DartifactId=mavenJava -DpackageName=com.changjiang.test
---------------------------->
接着用命令创建一个mavenWeb工程:
mvn archetype:generate -DgroupId=com.changjiang.web -DartifactId=mavenWeb -DpackageName=com.changjiang.web -DarchetypeArtifactId=maven-archetype-webapp
其过程与mavenJava类似;
---------------------------->
接下来,我们将工程修改符合eclipse要求的结构:
mvn eclipse:eclipse
=====================================
mvn eclipse:eclipse -DwtpVersion=2.0
导入eclipse。结构如下:
---------------------------->
如果我们不用一个父pom来管理这两个模块,那么当mavenWeb需要依赖mavenJava时,就必须在打包多次,如果有多个模块,这个操作就会非常复杂。这里引入pom对这两个模块进行管理。
... <packaging>pom</packaging> <properties> <version>1.0</version> </properties> <modules> <module>mavenWeb</module> <module>mavenJava</module> </modules> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
子项目里:
... <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.changjiang.maven</groupId> <artifactId>mavenParent</artifactId> <version>1.0</version> </parent> ...
这样,只要在mavenParent中进行mvn install的操作,它就会对所有的模块进行自动打包处理。
除了子模块的统一入口,父pom另一个作用就是依赖的遗传,设置统一的<dependency/>并在<properties/>中标注版本,即可统一管理所有的公共依赖和它们的版本。
... <module>CHiQ3-web</module> <module>CHiQ3-rest</module> </modules> <properties> <javax.ws.rs-api.version>2.0</javax.ws.rs-api.version> <resteasy-client.version>3.0.16.Final</resteasy-client.version> <dubbo.version>2.8.4</dubbo.version> <commons-logging.version>1.2</commons-logging.version> <slf4j-log4j12.version>1.7.7</slf4j-log4j12.version> <junit.version>4.11</junit.version> <mockito.version>1.9.5</mockito.version> <fastjson.version>1.2.7</fastjson.version> <mongodb.version>3.2.0</mongodb.version> <spring.version>4.2.4.RELEASE</spring.version> <spring-dao.version>2.0.8</spring-dao.version> <spring-data-mongo.version>1.8.2.RELEASE</spring-data-mongo.version> <druid.version>1.0.14</druid.version> <zookeeper.version>3.4.6</zookeeper.version> <zkclient.version>0.5</zkclient.version> <aspect.version>1.8.7</aspect.version> <javassist.version>3.20.0-GA</javassist.version> <mysql.version>5.1.38</mysql.version> <httpclient.version>4.5.1</httpclient.version> <commons-collections.version>3.2.1</commons-collections.version> <jackson-annotations.version>2.6.3</jackson-annotations.version> <!-- Plugin的属性定义 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <jdk.version>1.7</jdk.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <javax.servlet-api.version>3.1-b08</javax.servlet-api.version> </properties> <dependencies> <!-- restful api --> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>${javax.ws.rs-api.version}</version> </dependency> <!-- 嵌入式容器 --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> ...
子pom中也可以像在父pom中确定依赖的版本。
如果各个子模块之间也有依赖关系,比如我们提到的这个场景,mavenWeb依赖于mavenJava,那么也可以在父pom中用<dependencyManagement/>进行管理。
需要特别注意的是,父pom中所定义的各种参数,子pom可以用${}来引用,但是<parent/>里面不能用通配符。
---------------------------->
当然,父pom中的<plugin/>也是会被继承的。相对的,也会有<pluginManagement/>可以保证子pom中所有的版本,配置一致。
另外,对于maven依赖冲突时,maven有自己的规则来进行排序,比如同级的相同依赖,按在pom中出现的先后排序;不同级的依赖,就近原则。
如果在继承的过程中,发现有依赖中部分的依赖不想被继承,就要用到<exclusions/>:
... <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.1.0.Final</version> <exclusions> <exclusion> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
---------------------------->
在添加诸如spring等的依赖时,往往会用到一些依赖所依赖的jar包,这个时候最好能够将已经引用到,但是没有放到pom中的依赖放到pom中去。可以用mvn dependency:resolve来查询已经依赖的jar包和文件:
E:\Users\BruceChan\workspace\dev01\mavenParent>mvn dependency:resolve [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] mavenParent [INFO] mavenJava [INFO] mavenWeb Maven Webapp [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenParent 1.0 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.1:resolve (default-cli) @ mavenParent --- [INFO] [INFO] The following files have been resolved: [INFO] antlr:antlr:jar:2.7.7:compile [INFO] com.fasterxml:classmate:jar:1.3.0:compile [INFO] dom4j:dom4j:jar:1.6.1:compile [INFO] junit:junit:jar:4.11:test [INFO] org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile [INFO] org.hamcrest:hamcrest-core:jar:1.3:test [INFO] org.hibernate:hibernate-core:jar:5.1.0.Final:compile [INFO] org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile [INFO] org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile [INFO] org.javassist:javassist:jar:3.20.0-GA:compile [INFO] org.jboss:jandex:jar:2.0.0.Final:compile [INFO] org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile [INFO] xml-apis:xml-apis:jar:1.0.b2:compile [INFO] [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenJava 1.0 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.1:resolve (default-cli) @ mavenJava --- [INFO] [INFO] The following files have been resolved: [INFO] antlr:antlr:jar:2.7.7:compile [INFO] com.fasterxml:classmate:jar:1.3.0:compile [INFO] dom4j:dom4j:jar:1.6.1:compile [INFO] junit:junit:jar:4.11:test [INFO] org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile [INFO] org.hamcrest:hamcrest-core:jar:1.3:test [INFO] org.hibernate:hibernate-core:jar:5.1.0.Final:compile [INFO] org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile [INFO] org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile [INFO] org.javassist:javassist:jar:3.20.0-GA:compile [INFO] org.jboss:jandex:jar:2.0.0.Final:compile [INFO] org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile [INFO] xml-apis:xml-apis:jar:1.0.b2:compile [INFO] [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenWeb Maven Webapp 1.0 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.1:resolve (default-cli) @ mavenWeb --- [INFO] [INFO] The following files have been resolved: [INFO] antlr:antlr:jar:2.7.7:compile [INFO] com.changjiang.test:mavenJava:jar:1.0:compile [INFO] com.fasterxml:classmate:jar:1.3.0:compile [INFO] dom4j:dom4j:jar:1.6.1:compile [INFO] javax.servlet:javax.servlet-api:jar:3.1.0:provided [INFO] junit:junit:jar:4.11:test [INFO] org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile [INFO] org.hamcrest:hamcrest-core:jar:1.3:test [INFO] org.hibernate:hibernate-core:jar:5.1.0.Final:compile [INFO] org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile [INFO] org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile [INFO] org.javassist:javassist:jar:3.20.0-GA:compile [INFO] org.jboss:jandex:jar:2.0.0.Final:compile [INFO] org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile [INFO] xml-apis:xml-apis:jar:1.0.b2:compile [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] mavenParent ....................................... SUCCESS [1.148s] [INFO] mavenJava ......................................... SUCCESS [0.216s] [INFO] mavenWeb Maven Webapp ............................. SUCCESS [0.220s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.210s [INFO] Finished at: Thu Aug 25 15:18:28 CST 2016 [INFO] Final Memory: 9M/244M [INFO] ------------------------------------------------------------------------
---------------------------->
对于平时用到比较多的依赖,可以整理一个专门的pom来存放这些依赖,在使用的时候,直接引用这个pom就可以了。
<dependency> <groupId>com.xxx</groupId> <artifactId>xxx</artifactId> <version>xxx</version> <type>pom</type> </dependency>
不过采用这种方式存在依赖性的问题。
这种依赖性的问题,总体来说就是有共享的信息,多用依赖,没有共享的信息,就用多模块处理。