maven聚合工程(深度剖析)
Posted 一宿君
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了maven聚合工程(深度剖析)相关的知识,希望对你有一定的参考价值。
聚合的意义:
-
对于一个大型的项目,如果我们直接作为一个工程开发,由于相互之间的依赖我们只能从头到尾由一组人开发,否则就会出现一个类好多人开发,相互更改的混乱局面,这个时候我们就将项目进行了横向和纵向的拆分。
-
横向拆分
所谓的横向的拆分就是我们平常说的三层架构,将每个功能模块分成三层去开发
即web层(表现层),service层(业务逻辑层)、dao层(数据访问层、持久层),
可以理解为将一个功能模块的不同调用过程(三层的调用)进行了水平方向的拆分。 -
纵向拆分
所谓的纵向拆分就是将一个项目根据多个功能模块进行拆分,可以理解为,为了完成一个系统,深度(纵向)分析需要有哪些功能,然后将这些功能独立出来(独立为模块),进行了(纵向)拆分。
-
横向和纵向拆分后,对每层架构和功能模块进行单独的开发,项目整合的时候就需要有一个能够整合这些架构或者模块的工程,这就是所谓聚合工程的意义。
创建聚合工程的要点(重点理解):
- 该聚合项目(父级项目、顶级项目)本身也是一个maven项目,它必须有自己的pom
- 它的打包方式必须是:pom
- 引入新的元素:modules—module(模块:每个模块其实也是一个项目)
- 版本:聚合模块的版本要和被聚合模块的版本一致
- relative path:每个module名称都是一个当前pom的相对目录
- 目录名称:为了方便快速定位,模块所处的目录应当与其artifactId一致(maven约定而不是硬性要求),总之,模块所处的目录必须要和聚合模块中的模块目录保持一致。
- 聚合模块减少的内容:聚合模块的内容仅仅是一个pom.xml文件,它不包含src/main/java和src/test/java等目录,因为他只是用来将其他模块整合构建成一个整体的工具,本身并没有实质的内容。
- 聚合模块和子模块的目录:它们可以是父子级,也可以是平行结构(推荐)。默认是父子级结构,但是不建议使用,因为父子级是一种嵌套关系,子模块要建在父模块里面,维护起来很容易紊乱;推荐使用平行结构,是因为维护起来一目了然,条理比较清晰,当然同时要在pom文件的中修改相应的目录路径配置。
- 如果聚合模块对某一个子模块进行了删除操作,那么一定要在聚合模块的pom.xml文件中的modules选项中将对应的子模块删除掉。
继承的意义:
- 我们知道 maven工程之间可以完成依赖的传递性,实际上就是各个jar包和war包之间存在依赖的传递性,但是必须是compile范围的依赖才具有传递性,才可以根据传递性统一管理一个依赖的版本。
- 而对于test范围的依赖,只是孤零零的存在于某个项目中,各个项目中的依赖版本可能不同,容易造成问题,所以test范围依赖的统一版本的问题,通过依赖的传递性是无法解决的,所以我们使用继承这个概念来处理。
继承(要点):
1、说到继承肯定是一个父子结构,首先要创建一个parent project;
2、<packaging>:作为父模块的pom,其打包类型必须是pom;
3、结构:父模块本身就是为了消除子模块中依赖的冗余性,所以不需要src/main/java和src/test/java等目录;
4、新的元素:<parent>,是在子模块中用来继承父模块的;
5、<parent>元素的属性:<relativePath>表示父模块中pom的相对路径,在构建的时候maven会先根据<relativePath>检查父模块pom,如果找不到,再从本地仓库中查找;
6、<relativePath>的默认值:../pom.xml;
7、子模块省略groupId和version:在子模块中可以不声明groupId和version两个元素,子模块将隐式的继承父模块中的groupId和version元素。
8、继承能够提高代码的复用性,还可以让项目更加安全。
总结:
- 对于聚合模块来说,它知道有哪些被聚合的模块,而对于被聚合的模块来说,它们不知道被谁聚合了,也不知道它的存在
- 对于继承关系的父POM来说,它不知道自己被哪些子模块继承了,对于子POM来说,它必须知道自己的父POM是谁
- 在一些最佳实践中我们会发现:一个POM既是聚合POM,又是父POM,这么做主要是为了方便。
我们就用如下图来演示maven聚合工程:
1、创建聚合工程整体架构
1.1、首先在idea创建一个空项目
1.2、创建ebuy-parent模块(管理项目所需依赖)
- 然后在ebuy-parent模块中添加如下版本控制和相关依赖
<!-- properties:统一管理版本号 --> <properties> <junit.version>4.12</junit.version> <jstl.version>1.2</jstl.version> <servlet-api.version>2.5</servlet-api.version> <jsp-api.version>2.0</jsp-api.version> </properties> <dependencyManagement> <dependencies> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <!-- version:引用上面properties中配置的版本号 --> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> </dependencies> </dependencyManagement>
1.3、创建ebuy-main模块(聚合工程的父级项目)
1.4、分层创建模块(横向拆分)
1.4.1、创建ebuy-pojo模块
1.4.2、创建ebuy-dao模块
1.4.3、创建ebuy-service模块
1.4.4、创建ebuy-servlet模块(maven-web项目)
1.5、查看ebuy-main模块中pom.xml文件
2、测试聚合工程
- 首先分析多层依赖关系:
2.1、首先是dao层引用pojo层
2.2、service层引用dao层
2.3、servlet层引用service层
2.4、简单测试
-
首先在ebuy-pojo模块中创建com.ebuy.pojo包,其次创建UsersInfo类
-package com.ebuy.pojo; /** * @author 一宿君(CSDN:qq_52596258) * @date 2021年05月23日 16时40分04秒 * 用户信息实体类 */ public class UsersInfo { private int userid; private String username; private String userpwd; public int getUserid() { return userid; } public void setUserid(int userid) { this.userid = userid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUserpwd() { return userpwd; } public void setUserpwd(String userpwd) { this.userpwd = userpwd; } @Override public String toString() { return "UsersInfo{" + "userid=" + userid + ", username='" + username + '\\'' + ", userpwd='" + userpwd + '\\'' + '}'; } }
-
然后在ebuy-dao模块中创建com.ebuy.dao包,在下面创UsersInfoDao接口,在接口定义方法getUsers()
package com.ebuy.dao; import com.ebuy.pojo.UsersInfo; /** * @author 一宿君(CSDN : qq_52596258) * @date 2021-05-23 16:52:20 */ public interface UsersInfoDao { /*用于获取UsersInfo用户信息*/ public UsersInfo getUsers(); }
-
然后在ebuy-service模块中创建com.ebuy.service包,然后在下面创建UsersInfoDao接口的实现类UsersInfoService,然后重写方法getUsers()
package com.ebuy.service; import com.ebuy.dao.UsersInfoDao; import com.ebuy.pojo.UsersInfo; /** * @author 一宿君(CSDN : qq_52596258) * @date 2021-05-23 16:55:09 */ public class UsersInfoService implements UsersInfoDao { public UsersInfo getUsers() { UsersInfo usersInfo = new UsersInfo(); usersInfo.setUserid(1001); usersInfo.setUsername("张三"); usersInfo.setUserpwd("123456"); return usersInfo; } }
-
然后在ebuy-servlet模块中创建com.ebuy.servlet包,继承HttpServlet类,重写doGet()和doPost()方法。
-
首先要将有关jsp的相关依赖引入到ebuy-servlet的pom.xml文件中,在此处引用的全是ebuy-parent中的依赖,version版本是通过jstl标签的形式获取的。
<dependencies> <!--servlet层依赖service层--> <dependency> <groupId>com.ebuy</groupId> <artifactId>ebuy-service</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <!-- version:引用上面properties中配置的版本号 --> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies>
package com.ebuy.servlet; import com.ebuy.service.UsersInfoService; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 一宿君(CSDN : qq_52596258) * @date 2021-05-23 16:57:11 */ public class UsersInfoServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { UsersInfoService usersInfoService = new UsersInfoService(); System.out.println(usersInfoService.getUsers()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
-
最后还需在web.xml文件中配置下servlet
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>usersinfo</servlet-name> <servlet-class>com.ebuy.servlet.UsersInfoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>usersinfo</servlet-name> <url-pattern>/usersinfoServlet</url-pattern> </servlet-mapping> </web-app>
-
配置tomcat服务器
- 然后启动个tomcat发现报如下错误(版本问题):
- 将如下版本控制代码写入到所有模块项目的pom.xml文件中:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.9</maven.compiler.source> <maven.compiler.target>1.9</maven.compiler.target> </properties>
- 然后在启动tomcat服务器:
- 最后测试usersInfoServlet:
3、maven聚合工程的优点
在项目中使用Maven可以大大简化开发及构建的过程,一旦产品线庞大,包含的项目及模块繁多时,各模块间版本管理就会产生不一致现象,从而给维护及开发带来了不少难题。Maven的聚合特性可以帮助我们把项目的多个模块聚合在一起,使用一条命令完成构建。
以上是关于maven聚合工程(深度剖析)的主要内容,如果未能解决你的问题,请参考以下文章