1.简介:
maven是一个项目管理工具(简单理解为maven可以将你的java开发过程变简单,尤其是导包这种每次都要执行的复杂步骤,maven可以把你构建工程,管理jar包,编译代码,还可以帮你自动运行单元测试,打包,生成报表等)
1.1 Maven的作用:
1.1.1 依赖管理系统
Maven为Java世界引入了一个新的依赖管理系统jar包管理,jar包升级时修改配置文件即可。在Java世界中,可以用groupid、artifactid、version组成的Coordination(坐标)唯一标识一个依赖。
任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是jar包,也可以是war包或者jar包。一个典型的依赖引用如下所示:
<dependency>
<groupId>javax.servlet</groupId> com.baidu
<artifactId>javax.servlet-api</artifactId> ueditor echarts
<version>3.1.0</version>
</dependency>
坐标属性的理解
Maven坐标为各种组件引入了秩序,任何一个组件都必须明确定义自己的坐标。
groupId
定义当前Maven项目隶属于的实际项目-公司名称。(jar包所在仓库路径)由于Maven中模块的概念,因此一个世纪项目往往会被划分为多个模块。比如Spring是一个实际项目,其对因的Maven模块会有很多,如Spting core,Spring webmvc等。
artifactId
该元素定义实际项目中的一个Maven模块-项目名,推荐的做法是使用实际项目名称作为artifactId的前缀。
version
该元素定义Maven项目当前所处的版本。
1.1.2 多模块构建
我们写项目的时候通常会将一个项目分成多个模块,因为一个项目回非常的大,运行的时候会出一些问题或者启动比较慢,所以一般都会将项目分成多个模块。
在Maven中需要定义一个parent POM作为一组module的聚合POM。在该POM中可以使用标签来定义一组子模块。parent POM不会有什么实际构建产出。而parent POM中的build配置以及依赖配置都会自动继承给子module。
1.1.3 一致的项目结构
不同的编译器的项目结构不同,将项目导入其他编译器的时候会因为目录不一致而出问题。但是Maven项目的结构在所有的编译器中是一致的。
Ant时代大家创建Java项目目录时比较随意,然后通过Ant配置指定哪些属于source,那些属于testSource等。而Maven在设计之初的理念就是Conversion over configuration(约定大于配置)。其制定了一套项目目录结构作为标准的Java项目结构,解决不同ide带来的文件目录不一致问题。
1.1.4 一直的构建模型和插件机制
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<scanIntervaLseconds>10</scanIntervaLseconds>
<contextPath>test</contextPath>
</configuration>
</plugin>
2.Maven安装与配置:
2.1 下载
2.2 配置环境变量
- 新建MAVEN_HOME,值为Maven的bin目录
- 将MAVEN_HOME添加到Path中
- 验证是否安装成功:
3.Maven的生命周期
如图:
4.Maven常用命令
命令 | 作用 |
---|---|
mvn clean | 清楚编译的class文件,即删除target目录 |
mvn validate | 验证项目是否正确 |
mvn compole | 编译maven项目 |
mvn test | 编译maven项目及测试文件 |
mvn package | 编译maven项目及测试文件,并打包 |
mvn install | 编译maven项目及测试文件,并打包,并发布到本地仓 |
mvn deploy | 部署项目到远程仓库 |
mvn tomcat:run | 使用tomcat运行项目 |
5.Maven工程测试—@ Before、@ After
在测试类中:
@ Before修饰的方法会在测试方法之前自动执行
@ After修饰的方法会在测试方法执行之后自动执行
public class A {
@Before
public void before(){
System.out.println("开始测试");
}
@After
public void after(){
System.out.println("开始测试");
}
}
6.依赖冲突调节(自动调节)—最短路径优先原则和最先声明原则:
6.1 依赖冲突:
假设你的项目依赖jar包A,jar包A又依赖jar包B。当添加jar包A时,Maven会把jar包B也自动加入到项目中。这时就可能会产生依赖冲突问题,比如依赖A会引入依赖C,依赖B也会引入依赖C。如果不进行调解则会引入两个依赖C,那么Maven就会发生依赖冲突。
6.2 Maven调解依赖冲突的第一原则——最短路径优先原则:
也就是说项目依赖关系树中路径最短的版本会被使用。例如,假设有几个jar包之间的依赖关系是:
A->B->C->D(2.0)和E->F->D(1.0),如果同时引入A和E,那么D(1.0)会被使用,因为E到D的路径更短。
Spring-context到Spring-aop的路径更短,所以Spring-aop会按照Spring-context的版本引入。
6.3 依赖冲突调节——最先声明原则:
最短路径优先原则不能解决所有问题,比如这样的依赖关系:
A->B->C(1.0)和D->E->C(2.0)
同时引入A和D之后,C(1.0)和C(2.0)的依赖路径长度都为2。此时第一原则将不能解决问题。
Maven调解依赖冲突的第二原则–最先声明原则:
在依赖路径长度相等的前提下,在POM中依赖声明的顺序靠前的会被解析使用。
7.依赖冲突调节(手动调节)——排除依赖和锁定版本
如果不想使用Maven默认的冲突调节方式,有两种方式可以手动进行冲突调节。
7.1 排除依赖
例如:如果想使用Spring-webmvc的Spring-aop包,那么可以让Spring-context引入时排除引入Spring-aop包,这样就可以使用Spring-webmvc包了,写法如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
7.2 锁定版本:
在Maven中为某个jar包配置锁定版本后,不考虑依赖的声明顺序和依赖路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。以下可以直接配置spring-aop锁定的版本。
<dependencyManagement>
<dependencies>
<dependency>
<grouprd>org.springframework</groupId>
<artifactrd>spring-
aop</artifactId>
<version>4.2.4.RELEASE</version></dependency>
</dependencies>
</dependencyManagement>
8.Maven聚合开发——聚合关系:
之前我们在Idea中开发时回将项目的所有包放在同一个工程中。
- daomain:定义实体类
- dao:操作数据库
- service:具体业务逻辑,需要调用dao的方法
- controller:前后端交互,需要调用service的方法
- webapp:存放前端资源
假如我们现在写了两个项目分别是电商卖家和电商买家端,两个项目都需要调用service层查询订单的方法。原来的写法如下:
重复编码造成开发效率低。
而使用maven后,我们可以把之前的项目按需拆分成一个个小项目,之后将小项目发布到仓库中,小项目之间也可以使用相互引用,并且在我们的项目中引入需要的小项目即可。
Maven将一个大项目分成一个个小项目开发,最后打包时会将这些小的项目打成一个完整的war包独立运行。
Maven聚合开发总结:
- 将原有项目按需拆分成一个个小项目开发
- 最后打包时会将小项目打成一个完整的war包独立运行
- 聚合开发能提高代码复用率,提升开发效率
9.Maven聚合开发——继承关系:
Maven中的继承是针对于父工程和子工程。父工程定义的依赖和插件子工程都可以直接使用。注意父工程类型一定为POM类型工程。
多继承
在Maven中对于继承采用的也是单继承,也就是说一个子项目只能有一个父项目。但我们可以在配置多继承。
<dependencyManagement>
<dependencies>
<!-- 父项目a-->
<dependency>
<groupId>com.itbaizhan</groupId>
<artifactId>parent_a</artifactId>
<version>1.0-SNAPSHOP</version>
<type>pom</type>
<!-- 引入父类,scope的值为import-->
<scope>import</scope>
</dependency>
<!-- 父项目b-->
<dependency>
<groupId>com.itbaizhan</groupId>
<artifactId>parent_b</artifactId>
<version>1.0-SNAPSHOP</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
10.Maven聚合案例——搭建父工程
创建Maven工程作为父工程,父工程是虚拟工程,不需要写逻辑代码,所以删除父工程的src目录。
由于父工程的依赖和插件子工程都能继承,所以可以将需要的依赖和插件都配置在父工程中。
<packaging>pom</packaging>
<properties>
<!-- Spring版本 -->
<spring.version>5.2.12.RELEASE</spring.version>
</properties>
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- MyBatis与Spring的整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- springmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 事务 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- jsp -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
<systemProperties>
<java.util.logging.SimpleFormatter.format>%1$tH:%1$tM:%1$tS %2$s%n%4$s: %5$s%6$s%n </java.util.logging.SimpleFormatter.format>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
IDEA中工程project和模块Module有什么区别?
答:没有什么区别,只是新工程会占据一个新窗口,一般写父工程时定义为新工程,写子工程时定义为新模块。