一、让 Web 工程依赖 Java 工程

1、观念

明确一个意识:从来只有 Web 工程依赖 Java 工程,没有反过来 Java 工程依赖 Web 工程。本质上来说,Web 工程依赖的 Java 工程其实就是 Web 工程里导入的 jar 包。最终 Java 工程会变成 jar 包,放在 Web 工程的 WEB-INF/lib 目录下。

2、操作

在 pro02-maven-web 工程的 pom.xml 中,找到 dependencies 标签,在 dependencies 标签中做如下配置:

1
2
3
4
5
6
7
<!-- 在当前Web工程中配置对上一个Java工程的依赖,即配置对Java工程pro01-maven-java的依赖 -->
<!-- 具体的配置方式:配置被依赖的Java工程pro01-maven-java的坐标 -->
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

3、在 Web 工程中,编写测试代码

① 创建补充目录

pro02-maven-wb\src\test\java\com\atguigu\maven

② 确认 Web 工程依赖了 junit

1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

③ 创建测试类

把 Java 工程 pro01-atguigu-maven 的 CalculatorTest.java 类复制到 pro02-maven-wb\src\test\java\com\atguigu\maven目录下

4、执行 Maven 命令

① 测试命令

mvn test

说明:测试操作中会提前自动执行编译操作,测试成功就说明编译也是成功的。

② 打包命令

mvn package

images

通过查看 war 包内的结构,我们看到被 Web 工程依赖的 Java 工程确实是会变成 Web 工程的 WEB-INF/lib 目录下的 jar 包。

images

③ 查看当前 Web 工程所依赖的 jar 包的列表

1
mvn dependency:list

[INFO] The following files have been resolved:
[INFO] junit:junit:jar:4.11:test
[INFO] javax.servlet:javax.servlet-api:jar:4.0.1:provided
[INFO] org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile

说明:javax.servlet:javax.servlet-api:jar:4.0.1:provided 格式显示的是一个 jar 包的坐标信息。格式是:

​ groupId : artifactId : 打包方式 : version : 依赖的范围

这样的格式虽然和我们 XML 配置文件中坐标的格式不同,但是本质上还是坐标信息,大家需要能够认识这样的格式,将来从 Maven 命令的日志或错误信息中看到这样格式的信息,就能够识别出来这是坐标。进而根据坐标到 Maven 仓库找到对应的 jar 包,用这样的方式解决我们遇到的报错的情况。

④ 以树形结构查看当前 Web 工程的依赖信息

1
mvn dependency:tree

[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.1:provided
[INFO] - com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile

我们在 pom.xml 中并没有依赖 hamcrest-core,但是它却被加入了我们依赖的列表。原因是:junit 依赖了 hamcrest-core,然后基于依赖的传递性,hamcrest-core 被传递到我们的工程了。

二、测试依赖的范围

1、依赖范围

标签的位置:dependencies/dependency/scope

标签的可选值:compile/test/provided

①compile 和 test 对比

main 目录(空间)test 目录(空间)开发过程(时间)部署到服务器(时间)
compile有效有效有效有效
test无效有效有效无效

②compile 和 provided 对比

main 目录(空间)test 目录(空间)开发过程(时间)部署到服务器(时间)
compile有效有效有效有效
provided有效有效有效无效

③ 结论

compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需 jar 包。

test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。

provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”

2、测试

① 验证 test 范围对 main 目录无效

测试方式:在主体程序中导入 org.junit.Test 这个注解,然后执行编译。

具体操作:在 pro01-maven-java\src\main\java\com\atguigu\maven 目录下修改 Calculator.java

1
2
3
4
5
6
7
8
9
package com.atguigu.maven;

import org.junit.Test;

public class Calculator {
public int sum(int i, int j){
return i + j;
}
}

执行 Maven 编译命令:

1
2
Compilation failure
[ERROR] /D:/My/maven-workspace/space/pro01-maven-java/src/main/java/com/atguigu/maven/Calculator.java:[3,17] 程序包org.junit不存在

② 验证 test 和 provided 范围不参与服务器部署

其实就是验证:通过 compile 范围依赖的 jar 包会放入 war 包,通过 test 范围依赖的 jar 包不会放入 war 包。

images

③ 验证 provided 范围对测试程序有效

测试方式是在 pro02-maven-web 的测试程序中加入servlet-api.jar包中的类。

修改:pro02-maven-web\src\test\java\com\atguigu\maven\CalculatorTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.atguigu.maven;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import org.junit.Test;
import com.atguigu.maven.Calculator;

// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;

public class CalculatorTest{

@Test
public void testSum(){

// 1.创建Calculator对象
Calculator calculator = new Calculator();

// 2.调用Calculator对象的方法,获取到程序运行实际的结果
int actualResult = calculator.sum(5, 3);

// 3.声明一个变量,表示程序运行期待的结果
int expectedResult = 8;

// 4.使用断言来判断实际结果和期待结果是否一致
// 如果一致:测试通过,不会抛出异常
// 如果不一致:抛出异常,测试失败
assertEquals(expectedResult, actualResult);

}
}

然后运行 Maven 的编译命令:mvn compile

然后看到编译成功。

三、测试依赖的传递性

1、依赖的传递性

① 概念

A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面是不是可以直接使用 C。

② 传递的原则

在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A 取决于 B 依赖 C 时使用的依赖范围。

  • B 依赖 C 时使用 compile 范围:可以传递
  • B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。

2、使用 compile 范围依赖 spring-core

① 测试方式 1

让 pro01-maven-java 工程依赖 spring-core

具体操作:编辑 pro01-maven-java 工程根目录下 pom.xml

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

使用命令

1
mvn dependency:tree

查看效果:

[INFO] com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] - commons-logging:commons-logging:jar:1.1.1:compile

② 测试方式 2

还可以在 Web 工程 pro02-maven-web 中使用命令

1
mvn dependency:tree

查看效果(需要重新将 pro01-maven-java 安装到仓库 mvn install ):

[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.1:provided
[INFO] - com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] - commons-logging:commons-logging:jar:1.1.1:compile

3、验证 test 和 provided 范围不能传递

从上面的例子已经能够看到,pro01-maven-java 依赖了 junit,但是在 pro02-maven-web 工程中查看依赖树的时候并没有看到 junit。

要验证 provided 范围不能传递,可以在 pro01-maven-java 工程中加入 servlet-api 的依赖。

1
2
3
4
5
6
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

效果还是和之前一样:

[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.1:provided
[INFO] - com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] - commons-logging:commons-logging:jar:1.1.1:compile

四、测试依赖的排除

1、概念

当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,但是 A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。

images

所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 jar 包冲突。

2、配置方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

3、测试

测试的方式:在 pro02-maven-web 工程中配置对 commons-logging 的排除

运行命令

1
mvn dependency:tree

查看效果:

[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.1:provided
[INFO] - com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile

发现在 spring-core 下面就没有 commons-logging 了。