1.一个项目就是一个工程
如果项目非常庞大,就不适合继续使用package来划分模块。最好是每一个模块对应一个项目,利用分工协作。借助于Maven就可以将一个项目拆分成多个工程。
2.项目中需要的jar包必须手动“复制”,“粘贴”到WEB-INF/lib项目下
同样的jar包文件重复出现在不同的项目工程中,一方面是浪费存储空间,另外也让工程比较臃肿。借助Maven,可以将jar包仅仅保存在仓库中,有需要使用的工程“引用”这个文件,并不需要重复复制。
3.jar包需要别人帮我们准备好,或到官网下载
所有知名框架或第三方工具jar包已经按照统一规范放在Maven的中央仓库中。
4.一个jar包依赖的其他jar包需要自己手动加到项目中
Maven会自动将被依赖的jar包导入进来。
Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平台的项目构建和依赖管理 。
构建:就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、jsp页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
构建过程中的几个主要环节
①清理:删除以前的编译结果,为重新编译做好准备。
②编译:将Java源程序编译为字节码文件。
③测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
④报告:将每一次测试后以标准的格式记录和展示测试结果。
⑤打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对象war包。
⑥安装:在Maven环境下特指将打包的结果——Jar包或War包安装到本地仓库中。
⑦部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。
1.检查JAVA_HOME环境变量
2.解压Maven核心程序的压缩包,放在一个非中文、无空格 的路径下。
3.配置Maven相关的环境变量
①MAVEN_HOME 或 M2_HOME
②path
4.验证:运行 mvn -v 命令查看Maven版本
Maven的核心程序中仅仅定义了抽象的生命周期,而具体操作则是由Maven的插件来完成的,可以Maven的插件并不包含在Maven的核心程序中,首次使用需要联网下载。
下载得到的插件会被保存在本地仓库中,本地仓库的默认位置是:~\.m2\repositoy。
约定的目录结构对于Maven实现自动化构建是必不可少的一个环节,就拿自动编译来说,Maven必须找到java 源文件,下一步才能编译,而编译之后也必须有一个准确的位置保持编译得到的字节码文件。
我们在开发中如果需要让第三方工具或框架知道我们创建的资源在哪,那么基本就是两种方式
1)以配置的方式明确告诉框架,如:
< param-value>classpath:spring-context.xml < /param-value>
2)遵守框架内部已经存在的约定,如如log4j的配置文件名规定必须为 log4j.properties 或 log4j.xml 。
注意:约定>配置>编码
Maven对工程目录结构的要求就是属于后面一种。
执行与构建过程相关的Maven命令,必须进入pom.xml 所在的目录。
有构建过程相关:编译,测试,打包....
常用的命令:
Maven命令会有关联网问题:
Project Object Model:项目对象模型。将Java工程的相关信息封装为对象作为便于操作和管理的模型。
pom.xml 对于 Maven工程是核心配置文件,与构建过程相关的一切设置都在这个文件中进行配置。可以说学习Maven就是学习pom。xml文件中的配置。
为各种使用下面三个向量在仓库中唯一定位一个Maven工程:
(1)groupid:公司或组织域名倒序+项目名
/groupid>
(2)artifactid:模块名
< artifactid>Hello< /artifactid>
(3)version:版本
< version>1.0.0< /version>
Maven 工程的坐标与仓库中路径的对应关系,以spring为例:
< groupId>org.springframework< /groupId>
< artifactId>spring-core< /artifactId>
< version>4.0.0.RELEASE< /version>
org/springframework/spring-core/4.0.0.RELEASE/spring-core-4.0.0.RELEASE.jar
注意:我们自己的 Maven 工程必须执行安装操作才会进入仓库。安装的命令是:mvn install
仓库的分类:
(1)本地仓库:当前电脑部署的仓库目录,为当前电脑上的所有Maven工程服务
(2)远程仓库:
①私服:搭建在局域网环境中,为局域网范围内的所有Maven工程服务
②中央仓库:假设在Internet上,为全世界所有Maven工程服务
③中央仓库镜像:为了分担中央仓库的流量,提升用户访问速度
仓库中保存的内容:Maven工程
(1)Maven自身所需要的插件
(2)第三方框架或工具的jar包
(3)我们自己开发的Maven工程
不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。
我们分别创建两个Maven项目,分别是Hello和HelloFriend。在HelloFriend的类中调用了Hello的类:
package com.lianxi.maven;
import com.lianxi.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";
}
}
在HelloFriend的pom.xml配置文件中有对Hello的依赖:
com.lianxi.maven
Hello
0.0.1-SNAPSHOT
compile
尝试对HelloFriend进行编译,会发现编译失败。
当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖,这是概念上的描述。Maven解析依赖信息时会到仓库中查找被依赖的jar包。对于我们自己开发的Maven工程,要使用mvn install 命令安装后就可以进入仓库。
所以对Hello要先执行mvn install命令,然后再编译HelloFriend,就可以执行成功了。
根元素project下的dependencies可以包含多个dependency元素,以声明一个或多个项目依赖,每个依赖可以包含的元素有:
首先需要知道,Maven在编译项目主代码的时候需要一套classpath。其次,Maven在编译和执行测试的时候会使用另一套的classpath。最后,实际运行Maven项目的时候,又会使用一套classpath。
依赖范围就是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行classpath)的关系,Maven有以下几种依赖范围:
以下是一个简单的表格(Y代表有效,N代表无效);
依赖范围(scope) | 对于编译classpath有效 | 对于测试classpath有效 | 对于运行classpath有效 |
典型例子 |
compile | Y | Y | Y | spring-core |
test | N | Y | N | Junit |
provided | Y | Y | N | servlet-api |
runtime | N | Y | Y | JDBC驱动实现 |
system | Y | Y | N | 本地的,Maven仓库以外的类库文件 |
A依赖B,B依赖C,A能否使用C呢?那要看B依赖C的范围是不是compile,如果是则可用,否则不可用。
Maven工程 | 依赖范围 | 对A的可见性 | ||
A | B | C | compile | Y |
D | test | N | ||
E | provided | N |
如果我们当前工程中引入了一个依赖是A,而A又依赖了B,那么Maven会自动将A依赖的B引入当前工程,但是个别情况下B有可能是一个不稳定版本,或对当前工程有不良影响。这时我们可以在引入A的时候将B排除。
情景背景:
配置方式:使用了上面提到的exclusion元素
com.atguigu.maven
HelloFriend
0.0.1-SNAPSHOT
jar
compile
< exclusion>
commons-logging
commons-logging
exclusion>
依赖的原则就是为了解决jar包冲突。
这里“声明”的先后顺序指的是 dependency 标签配置的先后顺序。
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提取出来。
(1)统一声明版本号
<自定义标签>4.1.1.RELEASE自定义标签>
(2)引用前面声明的版本号
org.springframework
spring-core
${自定义标签名称}
……
(3)其他用法
UTF-8
Maven生命周期定义了各个构建环节的执行顺序,有了这个顺序,Maven就可以自动化的执行构建命令了。Maven声明周期有以下特点:
Maven有三套相互独立的生命周期,分别是:
它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然你可以直接运行 mvc clean install site运行所有这三套生命周期。
每套生命周期都是由一组阶段组成的,我们平时在命令行输入的命令总是会对应于一个特定的阶段。比如,运行mvn clean,这个clean是Clean生命周期中的一个阶段,有了Clean生命周期,也会有clean阶段。
Clean生命周期一共包含了三个阶段:
Default生命周期是Maven生命周期中最重要的一个,绝大部分的工作都发生在这个生命周期中,现在,只解释一些比较重要和常用的阶段:
现在有三个Maven项目,MakeFriends依赖Hello和HelloFriend,HelloFriend依赖Hello。由于非 compile 范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置。例如:
Hello | |
HelloFriend | |
MakeFriends |
此时如果项目需要将各个模块的junit版本统一为4.9,那么到各个工程中手动修改无疑是非常不可取的。 使用继承机制就可以将这样的依赖信息统一提取到父工程模块中进行统一管理。
将Junit依赖统一提取到“父”工程中,在子工程中声明Junit依赖是不指定版本,以父工程中统一设定的为准。同时也便于修改。
操作步骤如下:
(1)创建一个Maven工程作为父工程。注意:打包方式为pom。(创建父工程和创建一般的 Java 工程操作一致,唯一需要注意的是:打包方式处要设置为 pom。)
(2)在子工程中声明对父工程的引用
...
...
...
从当前目录到父项目的 pom.xml 文件的相对路径
(3)将子工程的坐标中与父工程坐标中重复的内容删除(例如相同的groupId等)
(4)在父工程中统一管理Junit的依赖,将 Parent 项目中的 dependencies 标签,用 dependencyManagement 标签括起来
junit
junit
4.9
test
(5)在子项目中重新指定需要的依赖,删除范围和版本号
junit
junit
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进 行 clean 操作。而使用了聚合之后就可以批量进行 Maven 工程的安装、清理工作。
在总的聚合工程中使用 modules/module 标签组合,指定模块工程的相对路径即可。
../Hello
../HelloFriend
../MakeFriends
注意,这个甚至打乱顺序都可以执行成功
Maven插件Eclipse已经内置。
Maven插件的设置: Window->Preferences->Maven
①installations : 指定Maven核心程序的位置。默认是插件自带的Maven程序,改为我们自己解压的那个。
②user settings : 指定Maven核心程序中 conf/settings.xml 文件的位置,进而获取本地仓库的位置。
基本操作
(1)创建Maven版的Java工程
① 创建时勾选上 Create a simple project(skip archetype selection)
创建的Maven工程默认使用的是JDK1.5,打开Maven核心程序settings.xml文件,找到profiles标签,加入如下配置,即可更改(或者在这个工程下Build Path修改)
jdk-1.7
true
1.7
1.7
1.7
1.7
(2)创建Maven版的Web工程
① 创建时勾选上 Create a simple project(skip archetype selection)
② Packing选择war
③调整web目录结构,在项目上点右键 -> properties->Project Facets -> 把Dynamic Web Module 勾选去掉,并Apply -> 将Dynamic Web Module 重新勾选 -> 点击Further configuration available -> 修改 Content directory为src/main/webapp -> Apply 即在Maven工程上生成动态Web目录结构。目录结构如下:
④新建jsp文件发现报错:The superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path/。因为缺少Tomcat 运行时环境,有两种解决方法:
a.以Maven方式添加:在pom.xml文件中添加
javax.servlet
servlet-api
2.5
provided
b.将Tomcat配置的Server直接引入这个工程。
⑤jsp写入EL表达式时发现报错:javax.servlet.jsp cannot be resolved to a type。解决方法:将JSPAPI导入,在pom.xml文件中添加
javax.servlet.jsp
jsp-api
2.1.3-b06
provided
注意:scope一定要是provided,不然jar包冲突,运行时会报空指针异常
(3)执行Maven命令:选中pom.xml 右键 Run As->Maven build…->Goals->输入 compile ->点击 run
本篇文章是尚硅谷Maven的视频的学习笔记,还参考了《Maven实战》