Maven-Day01
1、传统项目架构带来的问题
1.一个项目就是一个工程,模块之间的划分通过package来区分,对于大项目而言极度不友好 2.工程升级维护中打包,测试,部署等工作麻烦 3.项目中的jar包管理起来特别麻烦,体现在以下几点 2-1.所有的jar包需要自行去官网或github上下载 2-2.项目中的jar包需要通过复制粘贴或构建路径等方式导入,操作麻烦 2-3.多个项目中存在相同的jar包,浪费存储空间 2-4.当存在jar包之间的依赖关系时,需要开发人员清楚的了解其中的关系,例如spring-core依赖于commons-logging 2-5.当一切工作准备就绪后,还可能会面临jar包版本不一致,包与包之前冲突等问题 4.项目架构不统一,不同的开发工具或者不同的开发人员使用的目录结构不一致 Eclipse:WebContent MyEclipse:WebRoot
2、什么是Maven?
1.Maven是Apache基金会下一个跨平台,服务于Java的项目管理工具 2.Maven的本质是将项目开发和管理过程抽象成一个项目对象模型(POM)来进行管理
3、Maven的优势
1.聚合继承:一个项目可以由多个子模块构成,便于进行大型项目管理 2.项目构建:提供标准的,跨平台的自动化项目构建方式 3.依赖管理:方便快捷的管理项目依赖,多个项目可以引用同一个仓库中的jar包,避免空间浪费,包冲突等一系列问题 4.统一结构:maven提供了一套标准的项目结构共开发人员使用
4、Maven的环境要求
1.Maven是一个基于Java的工具,所以要做的第一件事情就是安装JDK。 2.确保安装了JDK之后还需要配置JAVA_HOME 3.JDK版本要求 2-1.Maven3.3要求JDK1.7或以上 2-2.Maven3.2要求JDK1.6或以上 2-3.Maven3.0/3.1要求JDK1.5或以上
5、下载并安装Maven
5-1.官网下载Maven
5-2.安装Maven
1.解压下载后maven压缩包 2.配置环境变量:MAVEN_HOME或者M2_HOME 3.将MAVEN_HOME或者M2_HOME下的bin目录配置到Path中,以便在任意位置使用maven 4.验证:mvn -version java -version
6、Maven安装目录介绍
bin:该目录包含了mvn运行的脚本 boot:该目录下文件是一个类加载器,对Java类加载器进行扩展,maven用该框架加载自己的类库 cont:该目录包含一个非常重要的文件settings.xml,直接修改此文件,可以在机全局定制化为maven行为,建议复制一份修改 lib:包含了maven允许时需要的java类库 LICENSE:记录了maven使用的软件许可证 NOTICE:记录了maven包含的第三方软件 README:包含了maven的简介,包括安装需求和如何安装的简要命令
7、Maven核心--仓库
1.仓库:用于存储各种jar包 2.仓库分类 本地仓库:本机上存储资源的目录 远程仓库:非本机上存储资源的目录 中央仓库:Maven官方维护,存储所有开放资源的仓库 私服:研发团队存储资源的仓库,从中央仓库获取资源 3.私服的作用 1.保存经购买或自主研发的未开源的资源 2.仅对内部开放,不对外共享 3.解决本地仓库在团队开发中的局限性
8、Maven核心--坐标
1.坐标:Maven中坐标用于描述仓库中资源的位置 2.坐标的组成 groupId:定义当前Maven项目的隶属组织名称(通常是域名反写,例如:org.apache.*) artifactId:定义当前Maven项目的名称(通常是模块名称,例如Spring中的:spring-aop,spring-mvc) version:当前版本号
ps:maven仓库中的资源
9、配置本地仓库
本地仓库默认路径:C:\Users\主机名称\.m2\repository 问题一:C盘作为系统盘,应该尽量精简,本地仓库配置在C盘会导致占用较多的空间 解决方案:通过配置文件settings.xml将本地仓库配置到其他路径 问题二:最终资源来源于中央仓库,但中央仓库为国外网站,下载速度很慢 解决方案:阿里云为我们提供了镜像仓库来代替中央仓库,效果不变,下载速度提升
9-1.将本地仓库配置到其他路径
1.在settings.xml中找到如下配置 <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository>--> 2.很明显看出来,localRepository路径被注释掉了,默认路径为 ${user.home}/.m2/repository 3.开始更改:复制一份本地仓库配置的标签来更改,不建议修改原先的配置 <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository>--> <localRepository>E:\xiaoscmvn\repository</localRepository>
9-2.配置阿里云镜像仓库
1.从settings.xml中找到已注释的下列代码 <!-- <mirror> <id>mirrorId</id> <mirrorOf>repositoryId</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://my.repository.com/repo/path</url> </mirror>--> 2.从以上配置可以看到镜像仓库的统一配置方式 3.阿里云的镜像仓库配置如下 <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
10、第一个Maven应用
10-1.开发步骤总览(手动构建)
1.创建maven工程 2.编写pom.xml文件 3.编写Java代码 4.编译 5.测试 6.报告 7.打包 8.部署 9.发布
10-2.创建maven工程(标准的maven项目结构,web项目有些微区别)
10-3.编写一个最简单的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <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"> <!--指定了当前Maven模型的版本号,对于Maven2和Maven3来说,它只能是4.0.0--> <modelVersion>4.0.0</modelVersion> <!--顾名思义,标识组织名称,一般由三部分组成(不一定),使用.分隔符隔开--> <!-- 第一部分是项目用途:例如商用com,非营利性组织org 第二部分代表公司名 第三部分代表项目名 --> <!--例如:org.springframework--> <groupId>cn.bdqn</groupId> <!--代表项目名或模块名--> <!--例如:spring-tx/spring-aop --> <artifactId>xiaosc</artifactId> <!--Snapshot和Release版本的区别--> <!-- 1.定义上 1-1.SNAPSHOT版本代表不稳定、尚处于开发中的版本,快照版本 1-2.RELEASE版本则代表稳定的版本,发行版本。 2.应用场景上 2-1.依赖库中的jar正处于开发的阶段,会被经常被更新,这种情况下,如果使用Release,会频繁增加版本号,导致版本号的滥用 这种时候应该使用SNAPSHOT 2-2.已发布的应用使用了SNAPSHOT,会导致应用的不稳定,因为第三方库更新后应用也会马上更新,这个时候就要选择RELEASE版本 来根据版本号进行jar包的更新 --> <version>1.0-SNAPSHOT</version> <!--依赖jar包的集合--> <dependencies> <!--导入junit依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!-- compile:默认值,存在于所有阶段(开发、测试、部署、运行) provided:只在开发、测试阶段使用,目的是不让Servlet容器和你本地仓库的jar包冲突,如servlet.jar runtime:只在运行时使用,如JDBC驱动,适用运行和测试阶段 test:只在测试时使用,用于编译和运行测试代码。不会随项目发布 system:类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它 需要显示的指定jar文件的路径<systemPath>path</systemPath> --> <scope>compile</scope> </dependency> </dependencies> </project>
10-4.通过一个业务方法和一个单元测试方式演示maven项目构建流程
业务方法
package cn.bdqn; public class FirstMvn{ public String say(String message){ System.out.println("say: " + message); return "say: " + message; } }
单元测试:Assert检验预想结果和实际结果是否一致,若不一致会抛出异常信息
package cn.bdqn; import org.junit.Test; import org.junit.Assert; public class TestDemo{ @Test public void testSay(){ FirstMvn fm = new FirstMvn(); String result = fm.say("maven"); Assert.assertEquals("say: maven",result); } }
11、Maven构建项目
构建的各个环节 清理clean:将以前编译得到的旧文件class字节码文件删除 编译compile:将java源程序编译成class字节码文件 测试test:自动测试,自动调用junit程序 报告report:测试程序执行的结果 打包package:动态Web工程打War包,java工程打jar包 安装install:Maven特定的概念-----将打包得到的文件复制到“仓库”中的指定位置 部署deploy:将动态Web工程生成的war包复制到Servlet容器下,使其可以运行
12、学习效果
1.理解传统项目的局限性 2.maven的优势 3.成功搭建好maven的环境 自定义maven仓库路径 配置阿里云镜像 4.理解仓库和坐标的概念 5.手动构建maven项目 清理clean:将以前编译得到的旧文件class字节码文件删除 编译compile:将java源程序编译成class字节码文件 测试test:自动测试,自动调用junit程序 报告report:测试程序执行的结果 打包package:动态Web工程打War包,java工程打jar包 安装install:Maven特定的概念-----将打包得到的文件复制到“仓库”中的指定位置
Maven-Day02
1、在IDEA中使用Maven
使用maven构建Java项目
使用maven构建web项目
2、依赖管理
依赖配置
依赖配置指的是当前项目运行需要的jar,一个项目可以设置多个依赖 在pom.xml文件中,依赖配置如下 <dependencies> <!--在项目中引用外部jar包--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <!--在项目中引用内部开发的jar包--> <dependency> <groupId>cn.bdqn</groupId> <artifactId>mvndemo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
依赖范围
依赖范围:资源jar包在maven项目中的作用范围 理解:Maven通过依赖范围来控制何时引用jar包 使用:Maven的依赖范围由scope控制 案例:以下为一个依赖,scope没有显式的表达,取默认值(compile) 修改:将scope默认值改为其他的值 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!--开始进行修改,将依赖范围修改为test,需要显式的指定--> <scope>test</scope> </dependency> </dependencies>
以下为 scope的取值
依赖范围 | 对于编译执行环境有效 | 对于测试执行环境有效 | 对于运行时执行环境有效 | 应用案例 |
---|---|---|---|---|
compile | √ | √ | √ | spring-core |
test | x | √ | x | junit |
provided | √ | √ | x | servlet-api |
runtime | x | √ | √ | JDBC驱动 |
system | √ | √ | x | 本地的,Maven仓库之外的类库 |
compile:依赖范围默认值是compile,最常用,表示maven项目在编译,测试,运行阶段都需要引用该依赖 test:表示该依赖包只和测试相关,测试代码的编译和运行会引用该依赖 provided:表示maven项目只在编译和测试时引用该依赖,打包运行时不会引入该依赖(Servlet ) runtime:不常用,表示在测试和运行阶段需要引入该依赖,如JDBC,由反射加载,可以不参与编译 system:基本不使用,指依赖在maven仓库中不存在,而是存在于本机某个文件夹下,需要通过systemPath指定路径
依赖传递
在mvndemo的 pom.xml文件中加入如下配置
mvndemo依赖于mybatis-3.5.7.jar <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> </dependencies>
我们把上述的行为称为:依赖传递
依赖传递可能产生的问题:jar包冲突(有maven在无需担心)!
问题描述如下
当模块webdemo需要使用spring-aop5.3.1和spring-messaging5.3.2两个模块: 由于spring-aop和spring-messaging都依赖于spring-core和spring-beans,但是版本不一致 这个时候webdemo既依赖于spring-core和spring-beans的5.3.1和spring-core和spring-beans的5.3.2 此时,到底是选择5.3.1还是5.3.2? 或者是产生冲突报错呢?
操作如下
在webdemo中导入依赖,spring-aop5.3.1和 spring-messaging5.3.2
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>5.3.2</version> </dependency>
maven操作面板中的结果
从以上结果不难看出,maven帮我们自动忽略了冲突,那么maven忽略的规则是怎样的?
maven解决依赖冲突
1.Maven自我调节原则 1-1.第一声明优先原则 1-2.就近原则 2.可选依赖 3.排除依赖 4.版本锁定
maven自我调节原则之:第一声明优先原则
那么,最终依赖的优先级是5.3.1 > 5.3.2 测试:将以上依赖顺序反过来
maven自我调节原则之:就近原则
该原则规定:层数越少,优先级越高 案例如下 项目P1依赖于dep1,依赖于A.jar A.jar依赖于dep2,依赖于B.jar B.jar依赖于dep3 那么,优先级:dep1 > dep2 > dep3
2.maven可选依赖
maven可选依赖,指的是被依赖者不让依赖者检测到自身的其他依赖
3.maven排除依赖
maven排除依赖,指的是依赖者拒绝接收被依赖者附带的其他依赖
4.版本锁定
所谓版本锁定就是指定依赖包的版本,这种依赖冲突的解决方案是目前实际项目中使用的最多的 版本锁定使用<dependencyManagement>节点 <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> 此时使用的是junit4.12 当去掉依赖中的版本号 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> 此时使用的是junit4.11
总结:类似于继承,子类没有使用父类的,子类重写使用自己的
实战经验:为了项目版本依赖管理的统一和方便升级,版本信息通常使用OGNL表达式表示,如下
<properties> <spring-version>4.3.2.RELEASE</spring-version> <mybatis-version>3.5.7</mybatis-version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> </dependencies> </dependencyManagement>
3、使用Maven搭建SSM框架
pom文件部分配置如下
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!-- spring版本号 --> <spring.version>5.3.1.RELEASE</spring.version> <!-- mybatis版本号 --> <mybatis.version>3.5.7</mybatis.version> <!-- log4j日志文件管理包版本 --> <log4j.version>1.2.17</log4j.version> <c3p0.version>0.9.5.2</c3p0.version> <taglibs.version>1.1.2</taglibs.version> </properties>
4、学习效果
1.会使用idea创建maven对应的Java项目和web项目 2.maven依赖管理 依赖范围 依赖传递 什么是依赖传递? 依赖传递引发的jar冲突问题 maven如何解决冲突问题 maven自我调节’ 可选依赖 排除依赖 版本锁定 3.使用maven进行ssm项目的开发 版本锁定 使用ognl表达式控制版本