第3章 后端Web基础 (Maven)

一、Maven概述

1、课程介绍

Maven是一款用于管理和构建Java项目的工具,是apache旗下的一个开源项目。

Apache软件基金会,成立于1999年7月,是目前世界上最大的最受欢迎的开源 软件基金会,也是一个专门为支持开源项目而生的非盈利性组织。 开源项目:Welcome to The Apache Software Foundation | Apache Software Foundation

(1)依赖管理

方便快捷的管理项目依赖的资源(jar包)

无需手动导入jar包,只需要在pom.xml文件中声明即可

(2)项目构建

标准化的跨平台(Linux、Windows、MacOs)的自动化项目构建方式

传统项目构建方式需要一系列流程

而Maven的项目构建提供了项目的生命周期

项目构建的文件存放在target目录下

(3)统一项目结构

提供标准、统一的项目结构 传统的各编译软件的项目结构是不相通的,引入Maven后就可以使用同一个项目结构

2、Maven介绍

Apache Maven是一个项目管理和构建工具,它基于项目对象模型(POM)(project object madel)的概念,通过一小段描述信息来管理项目的构建。

作用:

方便的依赖管理

标准的项目构建流程

统一的项目结构

官网:Welcome to Apache Maven -- Maven

项目对象模型(POM)

XML 复制代码
<!--描述当前项目信息。包名、项目名、版本-->
<groupId>com.itheima</groupId>
<artifactId>maven-project01</artifactId>
<version>1.0-SNAPSHOT</version>
​
<!--基于JDK哪个版本开发的  运行的时候是基于哪个JDK版本 字符集编码-->
<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

依赖管理模型(Dependency)

dependency里包括但不限于这些标签

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.1.4</version>
​
            <!--排除依赖-->
            <exclusions>
                <exclusion>
                    <groupId>io.micrometer</groupId>
                    <artifactId>micrometer-observation</artifactId>
                </exclusion>
            </exclusions>
    </dependency>
</dependencies>

仓库:用于存储资源,管理各种jar包。

本地仓库:自己计算机上的一个目录。

我的本地仓库地址:"D:\install\envresoce\maven\repository\commons-io\commons-io\2.6"

中央仓库:由Maven团队维护的全球唯一 的。仓库地址:Central Repository:

远程仓库(私服):一般由公司团队搭建的私有仓库。

3、Maven安装

(1)解压Apache-maven-3.9.4-bin.zip

(2)配置本地仓库

解压Maven文件,创建mvn-repo文件夹,并在conf\settings.xml文件下构建此本地仓库路径

(3)配置阿里云私服地址

该文件中<mirrors>标签中覆盖粘贴

XML 复制代码
<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

(4)配置环境变量

path中

(5)测试

二、IDEA集成Maven

1、Maven项目创建

(1)配置Maven和JDK

在欢迎页面

配置Maven

配置JRE

配置字节码文件

配置JDK版本,在新建的项目里面打开Project Settings

JDK和语言版本都选21(教程里面选的17)

(2)创建模块

这就是创建出来的Maven项目

Maven项目文件介绍

2、Maven坐标

什么是坐标?

Maven中的坐标是资源(jar)的唯一标识,通过该坐标可以唯一定位资源位置。

使用坐标来定义项目或引入项目中需要的依赖。

Maven坐标主要组成

  • groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)

  • artifactld:定义当前Maven项目名称(通常是模块名称,例如order-service、goods-service)

  • version:定义当前项目版本号

    • SNAPSHOT:功能不稳定、尚处于开发中的版本,即快照版本

    • RELEASE:功能趋于稳定、当前更新停止,可以用于发行的版本

    • 上面两个都是约定 而不是规定

例如:

XML 复制代码
<groupld>com.itheima</groupld>
<artifactld>maven-project01</artifactld>
<version>1.0-SNAPSHOT</version>

3、Maven项目导入

(1)方式一

(2)方式二

(3)演示

先将Maven项目放到项目文件夹下面

选择这个pom文件

先导入项目获取项目,再导入项目识别Maven项目

导入Maven项目

建议将要导入的maven项目复制到你的项目目录下

建议选择maven项目的pom.xml文件进行导入

因为会将关联项目一并导入

三、依赖管理

1、依赖配置

依赖:指当前项目运行 所需要的jar包,一个项目中可以引入多个依赖。

配置: 1.在pom.xml中编写<dependencies>标签

2.在<dependencies>标签中使用<dependency>引入坐标

3.定义坐标的groupld,artifactld,version

4.点击刷新按钮,引入最新加入的坐标

注意: 如果不知道依赖的坐标信息,可以到https://mvnrepository.com/中搜索。

当引入依赖时,会引入多个依赖,这些依赖都是引入该依赖时的依赖的其他依赖,称为Maven的依赖传递

如果不想要某个依赖,可以排除依赖

排除依赖:指主动断开依赖的资源,被排除的资源无需指定版本。

2、生命周期

Maven的生命周期就是为了对所有的maven项目构建过程进行抽象和统一。

Maven中有3套相互独立的生命周期:

clean:清理工作。

default:核心工作,如:编译、测试、打包、安装、部署等。

site:生成报告、发布站点等。

每套生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。

Maven生命周期的各个阶段

主要了解五个阶段

生命周期阶段

clean:移除上一次构建生成的文件

compile:编译项目源代码

test:使用合适的单元测试框架运行测试(junit)

package:将编译后的文件打包,如:jar、war等

install:安装项目到本地仓库

注意: 在同一套生命周期中,当运行后面的阶段时,前面的阶段都会运行。

clean就和其他四个不在同一套生命周期中

演示:在Maven项目下cmd,输入mvn clean、mvn compile等,在命令行窗口运行Maven生命周期

install了Maven项目之后,会在本地仓库下创建Maven项目的jar包,具体路径可以顺着xml文件找

重新看这张图

四、单元测试

1、概述

测试:是一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。

(1)阶段划分

单元测试、集成测试、系统测试、验收测试。

单元测试

介绍:对软件的基本组成单位进行测试,最小测试单位。

目的:检验软件基本组成单位正确性

测试人员:开发人员

集成测试

介绍:将已分别 通过测试的单元 ,按设计要求组合成系统或子系统,再进行的测试。

目的:检查单元之间的协作是否正确。

测试人员:开发人员

系统测试

介绍:对已经集成好的软件系统进行彻底的测试。

目的:验证软件系统的正确性、性能是否满足指定的要求。

测试人员:测试人员

验收测试

介绍:交付测试,是针对用户需求、业务流程进行的正式的测试。

目的:验证软件系统是否满足验收标准

测试人员:客户/需求方

(2)测试方法

2、入门

(1)main方法测试

  • 测试代码与源代码未分开,难维护

  • 一个方法测试失败,影响后面方法

  • 无法自动化测试,得到测试报告

(3)JUnit单元测试(推荐)

  • 测试代码与源代码分开,便于维护

  • 可根据需要进行自动化测试

  • 可自动分析测试结果,产出测试报告

(4)案例

使用JUnit,对UserService中业务方法进行单元测试。

1.在pom.xml中,引入JUnit的依赖。

XML 复制代码
<!--junit依赖-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.1</version>
    <!--依赖范围-->
    <scope>test</scope>
</dependency>

2.在test\java目录下,创建测试类,并编写对应的测试方法,并在方法上声明@Test注解。

注意:

JUnit单元测试类名命名规范为:XxxxxTest【规范】。

JUnit单元测试的方法,必须声明为public void【规定】

java 复制代码
package com.itheima;
​
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
​
/**
 * 测试类
 */
@DisplayName("用户信息测试类")
public class UserServiceTest {
    @Test
    public void testGetAge(){
        //先new一个对象
        UserService userService = new UserService();
        Integer age = userService.getAge("100000200010011011");
        System.out.println(age);
    }
}
​

3.运行单元测试(测试通过:绿色;测试失败:红色)。

3、断言

(1)断言方法

JUnit提供了一些辅助方法 ,用来帮我们确定被测试的方法是否按照预期的效果正常工作,这种方式称为断言。

java 复制代码
exp代表期望值,act代表实际值
​
Assertions.assertEquals(Object exp,Object act,String msg)//检查两个值是否相等,不相等就报错。
Assertions.assertNotEquals(Object unexp,Object act,String msg)//检查两个值是否不相等,相等就报错。
Assertions.assertNull(Object act, String msg)//检查对象是否为null,不为null,就报错。
Assertions.assertNotNull(Object act,String msg)//检查对象是否不为null,为null,就报错。
Assertions.assertTrue(boolean condition, String msg)//检查条件是否为true,不为true,就报错。
Assertions.assertFalse(boolean condition, String msg)//检查条件是否为false,不为false,就报错。
Assertions.assertThrows(Class expType,Executable exec,String msg)//检查程序运行抛出的异常,是否符合预期
    //Executable代表函数式接口

提示:

上述方法形参中的最后一个参数msg,表示错误提示信息,可以不指定(有对应的重载方法)。

(2)案例:检查两个值是否相等

身份证倒数第二位是奇数代表男性,偶数代表女性

java 复制代码
/**
     * 断言
     */
    @Test
    public void testGenderWithAssert(){
        UserService userService = new UserService();
        String gender = userService.getGender("100000200010011011");
        //断言
        //Assertions.assertEquals("男", gender);
        Assertions.assertEquals("男", gender, "性别获取错误有问题");
    }

若断言测试失败

(3)案例:检查程序运行抛出的异常

参数传入异常类型和一个Lambda表达式

java 复制代码
/**
     * 断言
     */
    @Test
    public void testGenderWithAssert2(){
        UserService userService = new UserService();
        //断言
        Assertions.assertThrows(IllegalArgumentException.class, () -> {
            userService.getGender(null);
        });
    }

异常类型:业务逻辑中抛出的异常,身份证号码无效

Lambda表达式中调用该方法,传入参数为null

java 复制代码
public String getGender(String idCard){
    if (idCard == null || idCard.length() != 18) {
        throw new IllegalArgumentException("无效的身份证号码");
    }
    return Integer.parseInt(idCard.substring(16,17)) % 2 == 1 ? "男" : "女";
}

若未抛出异常,则显示未抛出异常的失败断言

4、常见注解

(1)常见注解

在JUnit中还提供了一些注解,还增强其功能,常见的注解有以下几个:

java 复制代码
注解
说明
备注    

@Test
测试类中的方法用它修饰才能成为测试方法,才能启动执行
单元测试

@ParameterizedTest
参数化测试的注解(可以让单个测试运行多次,每次运行时仅参数不同)
用了该注解,就不需要@Test注解了

@ValueSource
参数化测试的参数来源,赋予测试方法参数
与参数化测试注解配合使用

@DisplayName
指定测试类、测试方法显示的名称(默认为类名、方法名)

@BeforeEach
用来修饰一个**实例方法**,该方法会在**每一个**测试方法执行之前执行一次。
初始化资源(准备工作)

@AfterEach
用来修饰一个**实例方法**,该方法会在**每一个**测试方法执行之后执行一次。
释放资源(清理工作)

@BeforeAll
用来修饰一个**静态方法**,该方法会在所有测试方法之前**只执行一次**。
初始化资源(准备工作)

@AfterAll
用来修饰一个**静态方法**,该方法会在所有测试方法之后**只执行一次**。
释放资源(清理工作)

(2)@BeforeEach、@AfterEach、@BeforeAll、@AfterAll的使用

可以用于new业务的方法

java 复制代码
@BeforeAll //在所有的单元测试方法运行之前, 运行一次
public static void beforeAll(){
    System.out.println("before All");
}
@AfterAll //在所有的单元测试方法运行之后, 运行一次
public static void afterAll(){
    System.out.println("after All");
}
@BeforeEach //在每一个单元测试方法运行之前, 都会运行一次
public void beforeEach(){
    System.out.println("before Each");
}
@AfterEach //在每一个单元测试方法运行之后, 都会运行一次
public void afterEach(){
    System.out.println("after Each");
}

(3)参数化测试

java 复制代码
/**
 * 参数化测试
 */
@DisplayName("测试用户性别")
@ParameterizedTest
@ValueSource(strings = {"100000200010011011","100000200010011031","100000200010011051"})
public void testGetGender2(String idCard){
    UserService userService = new UserService();
    String gender = userService.getGender(idCard);
    //断言
    Assertions.assertEquals("男", gender);
}

控制台输出结果

5、企业开发单元测试定义规范

(1)测试注意

要考虑边界情况和正常情况

新创建多个单元测试方法

(2)查看单元测试的覆盖率

在右侧展示单元测试覆盖率

Class:类的覆盖率

Method:方法的覆盖率(getGender方法测试到了,但是getAge方法没有测试到)

Line:代码有多少覆盖到了

Branch:分支(if else)

(3)只测单个文件的单元测试覆盖率

6、基于AI依赖自动生成单元测试2

在业务方法上面的通义灵码中,使用AI生成单元测试

7、Maven依赖范围

(1)依赖作用范围

在maven项目中,test目录存放单元测试的代码,是否可以在main目录中编写单元测试呢?

依赖的jar包,默认情况下,可以在任何地方使用。可以通过<scope>...</scope>设置其作用范围。

作用范围:

主程序范围有效。(main文件夹范围内)

测试程序范围有效。(test文件夹范围内)

是否参与打包运行。(package指令范围内)

作用范围:

因此,junit依赖可以限制作用范围

XML 复制代码
<!--junit依赖-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.1</version>
    <!--依赖范围-->
    <!--默认是comple-->
    <scope>test</scope>
</dependency>

(2)maven的生命周期,test详解

当生命周期执行到test时,所有命名规范的(以Test为结尾的)测试方法都会运行

若已经执行过test,不想重复执行,可以点击这里跳过test

五、Maven常见问题解决方案

Maven文件未完成下载

产生原因:由于网络原因,依赖没有下载完整导致的,在maven仓库中生成了xxx.lastUpdated文件,该文件不删除,不会再重新下载。

解决方案: 1.根据maven依赖的坐标,找到仓库中对应的xxx.lastUpdated文件,删除,删除之后重新加载项目即可。

2.通过命令(del/s*.lastUpdated)批量递归删除指定目录下的xxx.lastUpdated文件,删除之后重新加载项目即可。

在Maven仓库的根目录下cmd执行del/s*.lastUpdated

3.双击Maven目录下的del.bat文件,该文件打包好了cmd命令

最后重启项目即可

注意: 重新加载依赖,依赖下载了之后,maven面板可能还会报红,此时可以关闭IDEA,重新打开IDEA加载此项目即可。

相关推荐
小小编程路1 小时前
Java super 关键字详解:用法、场景与常见误区
java·开发语言
我登哥MVP1 小时前
走进 Gang of Four 设计模式:外观模式
java·设计模式·外观模式
tiancaijiben2 小时前
阿里云SAE应用引擎弹性扩缩容完全指南:从手动调控到智能自动化
java·网络·数据库
增量星球2 小时前
《持续交付2.0系列一》从技术交付到业务引领
java·docker·容器·devops
ch.ju2 小时前
Java Programming Chapter 4——Anonymous inner class
java·开发语言
Mr__Miss2 小时前
Java 随机数生成器选型指南:Random、ThreadLocalRandom 与 SecureRandom
java·开发语言·python
if_you_can_please_do2 小时前
IDEA插件Maven开发版本管理小助手Maven With Me更新2.9.x版本啦,升版、快速搜索依赖、JDK切换等核心功能助力中大厂业务快速开发与迭代!
java·maven·intellij-idea
zzz_23682 小时前
【Java实习面试算法冲刺】动态规划
java·算法·面试
cfm_29142 小时前
SpringBoot自定义Starter
java·spring boot·后端