1.maven简介
1.1 简介
maven最主要体现在两个词上:项目和管理。maven给我们整个开发团队找出了一种能够更加科学的去管理我们项目的思想。maven通过使用配置文件的方式使得项目在管理和交接的过程中成本变得非常低。maven提出了一种叫做maven仓库的概念,使得我们可以将第三方和我们需要引用的项目都放置在maven仓库当中。如果其他人或项目组也需要使用,就可以直接通过maven进行配置就行。这样就可以将人员成本、沟通成本等等都进行降低。
如果还不理解我们举个例子:加入我们现在想做一份菜:糖醋排骨。如果我们想要做这道菜,那么我们首先要先去菜市场买排骨、糖、醋、......,而且在做的时候还要注意使用糖醋的用量等等。那么如果有一个超市,该超市有卖糖醋排骨的料理包,这是不是就能很大的节省我们做饭和买菜的时间开销。其实maven就是这个卖料理包的超市,当人卖的不是料理包,而是一系列的jar包。这样我们在写代码的时候就不需要去其他网站上下载一大堆的jar包。
1.2 项目构建
不知道大家有没有意识到,构建(build)是每一个程序员都在做的工作。仔细观察我们会发现,除了编写代码,我们每天都有相当一部分时间花在了编译,运行单元测试,生成文档、打包和部署等繁琐和不起眼的工作上,这就是构建。如果我们现在还是手工的做这些事情,那么时间成本就太高了,于是有人用软件的方法让这一系列工作完全自动化。是软件构建完全像流水线一样,只需要一条简单的命令,所有繁琐的步骤就能很快的自动完成。
1.3 项目构建工具
Ant构建
最早的构建工具,基于IDE,大概是2000年有的,当时最流行的java构建工具,不过他的xml脚本编写风格让xml文件特别大。对工程构建过程中的过程控制的特别好。
Maven [ java ]
Maven是一个项目管理和整合工具。Maven为开发者提供了一整套完整的生命周期框架。开发团队几乎不用花多长时间就能够自动完成工程的基础构建配置。他填补了Ant的缺点,Maven第一次支持了从网上下载的功能,仍然采用xml作为配置文件格式Maven专注的是项目依赖,使用java编写。
Gradle
属于结合以上两个的优势,他继承了Ant的灵活和Maven的生命周期管理,他最终被google作为了Android御用管理工具。他最大的区别是不用XML作为配置文件格式,采用了DSL格式,使得脚本更加简洁。
目前市面上Ant比较老,所以一般是一些比较传统的软件企业公司使用,Maven使用java编写,是当下大多数互联网公司使用的一种构建工具,中文文档也比较齐全,gradle是用groovy编写,目前比较新的构建工具一些初创互联网公司会使用,以后会有很大的使用空间。
1.4 Maven的四大特征
1.4.1 依赖管理系统
Maven为java世界引入了一个新的依赖管理系统jar包管理 jar包升级时修改配置文件即可。在java世界中,可以用gropId、artifactId、version组成Coordination(坐标)唯一标识一个依赖。
任何基于maven构建的项目自身也必须定义这三个属性。
org.mybatis
mybatis
3.4.5
坐标属性的理解
Maven坐标为各个组件引入了新秩序,任何一个组件都必须明确定义自己的坐标。
groupId
定义当前Maven项目隶属的实际项目-公司名称。(jar包所在仓库路径)由于maven中模块的概念,因此一个项目实际往往会被分成多个模块。比如Spring是一个实际的项目,其对应的Maven模块会有很多,比如Spring-croe,spring-webmvc等。
artifactid
该元素定义实际项目中的Maven模块-项目名称,推荐的做法是使用实际项目名称作为atrifactid的前缀。比如:Spring-bean,Spring-webmvc等。
version
该元素定义Maven项目当前所处的版本。
采用依赖管理的好处是能够大大减少我们对jar包下载和管理的难度。比如项目当中如果有100个jar包,难道我们需要从网上下载这100个jar包吗?显然如果利用maven提供给我们的坐标,就可以很快完成项目的构建。
1.4.2 多模块构建
我们在写项目的时候往往需要将 dao service controller 层分离讲一个项目分解为多个模块已经是一种通用的方式。
1.4.3 一致的项目结构
我们当初在eclipse上边写的项目如果导入到idea上边,那么就会出现很多奇奇怪怪的问题,同理,将idea上边的项目导入到eclipse当中也是一样。究其原因是因为我们在这两个编译器上的项目的目录结构是不一致的。而maven在设计之初的理念就是Conversion over configuration (约定大于配置)。其制定了一套项目目录结构作为标准的java项目结构,解决不同的ida带来文件目录不一致的问题。
1.4.4 一致的构建模型和插件机制
这一个项目当中我们往往会引入很多插件,比如tomcat服务器或者jetty(嵌入式服务器),为了实现项目组内插件的统一,maven提供了一套机制来包证这要机制的施行。
org.eclipse.jetty
jetty-maven-plugin
9.2.8.v20150217
80
shutdown
9966
2.maven的安装配置
2.1 Maven的安装配置
2.1.1检测jdk的版本
jdk版本1.7及以上版本
2.1.2下载maven
apache-maven-3.6.2-bin.tar.gz
2.1.3配置maven环境变量
解压后把maven的根目录配置到下同环境变量中Maven_HOME,将bin目录配置到path变量中。
注:maven解压后存放的目录不要包含中文和空格。
编辑环境变量 :
变量名:MAVEN_HOME
变量值:自己的安装目录
编辑系统变量 Path
添加变量值:%MAVEN_HOME%\bin
检验是否安装成功
转存失败重新上传取消
2.2 认识maven的目录结构
Maven项目目录结构
maven的目录结构在所有的编译器下边都是能够运行的
转存失败重新上传取消
任务:手动创建一个maven项目,并编译运行成功。
2.2.1 创建一个文件夹作为项目的根目录
1.创建如下结构的目录
转存失败重新上传取消
2.在pom.xml文件中写入如下内容(不用记忆)
4.0.0
com.qcby
maven
1.0-SNAPSHOT
war
8
8
junit
junit
4.12
test
使用name标签声明是一个对用户更友好的项目名称,虽然不是必须的,但是还是推荐为每个pom声明name,以方便信息的交流。
3.在mian-->java--》下边创建java文件
转存失败重新上传取消
4.cmd下编译并运行
1.修改默认仓库位置
打开maven目录 -> conf -> settings.xml
D:\maven
转存失败重新上传取消
2.更换阿里镜像,加快依赖下载
转存失败重新上传取消
alimaven
aliyun maven
http://maven.aliyun.com/nexus/content/groups/public/
central
1.编译java文件
cmd下面,进入项目的根目录(需要使用管理员权限)
mvn compile
2.执行main方法
mvn exec:java -Dexec.mainClass="com.qcby.Hello"
这里如果转存失败重新上传取消
1.不是使用管理员执行dos命名
2.JDK环境变量配置有问题,重新配置jdk
3.编写代码时,类里边有代码出现
3.IDEA编译器集成Maven环境
选择:“File” ---> "Othoer Setting" --> "Settings for New Projects..." --->搜索“Maven”
4.Maven项目的创建
4.1创建java项目
4.1.1 新建项目
创建resources目录
利用maven命令去编译这个项目
利用maven命令去打包
4.2创建web项目
4.2.1 新建项目
新建web项目和创建java项目基本一致,区别在于选择Maven模板(web项目选择webapp),如图
4.2.2 启动项目
4.2.2.1 修改jdk的版本
UTF-8
1.8
1.8
4.2.2.2 设置单元测试的版本
junit
junit
4.12
test
4.2.2.3 删除pluginManagement标签
.....
4.2.2.4添加web部署插件
在build标签中添加plugins标签
1.Jetty插件
org.eclipse.jetty
jetty-maven-plugin
9.2.11.v20150529
10
/test
9090
2.Tomcat插件
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/mavenWeb
4.2.2.5 启动项目
点击右上角的 “Add Configurations”,打开“Run/Dedug Configurations”窗口
1.jetty启动
访问路径
http://localhost:9090/test/index.jsp
2.tomcat启动
访问路径
http://localhost/mavenWeb/index.jsp
5.Maven仓库的基本概念
当第一次运行Maven命令的时候, 你需要Internet链接, 因为它需要从网上下载一些文件。 那么它从哪里下载呢?它是从Maven默认的远程库下载的。 这个远程仓库有Maven的核心插件和可供下载的jar文件。
当Maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在,则直接使用; 如果本地没有,Maven就会去远程仓库查找,发现需要的构件之后,下载到本地仓库再使用。 如果本地仓库和远程仓库都没有,Maven就会报错。
远程仓库分为三种: 中央仓库,私服, 其他公共库。
中央仓库是默认配置下,Maven下载jar包的地方。
私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的仓库服务器,用其代理所有外部的远程仓库。 内部的项目还能部署到私服上供其他项目使用。
一般来说,在Maven项目目录下,没有诸如lib/这样用来存放依赖文件的目录。 当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下, 每个用户在自己的用户目录下都有一个路径名为.m2/repository/的仓库目录。 有时候,因为某些原因(比如c盘空间不足),需要修改本地仓库目录地址。
对于仓库路径的修改,可以通过maven 配置文件conf 目录下settings.xml来指定仓库路径
D:/m2/repository
5.1 中央仓库
由于原始的本地仓库是空的,maven必须知道至少一个可用的远程仓库,才能执行maven命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库。
maven-model-builder-3.3.9.jar maven自动的 jar 中包含了一个 超级POM。定义了默认中央仓库的位置。 中央仓库包含了2000多个开源项目,接收每天1亿次以上的访问。
5.2 私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务, 私服代理广域网上的远程仓库,供局域网内的maven用户使用。 当maven需要下载构件时, 它去私服当中找,如果私服没有, 则从外部远程仓库下载,并缓存在私服上, 再为maven提供。
此外,一些无法从外部仓库下载的构件也能从本地上传到私服提供局域网中其他人使用配置方式项目pom.xml 配置
true
public
Public Repositories
http://192.168.0.96:8081/content/groups/public/
getui-nexus
http://mvn.gt.igexin.com/nexus/content/repositories/releases/
公司内部应该建立私服:
5.3 其他公共库
常用的阿里云仓库配置
nexus-aliyun
central
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
6.Maven环境下构建多模块项目
使用maven提供的多模块构建的特征完成maven环境下多模块的项目的管理和构建
这里以四个模块为例来搭建项目,以达到通俗易懂的初衷
模块 maven_parent -- 基模块,也就是常说的parent (pom)
模块 maven_dao -- 数据库访问层,例如jdbc操作(jar)
模块 maven_service -- 项目的业务逻辑层(jar)
模块 maven_controller -- 用来接收请求,相应数据(war)
6.1创建maven_parent项目
2.创建maven_dao项目
选择项目mavenTest,右键New,选择Module
6.2 创建maven_service模块
创建maven_service模块的步骤与maven_dao模块一致
6.3 创建maven_controller模块
创建 maven_service 模块的步骤与maven_dao模块基本一致,只需要将第一步选择Maven模板设置为Web项目即可。(模板类型:maven-archetype-webapp)
模板创建完毕后,效果如下
注意:别忘了修改如下信息
6.3 设置模块之间的依赖关系
6.3.1 dao模块
1.新建文件并添加方法
6.3.2 service模块
1.添加maven_dao的依赖
添加dao的依赖
com.qcby
maven_dao
1.0-SNAPSHOT
2.在项目中添加UserService类,并添加方法
6.3.3 controller模块
1.添加maven_service模块的依赖
com.qcby
maven_service
1.0-SNAPSHOT
2.添加对servlet的依赖
javax.servlet
javax.servlet-api
3.1.0
provided
3.新建java类,继承HttpServlet,重写service方法
4.添加Tomcat插件
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/mavenWeb
5.启动
启动顺序:
父类:mavenTest----->install
子类:dao------------>install
子类:service------->install
子类:controller------>install
最后:启动tomcat
最后访问:
http://localhost/mavenWeb/user
7.Maven打包操作
对于企业级项目,无论是进行本地测试,还是测试环境测试以及最终的项目上线,都会涉及项目的打
包操作。对于每个环境下的项目打包,对应的项目所需要的配置资源都会有所区别,实现打包的方式有
很多种,可以通过ant,或者通过idea 自带的打包功能实现项目打包,但当项目很大并且需要的外界配
置很多时,此时打包的配置就会异常复杂,对于maven 项目,我们可以用过 pom.xml 配置的方式来实
现打包时的环境选择,相比较其他形式打包工具,通过maven 只需要通过简单的配置,就可以轻松完
成不同环境下项目的整体打包。
使用idea创建项目,目录结构可能会缺失,需要通过手动添加对应的目录结构
1.首先创建maven的web项目
清空和修改pom文件
2. 添加 Java 源文件夹
选择项目的 main 文件夹,右键选择New,选择Directory
3. 添加资源文件夹
步骤如上,创建文件夹,命名为 resources
4. 添加对应的文件夹目录,及添加不同环境下对应的配置文件。(本地环境、测试环境、正式环境)
5. 在pom文件当中添加打包环境
dev
dev
true
test
test
product
product
6.设置资源文件配置
src/main/resources/${env}
src/main/java
**/*.xml
**/*.properties
**/*.tld
false
7.打包
8.Maven依赖的基本概念
8.1:依赖的基本配置
根元素project下的dependencies可以包含多个 dependence元素,以声明多个依赖。每个依赖都应
该包含以下元素:
1. groupId, artifactId, version : 依赖的基本坐标, 对于任何一个依赖来说,基本坐标是最重要的,
Maven根据坐标才能找到需要的依赖。
2. Type: 依赖的类型,大部分情况下不需要声明。 默认值为jar
3. Scope: 依赖范围(compile,test,provided,runtime,system)
compile: 编译依赖范围。
如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测
试、运行三种classpath都有效。
test: 测试依赖范围。
使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使
用时将无法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候
才需要。
provided: 已提供依赖范围。
使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例
子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经
提供,就不需要Maven重复地引入一遍(如:servlet-api)。
runtime: 运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典
型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试
或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
system: 系统依赖范围。
该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依
赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓
库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。
4. Optional:标记依赖是否可选
5. Exclusions: 用来排除传递性依赖。
8.2 依赖范围
首先需要知道,Maven在编译项目主代码的时候需要使用一套classpath。 比如:编译项目代码的时
候需要用到spring-core, 该文件以依赖的方式被引入到classpath中。 其次, Maven在执行测试的时候
会使用另外一套classpath。 如:junit。
最后在实际运行项目时,又会使用一套classpath, spring-core需要在该classpath中,而junit不需
要。
那么依赖范围就是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行时
classpath)的关系, Maven有以下几种依赖范围:
Compile 编译依赖范围。 如果没有指定,就会默认使用该依赖范围。 使用此依赖范围的Maven依
赖, 对于编译,测试,运行都有效。
Test: 测试依赖范围。 只在测试的时候需要。比如junit
Provided: 已提供依赖范围。 使用此依赖范围的Maven依赖,对于编译和测试有效, 但在运行
时无效。 典型的例子是servlet-API, 编译和测试项目的需要, 但在运行项目时, 由于容器已经提
供, 就不需要Maven重复地引入一遍。
Runtime: 运行时依赖范围。 使用此依赖范围的Maven依赖,对于测试和运行有效, 但在编译代
码时无效。 典型的例子是:jdbc驱动程序, 项目主代码的编译只需要jdk提供的jdbc接口,只有在
执行测试或者运行项目的时候才需要实现上述接口的具体jdbc驱动。
System: 系统依赖范围。 一般不使用。
8.3 传递性依赖
传递依赖机制, 让我们在使用某个jar的时候就不用去考虑它依赖了什么。也不用担心引入多余的依
赖。 Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前项
目中。
注意: 传递依赖有可能产生冲突!!
冲突场景:
如果A下同时存在两个不同version的C,冲突!!(选取同时适合A、B的版本)
A
A
xxx
C
C
B
B
这里的
C
C
来排除冲突的