Maven

一. Maven是什么?

1. 自动化构建工具

Maven这个单词本意是:专家,内行,读音是['meivn]或['mevn];
是一款自动化构建工具,专注服务于java平台的项目构建和依赖管理。

构建就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、JSP页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。

2. 构建环节

1)清理:删除以前的编译结果,为重新编译做好准备。
2)编译:将Java源程序编译为字节码文件。
3)测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
4)报告:在每一次测试后以标准的格式记录和展示测试结果。
5)打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包。
6)安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。
7)部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。

二. Maven核心概念

Maven之所以能够实现自动化的构建,和它的设计是紧密相关的。围绕它的九个核心概念展开:
1)POM
2)约定的目录结构
3)坐标
4)依赖管理
5)仓库管理
6)生命周期
7)插件和目标
8)继承
9)聚合

1. POM

Project Object Model:项目对象模型。将Java工程的相关信息封装为对象作为便于操作和管理的模型。Maven工程的核心配置。可以说学习Maven就是学习pom.xml文件中的配置。

2. 约定的目录结构

现在JavaEE开发领域普遍认同一个观点:约定>配置>编码。意思就是能用配置解决的问题就不编码,能基于约定的就不进行配置。而Maven正是因为指定了特定文件保存的目录才能够对我们的Java工程进行自动化构建。

3. 坐标

使用如下三个向量在Maven的仓库中唯一的确定一个Maven工程。
[1]groupId:公司或组织的域名倒序+当前项目名称
[2]artifactId:当前项目的模块名称
[3]version:当前模块的版本

<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>

如何通过坐标到仓库中查找jar包?
[1]将gav三个向量连起来
com.atguigu.maven+Hello+0.0.1-SNAPSHOT
[2]以连起来的字符串作为目录结构到仓库中查找
com/atguigu/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
注意:我们自己的Maven工程必须执行安装操作才会进入仓库。安装的命令是:mvn install

4. 依赖管理

4.1 基本概念

当A jar包需要用到B jar包中的类时,我们就说A对B有依赖。
当前工程会到本地仓库中根据坐标查找它所依赖的jar包。
配置的基本形式是使用dependency标签指定目标jar包的坐标。例如:

<dependencies>
	<dependency>
		<!-- 坐标 -->
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
		<!-- 依赖的范围 -->
		<scope>test</scope>
	</dependency>
</dependencies>

4.2 依赖的范围

  1. compile
    [1]main目录下的Java代码可以访问这个范围的依赖
    [2]test目录下的Java代码可以访问这个范围的依赖
    [3]部署到Tomcat服务器上运行时要放在WEB-INF的lib目录下
    例如:对Hello的依赖。主程序、测试程序和服务器运行时都需要用到。

  2. test
    [1]main目录下的Java代码不能访问这个范围的依赖
    [2]test目录下的Java代码可以访问这个范围的依赖
    [3]部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
    例如:对junit的依赖。仅仅是测试程序部分需要。

  3. provided
    [1]main目录下的Java代码可以访问这个范围的依赖
    [2]test目录下的Java代码可以访问这个范围的依赖
    [3]部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
    例如:servlet-api在服务器上运行时,Servlet容器会提供相关API,所以部署的时候不需要。

  4. 其他:runtime、import、system等。

4.3 依赖的传递性

当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问。例如:

Maven工程在C的dependency的scope的依赖范围Cjar包对A可见性
A依赖B依赖Ccompile
test×
provided×

4.4 依赖的原则:解决jar包冲突

在这里插入图片描述

4.5 依赖的排除

有的时候为了确保程序正确可以将有可能重复的间接依赖排除。请看如下的例子:
假设当前工程为public,直接依赖environment,environment依赖commons-logging的1.1.1对于public来说是间接依赖。
当前工程public直接依赖commons-logging的1.1.2
加入exclusions配置后可以在依赖environment的时候排除版本为1.1.1的commons-logging的间接依赖

<dependency>
	<groupId>com.atguigu.maven</groupId>
	<artifactId>Environment</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<!-- 依赖排除  这里不用写v  把其他版本都排除了 -->
	<exclusions>
		<exclusion>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<!-- 直接依赖    直接使用1.1.2的version-->
<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.1.2</version>
</dependency>

4.6 统一管理目标jar包的版本

以对Spring的jar包依赖为例:Spring的每一个版本中都包含spring-core、spring-context等jar包。我们应该导入版本一致的Spring jar包,而不是使用4.0.0的spring-core的同时使用4.1.1的spring-context。

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.0.0.RELEASE</version>
</dependency>

问题是如果我们想要将这些jar包的版本统一升级为4.1.1,是不是要手动一个个修改呢?显然,我们有统一配置的方式:

<properties>
	<!-- 自己写一个标签例如spring.version -->
	<spring.version>4.1.1.RELEASE</spring.version>
</properties>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>

5. 仓库

  1. 分类
    ①本地仓库:为当前本机电脑上的所有Maven工程服务。
    ②远程仓库
    [1] 私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务。
    在这里插入图片描述
    [2]中央仓库:架设在Internet上,为全世界所有Maven工程服务。
    [3]中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
  2. 仓库中的文件
    ①Maven的插件
    ②我们自己开发的项目的模块
    ③第三方框架或工具的jar包
    ※不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查
    询或依赖。

6. 插件和目标

1)Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
2)每个插件都能实现多个功能,每个功能就是一个插件目标。
3)Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
例如:compile就是插件maven-compiler-plugin的一个功能;pre-clean是插件maven-clean-plugin的一个目标。

7. 继承

  1. 创建父工程和创建一般的Java工程操作一致,唯一需要注意的是:打包方式处要设置为pom,不再是maven的jar包
  2. 父工程管理依赖
    Parent/pom.xml
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
  1. 子工程引用父工程
    如果子工程的groupId和version如果和父工程重复则可以删除。
<parent>
	<groupId>com.atguigu.maven</groupId>
	<artifactId>Parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	
	<!-- 指定从当前子工程的pom.xml文件出发,查找父工程的pom.xml的路径 -->
	<relativePath>../Parent/pom.xml</relativePath>
</parent>

<!-- 在子项目中重新指定需要的依赖,删除范围和版本号 -->
<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
	</dependency>
</dependencies>

继承也算是统一管理jar包,但是是依赖模块之间的统一管理,而上面说的配置properties的统一管理是在单个模块内的。

8. 聚合

将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作。

在总的聚合工程中使用modules/module标签组合,指定模块工程的相对路径即可
可以在parent/pom.xml中进行配置,也可以创建一个总聚合工程

<!-- module没顺序要求 -->
<modules>
	<module>../Hello</module>
	<module>../HelloFriend</module>
	<module>../MakeFriends</module>
</modules>

三. Maven程序

1. 例子1

1)第一步:创建约定的目录结构

Hello
	 src
	 	main
	    	java
	 		resources
 		test
	 		java
			resources
	 pom.xml

Hello是工程名。
main目录用于存放主程序。
test目录用于存放测试程序。
java目录用于存放源代码文件。
resources目录用于存放配置文件和资源文件。

2)第二步:创建Maven的核心配置文件pom.xml

<?xml version="1.0" ?>
<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">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.atguigu.maven</groupId>
	<artifactId>Hello</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<name>Hello</name>
	  
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.0</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

3)第三步:编写主代码
在src/main/java/com/atguigu/maven目录下新建文件Hello.java

package com.atguigu.maven;
public class Hello {
	public String sayHello(String name){
		return "Hello "+name+"!";
	}
}

4)第四步:编写测试代码
在/src/test/java/com/atguigu/maven目录下新建测试文件HelloTest.java
注意:test文件的类名 建议写成***Test,例如HelloTest,默认规则。

package com.atguigu.maven;	
	import org.junit.Test;
	import static junit.framework.Assert.*;
	public class HelloTest {
		@Test
		public void testHello(){
			Hello hello = new Hello();
			String results = hello.sayHello("litingwei");
			assertEquals("Hello litingwei!",results);	
		}
	}

第五步:运行几个基本的Maven命令
运行Maven命令时一定要进入pom.xml文件所在的目录!

打开cmd命令行,进入Hello项目根目录(pom.xml文件所在目录)执行mvn compile命令,查看根目录变化
cmd 中继续录入mvn clean命令,然后再次查看根目录变化
cmd 中录入 mvn  compile命令, 查看根目录变化
cmd 中录入 mvn  test-compile命令, 查看target目录的变化
cmd 中录入 mvn  test命令,查看target目录变化
cmd 中录入 mvn  package命令,查看target目录变化
cmd 中录入 mvn  install命令, 查看本地仓库的目录变化

2. 例子2 依赖 例子1

  1. POM文件
<?xml version="1.0" ?>
<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">
	  <modelVersion>4.0.0</modelVersion>
	  <groupId>com.atguigu.maven</groupId>
	  <artifactId>HelloFriend</artifactId>
	  <version>0.0.1-SNAPSHOT</version>
	  <name>HelloFriend</name>
	  
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>4.0</version>
				<scope>test</scope>
			</dependency>		
			
			<dependency>
				<groupId>com.atguigu.maven</groupId>
				<artifactId>Hello</artifactId>
				<version>0.0.1-SNAPSHOT</version>
				<!-- 注意这里是compile   Hello要对HelloFriend的main可见 -->
				<scope>compile</scope>
			</dependency>
			
		</dependencies>
</project>
  1. 主程序
package com.atguigu.maven;	
import com.atguigu.maven.Hello;
public class HelloFriend {
	public String sayHelloToFriend(String name){
		Hello hello = new Hello();
		String str = hello.sayHello(name)+" I am "+this.getMyName();
		System.out.println(str);
		return str;
	}
	public String getMyName(){
		return "John";
	}
}
  1. 测试程序
package com.atguigu.maven;	
import static junit.framework.Assert.assertEquals;
import org.junit.Test;
import com.atguigu.maven.Hello;
	
public class HelloFriendTest {
	@Test
	public void testHelloFriend(){
		HelloFriend helloFriend = new HelloFriend();
		String results = helloFriend.sayHelloToFriend("litingwei");
		assertEquals("Hello litingwei! I am John",results);	
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值