`

一个多maven项目聚合的实例

阅读更多
本文介绍一个多maven项目的实例demo,展示了聚合、继承、工程依赖、单元测试、多war聚合、cargo发布等场景

一、工程介绍

该项目由5个maven项目组成



task-aggregator是父工程,同时承担聚合模块和父模块的作用,没有实际代码和资源文件
task-common是基础工程,里面是公共的代码
task-sla是某一个业务子模块,不包含web内容
task-sla-web是某一个web子模块
task-web-dist是最外围的web工程,聚合多个web工程,形成最终的war包

依赖关系是:task-common <-- task-sla <-- task-sla-web <-- task-web-dist

二、task-aggregator



这个工程是起到聚合作用,并充当parent pom,所以没有任何实际代码和资源文件。我这里选择了平行结构,另外一种方式是树形结构,我个人感觉平行结构看起来更舒服一点

下面是pom,有所简化:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

	<!-- 定义公共变量 -->
	<properties>
		<spring.version>3.1.0.RELEASE</spring.version>
		<struts2.version>2.3.1</struts2.version>
		<hibernate.version>3.2.7.ga</hibernate.version>
	</properties>

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.xxx.task</groupId>
	<artifactId>task-aggregator</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

        <!-- 待聚合模块 -->
	<modules>
		<module>../task-common</module>
		<module>../task-sla</module>
		<module>../task-sla-web</module>
		<module>../task-web-dist</module>
	</modules>

	<!-- 配置部署的远程仓库 -->
	<distributionManagement>
		<snapshotRepository>
			<id>nexus-snapshots</id>
			<name>nexus distribution snapshot repository</name>
			<url>http://10.78.68.122:9090/nexus-2.1.1/content/repositories/snapshots/</url>
		</snapshotRepository>
	</distributionManagement>

	<build>

		<pluginManagement>
			<plugins>

				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-resources-plugin</artifactId>
					<version>2.6</version>
					<configuration>
						<encoding>UTF-8</encoding>
					</configuration>
				</plugin>

				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.5.1</version>
					<configuration>
						<encoding>UTF-8</encoding>
					</configuration>
				</plugin>

			</plugins>
		</pluginManagement>

	</build>

	<dependencyManagement>

		<dependencies>

			<dependency>
				<groupId>com.sun</groupId>
				<artifactId>tools</artifactId>
				<version>1.6.0</version>
				<scope>system</scope>
				<systemPath>${env.JAVA_HOME}/lib/tools.jar</systemPath>
			</dependency>

		</dependencies>

	</dependencyManagement>

</project>

基本上是一目了然,只是有几点注意下:

    1、这里配置了<distributionManagement>,这样子项目就不需要重复配置了

    2、通过<pluginManagement>,对一些插件进行了公共的配置,这里主要是为了消除构建时的告警

    3、配置tools,是因为实际中发现,其他开发人员从svn上check out工程以后,有的人会报错,找不到tools.jar,这样配置以后就好了

三、task-common

该工程是公共工程,提供了项目中的公共代码,这里只包括了通用的DAO组件,作为示例。

该工程不依赖任何其他工程



该工程里有几点要点:

    1、在代码内部用了Spring的注解
public abstract class GenericDAO<T> implements IGenericDAO<T> {

	private Class<T> entityClass;

	public GenericDAO(Class<T> clazz) {
		this.entityClass = clazz;
	}

	@Autowired
	private HibernateTemplate hibernateTemplate;

}

这里用到了@Autowired注解,所以最终形成的war包,必须在spring配置文件中声明HibernateTemplate类型的bean,否则会报错

我这里用的maven环境是maven3.0.4,这个版本打出的jar包,带有Directory Entries信息,所以spring的注解即使在jar包中也可生效,如果是比较老的版本,spring的注解在jar包中不好用,关于这个问题的详细描述,见另外一篇博客:http://kyfxbl.iteye.com/blog/1675368

    2、单元测试的写法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-test.xml")
@Transactional
public class GenericDAOTest {

	@Autowired
	private IBookDAO bookDAO;

	@Test
	public void testInsert() {
		Book book = new Book();
		book.setName("thinking in java");
		book.setIsbn("111");
		bookDAO.insert(book);
	}

}

这里用到了几个注解,@RunWith是为了在spring容器环境下跑这个单元测试类,以支持依赖注入。@ContextConfiguration是声明spring配置文件的位置。@Transactional注解之后,在单元测试方法中的事务会自动回滚,这个比较方便,这样在前面执行的方法,不会对后面的方法造成影响

这个单元测试类,可以直接在maven里跑起来,让我比较惊喜。之前这样写,在ant里跑没有成功,可能是我没有找到合适的插件的原因

    3、除了测试的java代码之外,还有3个资源文件,都是放在src/test/resources下,这些资源文件只在test阶段生效,package阶段不会被打包,也就是专门供测试阶段使用

这个各有利弊,优点是测试的配置文件与开发的配置文件隔离,互不干扰。缺点是配置文件似乎缺少了集中放置的地点,这样如果多个maven工程都需要跑单元测试,要共享测试用配置文件,比较麻烦一点

不过从我个人来看,也算是利大于弊。只是在每个maven项目下,都需要独立的测试相关资源文件,其实也有利于分别修改

另外,可以看到这里的hibernate映射文件,不是和model类放在一个package下,而是放在resources目录下的,这样做可以避免一些潜在的问题,也有利于后续的聚合

    4、pom文件没有什么特别的,只是要引入<scope>为test的junit和spring-test

四、task-sla

该工程依赖task-common(因为用到了GenericDAO),是某一个业务模块的逻辑部分,包含了数据库访问层和业务逻辑层,但是不包括web相关的部分



这里没有什么特别要注意的,目录结构和task-common基本一样。比较特别的是可以看到Maven Dependencies里,有一个task-common工程,所以task-common里的任何修改,都可以第一时间在这个工程里体现出来,是比较方便的

关于这个问题,见另外一篇博客:http://kyfxbl.iteye.com/blog/1679806

另外就是前面说过的,hibernate的映射文件,应该放在src/main/resources下,而不是与Model类放在一起

五、task-sla-web

这个工程是上述task-sla工程的web层,依赖于task-sla,由于task-sla又依赖task-common,所以这个工程最终会同时依赖task-common和task-sla



然后这个工程里包含了web层的东西,包括Action类、jsp、图片、struts2的配置文件等,这些东西放在web工程里是最合适的



这里需要注意2点:

    1、这个工程的packaging类型是war,而不是jar。但是最终它不会独立打出war包来,其src/main/webapp里的所有文件,都会被最外围的task-web-dist工程聚合成一个总的war

    2、这个工程的WEB-INF目录下,没有web.xml(有也没用,最终会被覆盖)。默认情况下,packaging类型为war的项目,如果没有web.xml,则构建会失败,因此需要在pom里做一个配置

该项目的pom如下,省略了依赖部分:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<parent>
		<groupId>com.xxx.task</groupId>
		<artifactId>task-aggregator</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>../task-aggregator</relativePath>
	</parent>

	<modelVersion>4.0.0</modelVersion>
	<artifactId>task-sla-web</artifactId>
	<packaging>war</packaging>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<!-- 配置依赖 -->
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
		</dependency>

	</dependencies>

</project>

上面的<failOnMissingWebXml>,就是配置缺少web.xml也不使构建失败

六、task-web-dist

这个工程是最外围的web工程,起到聚合的作用,即把所有的web项目,打成最终的war包。同时,在这个工程里,放置里公共的配置文件,比如struts.xml、ssoconfig.properties等



这个工程的聚合意图十分明显,比如struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

	<constant name="struts.objectFactory" value="spring" />
	<constant name="struts.ui.theme" value="simple" />
	<constant name="struts.i18n.encoding" value="UTF-8" />
	<constant name="struts.action.extension" value="action" />
	<constant name="struts.enable.DynamicMethodInvocation" value="false" />
	<constant name="struts.devMode" value="true" />

	<include file="struts2/struts-sla.xml" />

</struts>

提供了项目通用的配置,并把各子项目的struts2配置文件聚合起来。war包中的web.xml也是在这里提供的

下面是该工程的pom,也省略了依赖的配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<parent>
		<groupId>com.xxx.task</groupId>
		<artifactId>task-aggregator</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>../task-aggregator</relativePath>
	</parent>

	<modelVersion>4.0.0</modelVersion>
	<artifactId>task-web-dist</artifactId>
	<packaging>war</packaging>

	<build>

		<finalName>task</finalName>

		<plugins>

			<!-- 合并多个war -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<packagingExcludes>WEB-INF/web.xml</packagingExcludes>  
					<overlays>
						<overlay>
							<groupId>com.huawei.inoc.wfm.task</groupId>
							<artifactId>task-sla-web</artifactId>
						</overlay>
					</overlays>
				</configuration>
			</plugin>

			<!-- 利用cargo启动容器 -->
			<plugin>
				<groupId>org.codehaus.cargo</groupId>
				<artifactId>cargo-maven2-plugin</artifactId>
				<version>1.2.3</version>
				<configuration>
					<container>
						<containerId>tomcat7x</containerId>
						<home>D:\apache-tomcat-7.0.29</home>
					</container>
					<configuration>
						<type>standalone</type>
						<home>${project.build.directory}/tomcat7.0.29</home>
						<properties>
							<cargo.jvmargs>
								-Xdebug
								-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8787
        					</cargo.jvmargs>
						</properties>
					</configuration>
				</configuration>
				<executions>
					<execution>
						<id>cargo-run</id>
						<phase>pre-integration-test</phase>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

		</plugins>

	</build>

</project>

这里主要是对maven-war-plugin和cargo-maven2-plugin这2个插件进行了配置,以起到聚合war,以及通过cargo启动容器的作用

关于多war聚合,以及cargo,见另外2篇博客:http://kyfxbl.iteye.com/blog/1678121、http://kyfxbl.iteye.com/blog/1677608

七、启动构建

在task-aggregator目录下,执行mvn clean deploy或者mvn clean install,就可启动整个构建过程,并将容器启动起来,跑最终生成的war包

  • 大小: 5.6 KB
  • 大小: 7.5 KB
  • 大小: 84.6 KB
  • 大小: 21.2 KB
  • 大小: 12.8 KB
  • 大小: 33.5 KB
  • 大小: 69.9 KB
  • 大小: 22.5 KB
分享到:
评论
38 楼 GGGGeek 2017-11-22  
受益匪浅,从组织项目结构,到技术细节,讲的很到位,只是博主不再更博了,有点可惜了
37 楼 smartdog 2017-02-06  
不错,值得借鉴
36 楼 六年虚度 2016-06-08  
你好 ,请教一下 为什么我 项目搭建完成 修改完JS和jsp文件后 必须要 手动重新编译一下?
35 楼 u014087707 2016-02-25  
task_sla下面有service层,现在你在task_web_dist这一层有一个spring-config.xml我用注解的话怎么拦截task_sla的service层的类,<context:component-scan  base-package="com.xxx.task.task_sla.service.*" />,所以我的task_web_dist要依赖task_sla这个哟,要配置依赖呀,  <dependency>
            <groupId>com.xxx.task</groupId>
            <artifactId>task-sla</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

那为啥还一直找不到这个路径呢 ,求指点,怎么配置扫描呢该
34 楼 kyfxbl 2016-02-07  
yuyining_1 写道
关于业务子模块划分的问题,有个问题请教下,如果不同的模块间的entity相互依赖,那么是不是应该划分为同一个模块?还是放在common模块中


如果合在一起比较合适,就合在一起,否则建议放在common里

放在common里还一个好处,以后如果你发布一些jar包给别人用,一般也是需要带Entity的,可以一起打成jar包发出去
33 楼 yuyining_1 2016-01-29  
关于业务子模块划分的问题,有个问题请教下,如果不同的模块间的entity相互依赖,那么是不是应该划分为同一个模块?还是放在common模块中
32 楼 qwe857359351 2015-08-26  
kyfxbl 写道
qwe857359351 写道
博主你好,我现在整合了两个web,打成一个war,我到war文件里的classes里看了,两个web的类已经合并到一起了,但是放到tomcat只是解压了,启动后访问也是404,Spring和web.xml配置文件没问题,链接也没错,能帮我解答一下吗,谢谢!


你好。404的话,说明tomcat已经起来了,但是web资源没找到。你这样说我也不好判断,请你检查一下WEB-INF先,或者尝试往根目录放一个a.html,看看直接访问是什么情况

谢谢您的回复,问题已经解决了,是我配置的问题
31 楼 kyfxbl 2015-08-24  
qwe857359351 写道
博主你好,我现在整合了两个web,打成一个war,我到war文件里的classes里看了,两个web的类已经合并到一起了,但是放到tomcat只是解压了,启动后访问也是404,Spring和web.xml配置文件没问题,链接也没错,能帮我解答一下吗,谢谢!


你好。404的话,说明tomcat已经起来了,但是web资源没找到。你这样说我也不好判断,请你检查一下WEB-INF先,或者尝试往根目录放一个a.html,看看直接访问是什么情况
30 楼 kyfxbl 2015-08-24  
zwfflying 写道
每个工程都有很多相同的第三方jar,比如spring的jar,怎么处理?
是每个工程都自己引入自己的,打包的时候只会有一份呢?还是可以大家都连接到某个位置?


放一个公共资源就可以了
29 楼 qwe857359351 2015-08-20  
博主你好,我现在整合了两个web,打成一个war,我到war文件里的classes里看了,两个web的类已经合并到一起了,但是放到tomcat只是解压了,启动后访问也是404,Spring和web.xml配置文件没问题,链接也没错,能帮我解答一下吗,谢谢!
27 楼 zwfflying 2015-07-17  
每个工程都有很多相同的第三方jar,比如spring的jar,怎么处理?
是每个工程都自己引入自己的,打包的时候只会有一份呢?还是可以大家都连接到某个位置?
26 楼 abc382410124 2014-12-31  
不错学习了 支持下
25 楼 kookob 2014-09-26  
1、这个工程的packaging类型是war,而不是jar。但是最终它不会独立打出war包来,其src/main/webapp里的所有文件,都会被最外围的task-web-dist工程聚合成一个总的war
==============================

那这个工程的webapp文件会被打在war包里面吗?其他工程怎么直接引用到它?
24 楼 lovko 2014-01-08  
lovko 写道
在分包的时候一直有个问题困扰我,每个模块有自己的jar包,包里有对应的entity使用的jpa标注,dist.war中统一配置的persistence.xml.但是他在进行持久类标注scan是只会扫描当前运行目录下class.除非通过jar-file指定引用的jar包或显式的指定class的列表。我现在用的jar-file的方式对物理目录和版本号依赖太强,测试和发布也不通一。想请教下如何处理这种独立的持久类的注解扫描的问题。感谢!!!!
附上一个其他朋友分享的方案,不过还是不太理想 www.iteye.com/topic/1131643
23 楼 lovko 2014-01-08  
在分包的时候一直有个问题困扰我,每个模块有自己的jar包,包里有对应的entity使用的jpa标注,dist.war中统一配置的persistence.xml.但是他在进行持久类标注scan是只会扫描当前运行目录下class.除非通过jar-file指定引用的jar包或显式的指定class的列表。我现在用的jar-file的方式对物理目录和版本号依赖太强,测试和发布也不通一。想请教下如何处理这种独立的持久类的注解扫描的问题。感谢!!!!
22 楼 kyfxbl 2013-12-04  
xieweijv 写道
哈哈,我知道什么公司的~lz,最后打包成war的plugin配置要改一下,暴露了


呵呵,前公司了
21 楼 xieweijv 2013-11-25  
哈哈,我知道什么公司的~lz,最后打包成war的plugin配置要改一下,暴露了
20 楼 Voitor 2013-10-30  
楼主,能问问 task-sla-web 这个你没有web.xml那是怎么测试的啊,或者怎么debug的
19 楼 niweiwei 2013-10-28  
能不能把每个工程的pom文件发出来,有的工程比如task-sla的packaging设置为什么形式等
谢谢

相关推荐

    maven聚合实例

    总结来说,"maven聚合实例"展示了如何利用Maven的聚合特性来管理多模块项目,以及如何在子项目之间进行依赖和接口调用。这样的实践使得大型项目变得有序且易于维护,同时充分利用了Maven的强大功能。

    maven聚合项目

    总结来说,这个"Maven聚合项目"是一个集成了聚合、继承、插件管理和私服使用的实例,展示了如何高效地管理和构建多模块的Java项目。通过这种方式,开发团队可以更有效地协同工作,保证项目的稳定性和一致性。

    java maven 聚合项目 分模块 socket 双向通信实例demo

    在Java开发中,Maven聚合项目(Aggregator Project)是一种管理多模块项目的方式,它允许开发者在一个父项目中集合并构建多个子项目。这样的结构有助于代码的组织和依赖管理,特别是当项目涉及到多个独立但相互关联...

    Maven项目对象模型(POM)

    Maven 项目对象模型 Maven搭建过程 web 模块加载另外一个web模块方法 Myeclipse Maven 忽略单元测试打包 一个多maven项目聚合的实例

    Maven聚合与继承实例详解.docx

    Maven聚合(Aggregation)功能则允许我们将多个Maven项目组合成一个单一的构建单元。通过在父POM中使用`&lt;modules&gt;`标签,可以列出所有子模块,Maven在构建时会按顺序编译和打包每个子模块。这在处理大型多模块项目时...

    maven聚合和继承

    例如,如果你有一个包含多个子模块的大型应用,如web服务、数据库访问层和业务逻辑层,你可以将它们配置为一个聚合项目,使得一次构建操作就可以完成所有模块的编译、测试和打包。 例如,在`pom.xml`中,我们可以...

    maven权威指南开发实例代码

    最后,书中还涉及到了Maven的多模块项目管理,如何将一个大型项目拆分成多个子项目,并通过聚合项目进行整体管理。这种模块化的构建方式有助于提高代码的复用性和项目的可维护性。 总的来说,《Maven权威指南开发...

    maven实例源码

    1. **Maven多模块项目**:Maven支持多模块项目结构,允许将大型项目拆分为多个独立的模块,每个模块都有自己的POM.xml文件,同时这些模块又可以聚合在一个顶层的父POM中。在这个实例中,"account-parent"可能是所有...

    MAVEN2实例与PPT教程

    8. **Maven的高级特性**: 如聚合项目、多模块项目、远程仓库配置等。 9. **最佳实践**: 提供在实际开发中使用Maven的经验和建议。 通过这个“MAVEN2实例与PPT教程”,学习者将能够深入了解Maven2的工作原理,掌握...

    使用MyEclipse构建多模块Maven项目说明.doc

    本篇文章将详细讲解如何使用MyEclipse这一集成开发环境来构建多模块的Maven项目。 首先,我们需要配置Maven的环境。确保在系统环境变量中设置了`M2_HOME`和`MAVEN_HOME`,这两个变量分别指向Maven的安装路径。例如...

    Maven3实战视频教程(14集)

    Maven3_05_maven的聚合和继承 Maven3_06_复习maven的基本内容 Maven3_07_nexus的介绍和安装 Maven3_08_nexus的配置 Maven3_09_发布项目到nexus中 Maven3_10_生命周期和插件简介 Maven3_11_插件基础 Maven3_12_插件的...

    Spark算子实例maven版

    Spark算子实例maven版是基于Apache Spark框架的开发示例,主要针对的是使用Maven构建项目的开发者。Apache Spark是一个用于大规模数据处理的快速、通用且可扩展的开源框架,它提供了一种分布式、内存计算的编程模型...

    Maven 实战(中文pdf)

    Maven是Apache软件基金会开发的一个开源项目,它以XML文件格式定义项目,能够自动化构建、依赖管理和项目信息管理,极大地提高了开发效率。这本书中文版的出现,对于中文读者来说,无疑提供了更方便的学习资源。 ...

    maven中文指导 学maven的很好一本参考书

    对于大型项目,Maven的聚合(aggregation)功能也很有用,它可以管理多个模块间的依赖关系,形成一个多模块的项目结构。这样,一个复杂的系统可以被拆分成多个独立的子项目,每个子项目都可以独立开发和测试,最后由...

    Maven应用实战源码 配套源码

    在Java开发领域,Maven是一个不可或缺的构建工具,它极大地简化了项目管理和构建过程。《Maven应用实战》这本书由杨式文和孙会军编著,提供了丰富的实践案例和详尽的解析,帮助读者深入理解并掌握Maven的使用技巧。...

    springboot+mybaties+maven聚合+eureka+ribbon访问

    在"springboot+mybaties+maven聚合+eureka+ribbon访问"的场景中,首先,我们会创建一个Maven多模块项目,每个模块代表一个微服务,使用Spring Boot和MyBatis构建业务逻辑。接着,这些微服务会向Eureka注册,提供服务...

    Maven入门到精通

    1. **聚合项目(Aggregation)**:一个POM可以作为多个子项目的父POM,方便管理多个相关联的项目。 2. **继承(Inheritance)**:多个POM可以继承自一个父POM,共享相同的配置。 3. **依赖范围(Dependency Scope...

    maven window下安装包

    第11章:用Maven管理项目版本/11.4 版本管理举例/11.4.9 实例完整源代码 第12章:编写自定义插件/12.1 自定义插件的步骤 第12章:编写自定义插件/12.2 注解说明/12.2.1 @Mojo:定义插件属性 第12章:编写自定义插件/...

    Maven实战 Maven实战Maven实战

    5. **聚合与继承**:聚合允许在一个顶级POM中管理多个子项目,而继承则可以让一个POM继承另一个POM的配置。 #### Maven高级特性 1. **使用Nexus建立私服**:Nexus是一个开源的仓库管理系统,可以帮助企业搭建私有...

Global site tag (gtag.js) - Google Analytics