Maven
1、使用Maven后每个jar包只在本地仓库中保存一份,需要jar包的工程只需要维护一个文本形式的jar包的引用——我们称之为“坐标”。
2、Maven就可以替我们自动的将当前jar包所依赖的其他所有jar包全部导入进来,无需人工参与,节约了我们大量的时间和精力。用实际例子来说明就是:通过Maven导入commons-fileupload-1.3.jar后,commons-io-2.0.1.jar会被自动导入,程序员不必了解这个依赖关系。
3、使用Maven就可以自动的处理jar包之间的冲突问题。因为Maven中内置了两条依赖原则:最短路径者优先和先声明者优先;
4、使用Maven我们可以享受到一个完全统一规范的jar包管理体系。你只需要在你的项目中以坐标的方式依赖一个jar包,Maven就会自动从中央仓库进行下载,并同时下载这个jar包所依赖的其他jar包——规范、完整、准确!一次性解决所有问题!
5、将项目拆分成多个工程模块;Maven的依赖管理机制。
上层模块依赖下层,所以下层模块中定义的API都可以为上层所调用和访问。
6、在实际生产环境中,项目规模增加到一定程度后,可能每个模块都需要运行在独立的服务器上,我们称之为分布式部署;
Maven是一款自动化构建工具,专注服务于Java平台的项目构建和依赖管理。在JavaEE开发的历
史上构建工具的发展也经历了一系列的演化和变迁:
Make→Ant→Maven→Gradle→其他……
通过浏览器访问Java程序时就必须将包含Java程序的Web工程编译的结果“拿”到服务器上的指定目录下,并启动服务器才行。这个“拿”的过程我们叫部署。
我们可以将未编译的Web工程比喻为一只生的鸡,编译好的Web工程是一只煮熟的鸡,编译部署的过程就是将鸡炖熟。
Web工程和其编译结果的目录结构对比见下图:
构建就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、JSP页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
构建环节
1) 清理:删除以前的编译结果,为重新编译做好准备。
2) 编译:将Java源程序编译为字节码文件。
3) 测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
4) 报告:在每一次测试后以标准的格式记录和展示测试结果。
5) 打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包。
6) 安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。
7) 部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。
Maven的九个核心概念展开:
1) POM(Project Object Model:项目对象模型。);
2)约定的目录结构;
3)坐标;
使用如下三个向量在Maven的仓库中唯一的确定一个Maven工程。 [1]groupId:公司或组织的域名倒序+当前项目名称 [2]artifactId:当前项目的模块名称 [3]version:当前模块的版本 <groupId>com.atguigu.maven</groupId> <artifactId>Hello</artifactId> <version>0.0.1-SNAPSHOT</version>
4) 依赖管理; 5) 仓库管理; 6)生命周期; 7)插件和目标; 8)继承; 9) 聚合
Maven程序
1) 第一步:创建约定的目录结构(约定>配置>编码;Maven正是因为指定了特定文件保存的目录才能够对我们的Java工程进行自动化构建。)
Hello
src
——main(目录用于存放主程序。)
———— java(目录用于存放源代码文件。)
————resources(目录用于存放源代码文件。)
——test(目录用于存放测试程序。)
————java(目录用于存放源代码文件。)
————resources(目录用于存放源代码文件。)
pom.xml
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
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); } }
5) 第五步:运行几个基本的Maven命令
打开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命令, 查看本地仓库的目录变化
本地仓库
1) 配置本地仓库 1) Maven的核心程序并不包含具体功能,仅负责宏观调度。具体功能由插件来完成。Maven核心程序会到本地仓库中查找插件。如果本地仓库中没有就会从远程中央仓库下载。此时如果不能上网则无法执行Maven的具体功能。为了解决这个问题,我们可以将Maven的本地仓库指向一个在联网情况下下载好的目录。 2) Maven默认的本地仓库:~.m2 epository目录。 Tips:~表示当前用户的家目录。 3) Maven的核心配置文件位置: 解压目录 D:DevInstallapache-maven-3.2.2confsettings.xml 4) 设置方式 <localRepository>以及准备好的仓库位置</localRepository> <localRepository>D:RepMaven</localRepository>
解决maven test命令时console出现中文乱码乱码
<build> <plugins> <!-- 解决maven test命令时console出现中文乱码乱码 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.7.2</version> <configuration> <forkMode>once</forkMode><!--在一个进程中进行所有测试 ; 默认值:once --> <argLine>-Dfile.encoding=UTF-8</argLine> </configuration> </plugin> </plugins> </build>
依赖管理
依赖的范围
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等。
各个依赖范围的作用可以概括为下图:
依赖的传递性
当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问。
Maven工程 依赖范围 对A的可见性
A B C compile √
D test ×
E provided ×
比如
<dependency> <groupId>com.atguigu.maven</groupId> <artifactId>Hello</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> <!-- 默认是可传递的,可不写 --> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope> --->>不具备传递性,所以每个pom.xml里面都要写。
</dependency>
依赖的原则:解决jar包冲突
1) 路径最短者优先
A依赖B,B依赖C; 则优先使用B中的jar包;
2) 路径相同时先声明者优先
A依赖B,B依赖C,
A依赖D; B和D都是直接依赖,谁先在dependency标签中声明,优先引用谁的jar包。
这里“声明”的先后顺序指的是dependency标签配置的先后顺序。
依赖的排除
有的时候为了确保程序正确可以将有可能重复的间接依赖排除。请看如下的例子:
假设当前工程为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> <!-- 依赖排除,排除commons-logging的所有版本,不加的话你直接引用1.1.2的版本,那么其他间接引用的版本也会加到下面 --> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <!-- 加上你所要引用的版本, --> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.2</version> </dependency>
统一管理目标jar包的版本
如果我们想要将这些jar包的版本统一升级为4.1.1,是不是要手动一个个修改呢?显然,我们有统一配置的方式:
把version自动动态的获取获取
<properties> <spring.version>4.1.1.RELEASE</spring.version> </properties>
把下面用到的用${ }加上去
<version>${spring.version}</version>
继承
由于非compile范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置。例如:junit的test
此时如果项目需要将各个模块的junit版本统一为4.9,那么到各个工程中手动修改无疑是非常不可取的。使用继承机制就可以将这样的依赖信息统一提取到父工程模块中进行统一管理。
创建父工程和创建一般的Java工程操作一致,唯一需要注意的是:打包方式处要设置为pom。
在子工程中引用父工程;在父工程中管理依赖
<!-- 在父工程中统一管理jar包管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
在子工程的pom.xml中
<!-- 配置父工程 -->
<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>
聚合
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作。
<!-- 聚合 --> <modules> <!-- 配置各个模块的相对路径 --> <module>../MakeFriend</module> <module>../OurFriend</module> <module>../HelloFriend</module> <module>../Hello</module> </modules> [INFO] Parent ............................................. SUCCESS [ 0.402 s] [INFO] Hello .............................................. SUCCESS [ 5.143 s] [INFO] HelloFriend ........................................ SUCCESS [ 2.329 s] [INFO] OurFriend .......................................... SUCCESS [ 0.124 s] [INFO] MakeFriend ......................................... SUCCESS [ 0.069 s]
WebMaven工程
创建简单的Maven工程,打包方式选war包
在Idea中的配置:
Maven酷站
我们可以到http://mvnrepository.com/搜索需要的jar包的依赖信息。
Maven报错信息收集:
maven项目添加pom依赖后,一直不能正常导入所依赖的jar包,并且报错“ Auto build completed with errors”