Maven教程–下(包括手动实现)
前言
注意本篇是需要一定的maven基础的 如果没有请移步Maven教程–上
手动创建Maven 项目- 理解Maven 底层机制
需求说明/图解
用手工的方式,创建maven 项目, 深刻理解Maven 工作机制
完成功能-说明
- 编写一个类, 有一个方法sum,可以返回两个数的和
- 编写测试类TestSum, 可以测试sum 是否正确.
- 使用指令完成Maven 的编译(complile)、测试(test)、打包(package)、安装(install)、清理(clean)等操作
手写方式
完成代码编写
- 先根据maven 项目的结构要求,在d 盘: 创建项目结构(如图)
- 创建\Hello.java ,说明: 这个文件可以手写, 也可以从快速入门项目拷贝一份.
public class Hello {
public String sum(int n1, int n2) {
System.out.println("sum= " + (n1 + n2));
return "sum= " + (n1 + n2);
}
}
- 创建HelloTest.java,说明: 这个文件可以手写, 也可以从快速入门项目拷贝一份, 同时注意这个文件是在src\test… 下的…
public class HelloTest {
@Test
public void testSum() {
Hello hello = new Hello();
String res = hello.sum(1, 9);
//使用断言
/**
* 1.Assert 是一个断言类,(就是判断实际返回的值和期望值是否相同)
* 2.如果res 和 "sum=10" 是相同的,则通过断言
* 3.如果res 和 "sum=10" 是不相同的,则给出提示
*
*/
Assert.assertEquals("sum=10", res);
}
- 创建pom.xml, 从快速入门项目拷贝一份即可. 放在和src 同级目录即可, 提示:使用记事本来保存, 保证该文件的编码是utf-8
<!--
解读:modelVersion
1. 描述这个pom文件/pom模型遵循的哪个版本
2. 对应maven2 和 maven3 而言, 这里的modelVersion只能是4.0.0
-->
<modelVersion>4.0.0</modelVersion>
<!--
解读: 下面是指定该项目的坐标, 是创建项目时,程序员指定
1. groupId: 组织名
2. artifactId: 项目名
3. version: 版本
-->
<groupId>com.wedu</groupId>
<artifactId>java-project-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
解读
1. 这里就是引入项目需要的jar包, 类似传统项目的import jar的作用
2. 在 dependencies标签内, 可以指定多个需要依赖的jar /导入jar
3. 引入的jar包需要一个完整的jar包坐标, 从mvn仓库查询得到
-->
<dependencies>
<dependency>
<!-- 依赖jar的 groupId : 组织名-->
<groupId>junit</groupId>
<!-- 依赖jar的 artifactId : 项目名-->
<artifactId>junit</artifactId>
<!-- 依赖jar的 version : 版本-->
<version>4.12</version>
</dependency>
完成编译
- 执行如下指令,完成maven 项目的编译,会得到源代码对应的class 文件(如图)
- 编程成功,会自动创建target 目录,并生成对应的.class 文件(如图)
- 细节说明: 第一次速度慢,需要下载相关jar,后面就快了.
完成测试
- 执行如下指令,完成maven 项目的测试,(如图)
- 测试指令执行完毕,会生成Test 源文件的class , 还会输出测试结果.
- 细节说明: 第一次速度慢,需要完成一些初始化工作,后面就快了.
完成打包
- 执行如下指令,完成maven 项目的打包,输出jar, 可以供其它模块使用(如图)
- 打包后,在target 目录生成对应的打包文件jar
完成安装
- 为了演示方便, 把当前maven 的settings.xml 的仓库恢复到默认的, 修改D:\program\apache-maven-3.6.3-bin\apache-maven-3.6.3\conf\settings.xml
- 执行install 指令,能完成maven 项目的安装,会把打包得到的jar, 提交到本地仓库
- 说明: 如果没有修改settings.xml 成默认的仓库路径, install 后, 生成的jar 会在指定的仓库路径下.
- 注意当把hello-project-1.0.jar 提交到本地仓库后,该jar 也可以被其他maven 项目使用了,非常方便
完成清理
- 执行如下指令,完成maven 项目的清理,会清除生成的target 目录
- 应用场景,比如我们希望把源码进行拷贝或移植, 或者希望来一次全新的bulid,就可以先进行clean
小结Maven 构建指令
● 说明: Maven 构建命令使用mvn 开头,后面添加功能参数,可以一次执行多个命令,使用空格分隔
mvn compile #编译
mvn clean #清理
mvn test #测试
mvn package #打包
mvn install #安装
IDEA 创建Maven Web 工程
需求说明/图解
使用IDEA 创建Maven WEB 项目, 可以运行hello,world 页面
注意体会Maven WEB 项目和前面创建的Maven java 项目不同
创建Maven web 项目
创建maven web 工程
web-hello-maven 工程
创建成功的maven web 项目结构
创建的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">
<modelVersion>4.0.0</modelVersion>
<!--
解读
1. groupId 、artifactId、version就是 maven项目坐标
2. packaging: 打包方式,默认是jar, 因为当前是web项目,所以这里打包成war
-->
<groupId>com.wyxedu</groupId>
<artifactId>web-hello-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>web-hello-maven Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!-- maven项目的属性, 根据实际情况,可以修改 -->
<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>
</properties>
<dependencies>
<!-- 默认引入的jar -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--默认引入的maven插件, 前面说过mvn的各种指令compile/install/test等都是由插件完成的 -->
<build>
<finalName>web-hello-maven</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
配置Tomcat 服务器&运行
- 为maven web 项目配置tomcat
war:先打包成war 包,再把该war 包部署到服务器上
war exploded:直接把文件夹、class 文件等等移到Tomcat 上进行部署。因此这种方式支持热部署,一般在开发的时候都是使用这种模式
依赖管理
依赖配置
一句话: 依赖指当前项目运行需要的jar,一个项目可以设置多个依赖
依赖的举例
<!-- 解读:
1. 这里就是引入项目需要的jar 包, 类似传统的import jar 的作用
2. 在dependencies 标签内,可以指定多个需要依赖的jar/导入的jar
3. 引入的jar 包需要一个完整的jar 包坐标,从mvn 仓库查询即可得到-->
<dependencies>
<!-- 引入的一个具体的依赖jar, 包括一个完整的依赖坐标-->
<dependency>
<!-- 依赖的gruopid: 组织名-->
<groupId>junit</groupId>
<!-- 依赖的项目名-->
<artifactId>junit</artifactId>
<!-- 依赖的版本-->
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
依赖传递
直接依赖
一句话: 在当前项目中通过依赖配置建立的依赖关系
举例说明
- 创建maven_A java 项目
- 在maven_A 项目中引入mysql5.1.47 , 这时我们就说maven_A 项目直接依赖mysql5.1.47jar
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
- 如图
间接依赖
一句话: 当前项目直接依赖资源(比如m1), 而m1 又依赖资源(m2),我们就说当前项目间接依赖资源(m2)
举例说明
- 创建maven_B java 模块(为了好理解,我们放在一个项目中)
- 修改D:\java_projects\maven_B\pom.xml , 引入junit4.12
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- 修改D:\java_projects\maven_A\pom.xml , 引入maven_B
<dependencies>
<!-- 引入maven_B -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_B</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
- 观察maven_A 和maven_B 的依赖情况
依赖冲突
路径优先
- 路径优先∶当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
- 示意图说明:
- 解释项目A 依赖情况
- 如果1 度资源有junit 4.1 , 而2 度资源有junit4.2
- 根据路径优先原则, 项目A 生效的是junit4.1
- 举例说明.
- 创建maven_C(为了方便观察,仍然放在一个项目中), 创建方式和maven_B 类似,就不截图了
- 修改D:\java_projects\maven_C\pom.xml, 引入junit4.13
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
- 修改D:\java_projects\maven_B\pom.xml, 引入maven_C
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_B</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 引入maven_C -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_C</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
- 刷新工程,看看maven_A 生效的就是路径优先的maven_B 的junit4.12
- 为了验证是哪个junit 生效了, 还可以通过代码来验证, 写一段代码D:\java_projects\maven_A\src\main\java\HelloTest.java
声明优先
- 声明优先∶当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
- 示意图说明:
图解项目A 依赖情况
- 如果1 度(灰框)资源有junit 4.1 , 而1 度(蓝框)资源有junit4.2
- 根据声明优先原则, 要看项目A , 在pom.xml 引入的顺序,先引入的就是生效的
- 举例说明.
- 创建maven_D(为了方便观察,仍然放在一个项目中), 创建方式和maven_B 类似,就不截图了
- 修改D:\java_projects\maven_D\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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
</project>
- 修改D:\java_projects\maven_A\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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_A</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 引入maven_D -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入maven_B -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_B</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
- 为了验证是junit4.13.2 生效还是junit4.12 生效, 写一段代码D:\java_projects\maven_A\src\main\java\HelloTest.java
特殊优先
- 特殊优先∶当同级配置了相同资源的不同版本,后配置的覆盖先配置的(提醒:要尽量避免这种没有意义的冲突)
- 修改D:\java_projects\maven_A\pom.xml, 引入mysql5.1
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_A</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 引入maven_D -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入maven_B -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_B</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 引入mysql5.1.43 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
</dependency>
</dependencies>
</project>
- 根据特殊优先原则: maven_A 生效的是mysql5.1.43
- 测试完后,注销到引入mysql5.1.43 , 这里是为了验证.
可选依赖
一句话: 可选依赖指对外隐藏当前所依赖的资源- 不透明
举例说明
- 需求: 隐藏maven_D 项目的junit 依赖,不让其他项目来使用
- 修改D:\java_projects\maven_D\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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- 解读
1. option 默认是false , 即不隐藏
2. option 设置为true , 即隐藏-->
<optional>true</optional>
</dependency>
</dependencies>
</project>
- 刷新maven 管理器,看maven_A 的变化
- 测试完毕后,别忘了恢复原来状态.
排除依赖
一句话: 排除依赖指主动断开依赖的资源, 被排除的资源无需指定版本- 不需要
举例说明
- 需求: maven_A 项目主动排除maven_D 的junit4.13.2 这个依赖
- 修改D:\java_projects\maven_D\pom.xml
<!-- 引入maven_D -->
<dependency>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
<!--排除junit-->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
- 刷新maven 管理器,看maven_A 的变化, 仍然是拿不到junti4.13.2, 提示: 再通过HelloTest.java 来验证实际使用的junit 版本, 更加清晰了.
可选依赖和排除依赖区别
一句话: 隐藏依赖是不让其他项目来引用(我不给), 排除依赖是主动不要引入的某个资源(我不要)
依赖范围
作用范围
一句话: 依赖的jar 默认情况可以在任何地方使用, 通过scope 标签设定其作用范围
举例说明
● 作用范围说明
- 主程序范围有效(src/main 文件夹范围内)
- 测试程序范围有效(src/test 文件夹范围内)
- 是否参与打包(package 指令范围内)
- compile(默认,在主程序、测试代码、打包都有效)
● 作用范围一览图
解读
- 某个引入的jar 包作用范围是程序员根据,业务的实际需要来设置的,不要认为是固定的。
- 比如log4j jar 包,在主程序,测试代码,打包都是需要的, 因此作用范围应当设置为complie
- junit 只是测试代码需要,因此作用范围设置为test 合适,但是如果程序员认为在主程序和打包就是要junit, 仍然可以设置为默认compile
- 比如servlet-api 是tomcat 自己带的,当把程序打包放到生产环境时,用生产环境tomcat 的servlet-api 即可,所以设置为provided 合适,这样就放在servlet-api 版本冲突.
- 比如jdbc, 是第三方的jar , 打包放在生产环境,就应当在自己的包提供jdbc 驱动包,否则程序会因为少驱动包,运行失败
● 看一个案例, 体会依赖范围的特点.
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- 解读
1. option 默认是false , 即不隐藏
2. option 设置为true , 即隐藏-->
<optional>false</optional>
<!-- scope 设置为test, 让他在test 范围有效-->
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 创建D:\java_projects\maven_D\src\test\java\T2.java, 在test 范围正常使用
import org.junit.Test;
public class T2 {
@Test
public void f1(){
}
}
- 创建D:\java_projects\maven_D\src\main\java\T1.java, 在主程序中,报错
- 修改D:\java_projects\maven_D\pom.xml, 发现主程序和测试程序都可以使用了.
<optional>false</optional>
<!-- scope 设置为test, 让他在test范围有效, 默认就是compile,可以不设置-->
<scope>compile</scope>
- 运行maven web 项目
Maven 项目构建生命周期
一句话: Maven 构建生命周期描述的是一次构建过程经历了多少个事件
生命周期的3 大阶段
clean
清理工作
default
核心工作,例如编译,测试,打包,部署等
site
产生报告,发布站点等
生命周期是分阶段执行的
一句话: 项目构建生命周期分很多阶段,并不是每次都完整执行,而是根据用户的要求来执行的【比如你执行compile, 那么就执行到complie 这个阶段,如果你执行install, 则会执行compile->test->package->install】
举例说明
1、演示compile
2、演示install
maven 插件
介绍
1、插件与生命周期内的某个阶段绑定,在执行到对应生命周期时, 由对应插件来完成任务/功能.
2、maven 插件很多,先看一张图:
3、通过插件可以自定义其他功能
4、文档: http://maven.apache.org/plugins/index.html
自定义插件-应用实例
需求: 在pom.xml 加入自定义插件,能够在对maven_D 项目打包时,能输出主程序和测试程序的源码
完成步骤
- 当前package 只会得到项目的jar
- 修改D:\java_projects\maven_D\pom.xml, 加入maven 插件并配置(注意: 加入自定义插件后,可能会爆红,重启项目即可.)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
韩顺平Java 工程师
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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wyx</groupId>
<artifactId>maven_D</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- 解读
1. option 默认是false , 即不隐藏
2. option 设置为true , 即隐藏-->
<optional>false</optional>
<!-- scope 设置为test, 让他在test 范围有效-->
<scope>compile</scope>
</dependency>
</dependencies>
<!--在build 时,自定义的插件-->
<build>
<plugins>
<plugin>
<!-- 插件坐标-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<!-- 对主程序输出源码打包-->
<goal>jar</goal>
<!-- 对测试程序输出源码打包-->
<goal>test-jar</goal>
</goals>
<!-- 在generate-test-resources 阶段执行-->
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 观察一下maven 项目管理器
- 再次执行maven-D 的intall 操作, 会得到两个新的jar ,分别包含了主程序和测试程序的源码。(说明: 测试时,需要保证src/main/… 和src/test/… 两个目录下有java 源代码,否则不会生成源码jar)
- 解压得到jar , 可以看到源码了.
maven 插件-maven 构建生命周期关系图
图解
-
在maven 项目构建生命周期中,每个阶段的执行都有相应的插件完成
-
各个插件执行过程中,会附带输出内容,比如jar/war/xml/源码
-
程序员可以使用maven 默认的插件,也可以自定义插件,完成定制任务.
-
自定义插件引入成功, 是可以看到文章来源:https://www.toymoban.com/news/detail-486250.html
文章来源地址https://www.toymoban.com/news/detail-486250.html
到了这里,关于Maven教程--下(包括手动实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!