1. 项目构建过程

构建过程的几个主要环节
-
清理:删除以前的编译结果,为重新编译做好准备。
-
编译:将Java源程序编译为字节码文件。
-
测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
-
报告:在每一次测试后以标准的格式记录和展示测试结果。
-
打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web 工程对应war包。
-
安装:在Maven环境下特指将jar包安装到本地仓库中。这样该项目就可以被其他的maven项目通过依赖的方式引入。
-
部署:将jar包部署到私服上。
Maven的两大核心功能(重点)
项目构建
对项目进行编译,测试,打包,部署等构建。
依赖管理
对jar包的统一管理,Maven提供中央仓库,私服,本地仓库解决jar包的依赖和相关依赖的下载。如下图所示:包括蓝、黄两个部分分别对应着依赖关系和 项目构建两大核心功能。

Maven的核心概念
什么是POM
POM(Project Object Model)项目对象模型,它是Maven的核心组件。它是Maven中的基本工作单元。它是一个xml文件,以pom.xml驻留在项目的根目录中。POM不仅包含有关项目的信息及Maven用于构建项目的各种配置的详细信息,还包含目标和插件。
什么是约定的目录结构
预先约定好的目录结构,必须要遵循的规范,所有的Maven项目都依照这个规范。主要的目的是将项目的源码文件,测试代码,资源文件完全分开,便于项目管理和扩展。

什么是坐标GAV
gav定位。使用三个标签来唯一定位jar资源。项目的唯一的名称,创建项目时定义gav名称,引用项目时使用gav名称。相当于项目的身份证号。
groupId: 组织名称,一般是公司域名的倒写 com.bjpowernode
artifactId:项目名称 springmvc_006_ssm
version: 版本编号 1.0-SNAPSHOT(开发时的临时版本号) 5.2.5.RELEASE(发布版本)
什么是仓库
存放jar包的位置 。Maven中所有的jar包都在仓库中。仓库分为本地仓库和远程仓库。
依赖的jar包它从哪儿获取呢?maven有仓库的概念。**在Maven中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。**Maven 核心程序仅仅定义了自动化构建项目的生命周期,但具体的构建工作是由特定的构件完成的。而且为了提高构建的效率和构件复用,maven把所有的构件统一存储在某一个位置,这个位置就叫做仓库。
本地仓库:路径中不要有中文;
本地仓库
本地仓库,存在于当前电脑上,默认存放在~.m2\repository中,为本机上所有的Maven工程服务。你也可以通过Maven的配置文件Maven_home/conf/settings.xml中修改本地仓库所在的目录。~ 是用户的主目录,windows系统中是 c:/user/登录系统的用户名
存放在本机上的某个磁盘的位置(一定是没有中文的路径). D:\repository
远程仓库
远程仓库,分为为全世界范围内的开发人员提供服务的中央仓库、为全世界范围内某些特定的用户提供服务的中央仓库镜像、为本公司提供服务自己架设的私服。
中央仓库是maven默认的远程仓库,其地址是:http://repo.maven.apache.org/maven2/,中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载得到。
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。还可以把一些无法从外部仓库下载到的构件上传到私服上。

程序员常用的一个仓库: http://mvnrepository.com/
什么是依赖
添加jar包
一个Maven 项目正常运行需要其它项目的支持,Maven 会根据坐标自动到本地仓库中进行查找。对于程序员自己的 Maven 项目需要进行安装,才能保存到仓库中。不用maven 的时候所有的 jar 都不是你的,需要去各个地方下载拷贝,用了 maven 所有的 jar 包都是你的,想用谁,叫谁的名字就行。maven 帮你下载。
除了管理当前要使用的jar包,并且同时管理与其有依赖关系的jar包,自动去下载,并添加到当前的仓库,并给项目添加引用。是通过<dependencies>大标签中的子标签<dependency>,使用gav添加依赖。
什么是生命周期
构建项目时按照生命周期顺序构建,每一个阶段都有特定的插件来完成。不论现在要执行生命周期中的哪个阶段,都是从这个生命周期的最初阶段开始的。
对于程序员而言,无论要进行哪个阶段的构建,直接执行相应的命令即可,无需担心它前边阶段是否构建,Maven 都会自动构建。这也就是 Maven 这种自动化构建工具给我们带来的好处。
使用idea后,生命周期要调用的命令被集成化一些按钮,只需要双击即可调用相应的插件来运行。

生命周期对应的Maven命令(了解):
-
mvn clean 清理(删除原来编译和测试的目录,即 target 目录,但是已经 install 到仓库里的包不会删除)
-
mvn compile 编译主程序(在当前目录下生成一个 target,里边存放编译主程序之后生成的字节码文件)
-
mvn test-compile 编译测试程序(在当前目录下生成一个 target,里边存放编译测试程序之后生成的字节码文件)
-
mvn test 测试(生成一个目录surefire-reports,保存测试结果)
-
mvn package 打包主程序 (首先执行编译、编译测试、测试、并且按照 pom.xml 配置把主程序打包生成 jar 包或者 war 包)
-
mvn install 安装主程序(会把本工程打包,并且按照本工程的坐标保存到本地仓库中)
-
mvn deploy 部署主程序(部署到私服仓库中)。
什么是插件
Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven- compiler-plugin的compile目标用来编译位于src/main/java/目录下的主源码,testCompile目标用来编译位于src/test/java/目录下的测试源码。
Maven支持极简化的插件添加.使用<plugins>大标签中添加<plugin>子标签引用插件.
XML
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
基于Maven开发JavaSE的项目
java
public class Hello {
//加法运算
public int sum(int num1,int num2){
return num1 + num2;
}
//乘法运算
public int mul(int num1,int num2){
return num1 * num2;
}
}
Test
java
public class MyTest {
/**
* 测试功能由测试方法来实现
* 测试方法的规范
* 1)访问权限是public
* 2)方法没有返回值void
* 3)方法名称自 定义,推荐以test开头
* 4)方法没有参数
* 5)使用@Test注解声明是测试方法
*/
@Test
public void testSum(){
Hello hello = new Hello();
System.out.println(hello.sum(3,6));
}
@Test
public void testMul(){
Hello hello = new Hello();
System.out.println(hello.mul(3,6));
}
}
基于Maven开发JavaWeb的项目
java
@WebServlet("/demo")
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("服务器被访问到了..........");
req.getRequestDispatcher("/main.jsp").forward(req, resp);
}
}
index.jsp
java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<br><br>
<a href="/demo">访问服务器</a>
</body>
</html>
main.jsp
java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>main........................</h2>
</body>
</html>
JSP:
1.直接写HTML代码,就像在普通HTML文件中一样。
2.嵌入Java代码,使用<% %>脚本片段,或者使用JSP标签(如<jsp:useBean>)和EL表达式(${})来更优雅地集成Java代码。
3.使用JSP指令(如<%@ page %>)设置页面属性,比如 contentType 和 language。
4.使用JSP声明(<%! %>)声明成员变量和方法。
5.使用JSP表达式(<%= %>)将Java表达式的值输出到HTML中。
Maven的依赖管理
在JAVA开发中,项目的依赖管理是一项重要任务。通过合理管理项目的依赖关系,我们可以有效的管理第三方库,模块的引用及版本控制。
什么是依赖范围
Maven的依赖构件包含一个依赖范围的属性。这个属性描述的是三套classpath的控制,即编译、测试、运行。这说白了就是添加的jar包起作用的范围。 maven提供了以下几种依赖范围:compile,test,provided.runtime,system。分别介绍如下:
1. compile
编译依赖范围,如果没有指定,默认使用该依赖范围,对于 编译、测试、运行3种classpath都有效。
2. test
测试依赖范围,使用此依赖范围的maven依赖,只对 编译、测试、运行测试的classpath有效,在编译主代码、运行项目时无法使用此类依赖。比如junit,它只有在编译测试代码及运行测试的时候才需要。
3. provided
已提供依赖范围。表示项目的运行环境中已经提供了所需要的构件,对于此依赖范围的maven依赖,对于 编译源码、编译测试、运行测试中classpath有效,但在运行时无效。比如上面说到的servlet-api,这个在编译和测试的时候需要用到,但是在运行的时候,web容器已经提供了,就不需要maven帮忙引入了。
4. runtime
运行时依赖范围,使用此依赖范围的maven依赖,对于 测试和运行 项目的classpath有效,但在编译时无效,比如jdbc驱动实现,项目代码编译的时候只需要提供JDK提供的JDBC接口,运行的时候才需要具体的jdbc驱动实现。
5. system
系统依赖范围,该依赖与3中classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显示第指定依赖文件的路径。这种依赖直接依赖于本地路径中的构件(jar包),可能每个开发者机器中构件的路径不一致,所以如果使用这种写法,机器中可能没有问题,别人的机器中就会有问题,所以建议谨慎使用。

依赖传递
依赖具有传递性。 Maven 的依赖传递机制是指:不管 Maven 项目存在多少间接依赖,POM 中都只需要定义其直接依赖,不必定义任何间接依赖,这在一定程序上简化 了POM 的配置。
假设项目A依赖项目B,项目B依赖项目C,则A----->直接依赖B,B----->直接依赖C,A----->间接依赖C。直接依赖和间接依赖是一个相对的概念。直接在项目中配置的依赖称为直接依赖,通过添加依赖关联进来的依赖称为间接依赖。1是项目的直接依赖,2是1的直接依赖,2是项目的间接依赖,以此类推。如图

依赖范围对依赖传递的影响
B 是 A 的直接依赖,C 是 A 的间接依赖,根据 Maven 的依赖传递机制,间接依赖 C 会以传递性依赖的形式引入到 A 中,但这种引入并不是无条件的,它会受到依赖范围的影响。

行指的是直接依赖,列指的是间接依赖(表格里的内容就是laoda看到时的状态)
| | compile | test | provided | runtime |
| compile | compile | 0 | 0 | runtime |
| test | test | 0 | 0 | test |
| provided | provided | 0 | 0 | provided |
runtime | runtime | 0 | 0 | runtime |
---|
-
当间接依赖的范围是 compile 时,与直接依赖的范围一致;
-
当间接依赖的范围是 test 或 provided 时,传递性依赖不会被传递;因为打包之后本来就不存在子依赖中,所以更不会出现在父依赖中;
-
当间接依赖的范围是 runtime 时,传递性依赖的范围与直接依赖的范围一致,但 compile 例外,此时传递性依赖的范围为 runtime。
XML
<groupId>com.hnlg</groupId>
<artifactId>maven_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 父工程的打包方式,此工程不能运行,只是用来规范和定义的 -->
<packaging>pom</packaging>
<modules>
<module>maven_son</module>
</modules>
<!-- dependencyManagement标签只是用来定义,并没有真正的添加依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
子工程依赖
XML
<parent>
<groupId>com.hnlg</groupId>
<artifactId>maven_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>maven_son</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>