Java 项目的构建工具 Maven

Maven

    • 一、Maven 简介
    • 二、Maven 安装配置
      • 1、Maven 下载安装
      • 2、Maven 配置
    • 三、IDEA 集成 Maven
    • 四、Maven 依赖管理
      • 1、依赖配置
      • 2、依赖传递
      • 3、依赖范围
      • 4、生命周期
    • 五、Maven 高级特性
      • 1、分模块设计与开发
      • 2、Maven 继承
      • 3、Maven 版本管理
      • 4、Maven 聚合
      • 5、私服

一、Maven 简介

Maven 是 Apache 旗下的一个开源项目,是一款管理和构建 Java 项目的工具。他有 3 大核心功能:

  1. 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题(直接在 pom.xml 文件中导入依赖)
  2. 统一项目结构:提供标准、统一的项目结构(两个标准目录:main、test)
  3. 项目构建:maven提供了标准的、跨平台(Linux、Windows、MacOS) 的自动化项目构建方式(清理、编译、测试、打包、发布等插件)

Maven 中有三种模型,其对应关系如下:

Maven 中仓库如图:

  • 本地仓库:自己计算机上的一个目录(用来存储jar包)
  • 中央仓库:由Maven团队维护的全球唯一的。仓库地址:https://repo1.maven.org/maven2/
  • 远程仓库(私服):一般由公司团队搭建的私有仓库

一般来说,Maven 仓库查找 jar 包的顺序是:

当项目中使用坐标引入对应依赖 jar 包后,首先会查找本地仓库中是否有对应的jar包,如果有,则在项目直接引用,如果没有,则去中央仓库中下载对应的jar包到本地仓库。如果还可以搭建远程仓库(私服),将来 jar 包的查找顺序则变为: 本地仓库 --> 远程仓库–> 中央仓库。

二、Maven 安装配置

1、Maven 下载安装

Maven 下载地址:https://maven.apache.org/download.cgi

Maven 是绿色软件,下载压缩包之后,直接解压即可:

2、Maven 配置

进入到conf目录下修改settings.xml配置文件:
(1)配置本地仓库地址
在55行添加如下信息,标签中的路径为自定义的本地仓库路径。

  <localRepository>D:\maven3.8.5\apache-maven-3.8.5-bin\apache-maven-3.8.5\mvn_repo</localRepository>

(2)配置阿里镜像源
由于中央仓库在国外,所以下载 jar 包速度可能比较慢,这里我们使用阿里公司提供了一个远程仓库镜像。需要在160行添加如下配置

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

(3)配置环境变量

  1. 在系统变量处新建一个变量 MAVEN_HOME,值为 maven 的解压安装目录
  2. PATH环境变量的值,设置为:%MAVEN_HOME%\bin

验证:mvn -v

三、IDEA 集成 Maven

(1)创建 Maven 项目
可以先创建一个空项目,然后在空项目中导入 Maven 模块:

(2)pom 文件详解

<?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"><!--  pom 模型版本  --><modelVersion>4.0.0</modelVersion><!--  当前项目坐标  --><groupId>com.lee</groupId><artifactId>maven_projectA</artifactId><version>1.0-SNAPSHOT</version><!--  定义项目的属性  --><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><!-- 打包方式(默认为 jar) --><packaging>jar</packaging></project>

关于坐标:

  • Maven中的坐标是资源的唯一标识 , 通过该坐标可以唯一定位资源位置(Jar 包位置)
  • 使用坐标来定义项目或引入项目中需要的依赖,我们的项目如果被其他的项目依赖时,也是需要坐标来引入的。

Maven 坐标主要由一下3个部分组成:

  • groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)
  • artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
  • version:定义当前项目版本号

(3)导入 Maven 项目
导入 Maven 项目只需导入 pom.xml 文件即可:

四、Maven 依赖管理

1、依赖配置

(1)什么是依赖?

指当前项目运行所需要的 Jar 包,一个项目中可以引入多个依赖。实际上这里说的依赖就是我们在 maven 工程的 pom.xml 文件中,引入的 Jar 包坐标

(2)如何添加依赖?

在 Maven 中添加依赖,关键是拿到依赖的坐标,然后再 pom.xml 中的 <dependencies><dependency>依赖坐标</dependency></dependencies> 标签中添加对应的依赖坐标即可,我们可以通过以下方式拿到依赖坐标的方式:

  1. 到mvn的中央仓库(https://mvnrepository.com/)中搜索依赖,得到对应依赖坐标。
  2. 利用 IDEA 工具搜索依赖(快捷键 Alt + Insert)

2、依赖传递

(1)什么是依赖传递?

在 Maven 中依赖具有传递性,早期没有 Maven 的时候,如果我们想引入依赖,但是引入的依赖又间接的依赖了其他的 Jar 包,这个时候我们就需要把所有依赖的 Jar 包都下载下来。但是有了 Maven 之后,我们只需要在 pom.xml 中添加直接依赖的坐标即可,由于maven的依赖具有传递性,所以会自动把所依赖的其他jar包也一起导入。

我们可以将依赖细分为:

  1. 直接依赖:在当前项目中通过依赖配置建立的依赖关系
  2. 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源

如下图:


  • projectA依赖了 projectB。对于 projectA 来说,projectB 就是直接依赖。
  • 而 projectB 依赖了 projectC 及其他 jar 包。 那么此时,在 projectA 中也会将 projectC 的依赖传递下来。对于 projectA 来说,projectC 就是间接依赖。

(2)Maven 支持排除依赖

例如我们的 maven_projectA 依赖的 maven_projectB 中还依赖了 junit 框架,但是我们并不想依赖将 junit 依赖到 maven_projectA 中,此时我们就可以使用如下方式排除 junit 依赖:

<dependency><groupId>com.lee</groupId><artifactId>maven_projectB</artifactId><version>1.0-SNAPSHOT</version><!--排除依赖, 主动断开依赖的资源--><exclusions><exclusion><groupId>junit</groupId><artifactId>junit</artifactId></exclusion></exclusions>
</dependency>

3、依赖范围

依赖范围也就是导入依赖的 Jar 包后,Jar 包的使用范围,可以通过<scope>标签设置其作用范围。如:

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope>
</dependency>

score 标签取值范围:

scope编译(main文件夹范围内)测试(test 文件夹范围内)打包/运行(package 指令范围内)范例
compile(默认)YYYlog4j
test-Y-junit
providedYY-servlet-api
runtime-YYjdbc 驱动

4、生命周期

Maven 的生命周期就是为了对所有的构建过程进行抽象和统一。描述了一次项目构建,经历哪些阶段。

Maven 对项目构建的生命周期划分为相互独立的 3 套:

  • clean:清理工作。
  • default:核心工作。如:编译、测试、打包、安装、部署等。
  • site:生成报告、发布站点等。


其中我们主要关注以下几个:

  • clean:移除上一次构建生成的文件
  • compile:编译项目源代码
  • test:使用合适的单元测试框架运行测试(junit)
  • package:将编译后的文件打包,如:jar、war等
  • install:安装项目到本地仓库

注意:在同一套生命周期中,我们在执行后面的生命周期时,前面的生命周期都会执行。

这意味着当运行package生命周期时 clean 不会运行,compile会运行。 因为compile与 package 属于同一套生命周期,而 clean 与 package 不属于同一套生命周期。

Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际工作。在Maven的设计中,实际任务都交由插件来完成的:

在这里插入图片描述

五、Maven 高级特性

1、分模块设计与开发

所谓分模块设计,顾名思义指的就是我们在设计一个 Java 项目的时候,将一个 Java 项目拆分成多个模块进行开发。在分模块之前,我们的项目都整合在一个模块中,随着项目的业务扩张,单模块在管理和维护上都比较困难。并且项目中的通用组件难以复用。

而分模块设计就可以很好地解决上述问题,分模块可以将项目按照功能/结构拆分成若干个子模块,方便项目的管理维护、拓展,也方便模块键的相互调用、资源共享。

比如一个电商项目包括订单管理、商品管理、物流管理……以及一些通用组件等。在开发这个项目的时候我们就可以采用分模块的思想,将项目划分为订单模块、商品模块、物流模块、通用组件模块等。如果当某个模块,比如订单模块需要用通用组件,此时直接在订单模块当中引入通用组件模块的坐标就可以了。此外,由于对模块进行了拆分,可以更方便高效的进行项目管理。

PS:分模块开发需要先针对模块功能进行设计,再进行编码。不会先将工程开发完毕,然后进行拆分。

2、Maven 继承

当我们对项目分模块开发之后,往往会遇到这样的问题:多个模块中引入了相同的依赖,比如 lombok。在实际开发中重复的依赖可能会很多很多。如果每一个 Maven 模块里面,我们都来单独的配置一次,这个过程是相当繁琐的。而下面要介绍的 Maven 中的继承恰好可以解决这个问题:

Maven 中的继承与 Java 中的继承相似,子工程可以继承父工程中的配置信息。可以简化依赖配置、统一管理依赖。
具体实现是通过在子工程中添加下面的 <parent></parent>标签实现的:

<parent><groupId>父工程组织Id</groupId><artifactId>父工程项目Id</artifactId><version>父工程版本号</version><relativePath>父工程相对路径</relativePath>
</parent>

比如 parent 工程作为 A、B、C 工程的父工程,引入了 lombok 依赖,同样可以看到子工程中继承的父工程依赖:

这里需要注意的是父工程打包方式需要配置为 pom

  1. jar:普通模块打包(默认打包方式),springboot项目基本都是jar包(内嵌tomcat运行)
  2. war:普通web程序打包,需要部署在外部的tomcat服务器中运行
  3. pom:父工程或聚合工程,该模块不写代码,仅进行依赖管理
  1. 在子工程中,配置了继承关系之后,坐标中的 groupId 是可以省略的,因为会自动继承父工程的 。
  2. relativePath 指定父工程的pom文件的相对位置(如果不指定(不写<relativePath>标签),默认路径为 ../pom.xml;如果显示不指定(<relativePath/>)将从本地仓库/远程仓库查找该工程)。

PS:Maven 和 Java 一样都不支持多继承,但都支持多重继承。

3、Maven 版本管理

如果项目中各个模块中都公共的这部分依赖,我们可以直接定义在父工程中,从而简化子工程的配置。 然而在项目开发中,还有一部分依赖,是一部分模块独有的。对于一个项目来讲依赖的版本一般是统一的,假如我们的项目要升级,对应的依赖的版本也要升级,共有的依赖直接在父工程中修改就好了,但是对于一些模块独有的依赖修改起来就相当的困难了。

如果项目拆分的模块比较多,每一次更换版本,我们都得找到这个项目中的每一个模块,一个一个的更改。 不仅过程很繁琐,而且很可能一不小心就遗漏掉一个模块。

Maven 也是关注到这一点,很贴心的给我们提供了版本管理的功能:

在maven中,可以在父工程的pom文件中通过 <dependencyManagement></dependencyManagement> 来统一管理依赖版本:
父工程:

<!--统一管理依赖版本-->
<dependencyManagement><dependencies><!--JWT令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency></dependencies>
</dependencyManagement>

子工程:

<dependencies><!--JWT令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency>
</dependencies>
  1. 在父工程中所配置的 <dependencyManagement> 只能统一管理依赖版本,并不会将这个依赖直接引入进来。 这点和 <dependencies> 是不同的, <dependencies> 标签会直接将依赖引入。
  2. 子工程要使用这个依赖,还是需要引入的,只是此时就无需指定 <version> 版本号了,父工程统一管理。变更依赖版本,只需在父工程中统一变更。

这里需要注意一点,Maven 中还支持自定义属性标签功能,可以将父工程中的版本管理进一步解耦:

<!-- 自定义属性 -->
<properties><lombok.version>1.18.24</lombok.version><jjwt.version>0.9.1</jjwt.version>
</properties><!-- 引用属性 -->
<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency>
</dependencies><!--统一管理依赖版本-->
<dependencyManagement><dependencies><!--JWT令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jjwt.version}</version></dependency></dependencies>
</dependencyManagement>

4、Maven 聚合

分模块设计与开发之后啊,我们的项目被拆分为多个模块,而模块之间的关系,可能错综复杂。子模块之间也可能相互依赖,那么我们在对某个模块进行打包时,就需要先将依赖的模块安装到 Maven 仓库在,再针对模块采取打包操作。

试想一下,如果开发一个大型项目,拆分的模块很多,模块之间的依赖关系错综复杂,那此时要进行项目的打包、安装操作,是非常繁琐的。

Maven 的聚合就是来解决这个问题的,通过 Maven 的聚合就可以轻松实现项目的一键构建(清理、编译、测试、打包、安装等)

Maven 中的聚合就是将多个模块组织成一个整体,同时进行项目构建。其中的聚合工程是一个不具有业务功能的“空”工程(有且仅有一个pom文件)一般来说,继承关系中的父工程与聚合关系中的聚合工程是同一个。使用 Maven 的聚合功能我们就可以实现快速构建项目,即无需根据依赖关系手动构建,直接在聚合工程上构建即可。

    <!--聚合其他模块--><modules><module>maven-projectA</module><module>maven-projectB</module><module>maven-projectC</module></modules>

执行打包 package 命令:

小结:

  1. 聚合用于快速构建项目
  2. 继承用于简化依赖配置、统一管理依赖

5、私服

通常情况下,我们所拆分的模块是可以在同一个公司各个项目组之间进行资源共享的,如何实现一个公司中模块资源共享呢?这就需要使用到 Maven 中的私服了。那么你可能会问了,为什么不使用中央仓库呢?直接把共享模块的 Jar 包资源上传到 Maven 中央仓库,通过引入的依赖坐标,先到本地仓库查找,再到中央仓库查找。其实这个想法是行不通的,主要原因有如下两点:

  1. 中央仓库全球只有一个,不是什么人都可以往中央仓库中来上传jar包的,我们是没有权限操作的
  2. 共享的模块可能涉及到公司敏感信息,不适合放到中央仓库

所以最好的解决方案依然是使用 Maven 私服:

有了私服之后,各个团队就可以直接来连接私服了,连接上私服之后,他就可以把 jar 包直接上传到私服当中,如果需要某些共享模块资源,直接引入坐标,从私服当中将对应的 jar 包下载到自己的本地仓库。如果需要第三方提供的依赖,获取依赖的顺序变为:本地仓库–》私服–》中央仓库。

使用私服完成资源上传和下载:


第一步配置:在maven的配置文件中配置访问私服的用户名、密码。(在maven安装目录下的conf/settings.xml中的servers中配置)

<server><id>maven-releases</id><username>admin</username><password>admin</password>
</server><server><id>maven-snapshots</id><username>admin</username><password>admin</password>
</server>

第二步配置:设置私服依赖下载的仓库组地址(在maven安装目录下的conf/settings.xml中的mirrors、profiles中配置)

<mirror><id>maven-public</id><mirrorOf>*</mirrorOf><url>http://xxx:xxx/repository/maven-public/</url>
</mirror>
<profile><id>allow-snapshots</id><activation><activeByDefault>true</activeByDefault></activation><repositories><repository><id>maven-public</id><url>http://xxx:xxx/repository/maven-public/</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories>
</profile>

第三步配置:在项目的pom.xml文件中配置上传资源的位置(url地址)。

<distributionManagement><!-- release版本的发布地址 --><repository><id>maven-releases</id><url>http://xxx:xxx/repository/maven-releases/</url></repository><!-- snapshot版本的发布地址 --><snapshotRepository><id>maven-snapshots</id><url>http://xxx:xxx/repository/maven-snapshots/</url></snapshotRepository>
</distributionManagement>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/38360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac虚拟机软件有什么用?

随着苹果M系列芯片电脑的推出&#xff0c;虚拟机的使用变得越来越流行。不同于苹果以往的Intel处理器电脑&#xff0c;其M系列芯片电脑无法安装双系统。如果要使用非macOS系统&#xff0c;可以通过创建虚拟机系统的方式实现。那么&#xff0c;虚拟机软件有什么作用和用途&#…

设计模式-代理模式和装饰者模式

二者都是结构型的设计模式. 1.代理模式 1.1定义 为其他对象提供一种代理以控制对这个对象的访问. 代理从code实现方面分为静态代理和动态代理两种&#xff1b; 从适用范围来看,分为远程代理,虚拟代理,保护代理,智能引用几种. 远程代理:为某个对象在不同的内存地址空间提供…

【Python】已解决:The method is not allowed for the requested URL.

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项进阶讨论总结 已解决&#xff1a;The method is not allowed for the requested URL. 一、分析问题背景 在开发Web应用程序时&#xff0c;常常需要处理不同的HTTP请求方法&#xff…

WPF的IValueConverter用于校验和格式化TextBox的数字输入

在数据绑定&#xff08;Data Binding&#xff09;的上下文中&#xff0c;我们经常使用继承 IValueConverter 接口的类&#xff0c;用于在源值和目标值之间进行转换。该接口定义了两个方法&#xff1a;Convert 和 ConvertBack&#xff0c;这两个方法分别用于从源值到目标值的转换…

centos 7.9 离线环境安装GPU服务环境

文章目录 centos 7.9 离线环境安装GPU服务环境系统配置更新 gcc更新内核安装显卡驱动安装cuda安装docker 和 nvidia-container-runtime验证 centos 7.9 离线环境安装GPU服务环境 基于centos 7.9 离线安装gpu 服务基础环境&#xff0c;用于在docker 中运行算法服务 系统配置 …

LeetCode 全排列

思路&#xff1a;这是一道暴力搜索问题&#xff0c;我们需要列出答案的所有可能组合。 题目给我们一个数组&#xff0c;我们很容易想到的做法是将数组中的元素进行排列&#xff0c;如何区分已选中和未选中的元素&#xff0c;容易想到的是建立一个标记数组&#xff0c;已经选中的…

二轴机器人装箱机:重塑物流效率,精准灵活,引领未来装箱新潮流

在现代化物流领域&#xff0c;高效、精准与灵活性无疑是各大企业追求的核心目标。而在这个日益追求自动化的时代&#xff0c;二轴机器人装箱机凭借其较佳的性能和出色的表现&#xff0c;正逐渐成为装箱作业的得力助手&#xff0c;引领着未来装箱新潮流。 一、高效&#xff1a;重…

解析桥式整流电路

下面这个桥式整流电路出场率很高&#xff0c;看着一定眼熟。 事实证明&#xff0c;强行灌输的东西总是难以下咽。记得读书那会&#xff0c;第一次看到这个电路时被吓到了&#xff0c;以至于直到这门课结束了也没搞清楚。 本文就来分析一下此电路中电流的走向&#xff0c;进而理…

Spark SQL 的总体工作流程

Spark SQL 是 Apache Spark 的一个模块,它提供了处理结构化和半结构化数据的能力。通过 Spark SQL,用户可以使用 SQL 语言或 DataFrame API 来执行数据查询和分析。这个模块允许开发者将 SQL 查询与 Spark 的数据处理能力结合起来,实现高效、优化的数据处理。下面是 Spark S…

Labview绘制柱状图

废话不多说&#xff0c;直接上图 我喜欢用NXG风格&#xff0c;这里我个人选的是xy图。 点击箭头指的地方 选择直方图 插值选择第一个 直方图类型我选的是第二个效果如图。 程序部分如图。 最后吐槽一句&#xff0c;现在看CSDN好多文章都要收费了&#xff0c;哪怕一些简单的入…

Spark SQL----ANSI Compliance

Spark SQL----ANSI Compliance 一、算术运算二、Cast2.1 Rounding in cast 三、存储分配四、Type coercion4.1 类型提升和优先级4.2 最不常见类型解析 五、SQL函数5.1 函数调用5.2 具有不同行为的函数 六、SQL操作符七、ANSI模式的有用函数八、SQL关键字(可选&#xff0c;默认禁…

浪子易支付最新增加订单投诉版源码

此版本增加了订单投诉功能&#xff0c;和一个好看的二次元模板。

【Python实战因果推断】9_元学习器4

目录 Double/Debiased Machine Learning Double/Debiased Machine Learning Double/Debiased ML 或 R-learner 可以看作是 FrischWaugh-Lovell 定理的改进版。其思路非常简单--在构建结果和治疗残差时使用 ML 模型 结果和干预残差&#xff1a; , 预估&#xff0c;预估 由于 …

Python28-4 KNN近邻算法

KNN&#xff08;K-Nearest Neighbors&#xff09;算法是一种常用的机器学习算法&#xff0c;主要用于分类和回归问题。 1. KNN算法的基本概念 KNN算法是一种基于实例的学习算法&#xff0c;也称为惰性学习&#xff08;Lazy Learning&#xff09;算法&#xff0c;因为它在训练…

51单片机第17步_外部中断

本章重点学习外部中断。 1、外部中断0框图&#xff1a; 2、外部中断1框图&#xff1a; 3、Keil C51中有一些关键字&#xff0c;需要牢记&#xff1a; interrupt 0&#xff1a;指定当前函数为外部中断0&#xff1b; interrupt 1&#xff1a;指定当前函数为定时器0中断&#x…

2 z变换与离散时间傅里叶变换

目录 序列的z变换 z变换的定义 常用典型序列的z变换 序列类型与z变换的收敛域 序列的分类 X(z)的极点与收敛域 单边序列 双边序列 z变换的性质 线性 序列移位 单边序列 双边序列 z域尺度变换 序列乘以n 复共轭序列的z变换 初值定理 终值定理 时域卷积定理 …

Spring事务及其传播机制(二)

目录 1.Transcational详解 1.1 rollbackFor 2事务隔离级别 2.1MySQL事务隔离级别回顾 2.2Spring事务隔离级别 3.Spring事务传播机制 3.1什么是事务传播机制 3.2事务的传播机制有哪些 3.3 Spring 事务传播机制使用和各种场景演示 3.3.1 REQUIRED(加入事务) 3.3.2 REQ…

Apache ZooKeeper 简介

介绍 Apache ZooKeeper 是一种分布式协调服务&#xff0c;旨在管理和同步大量分布式应用程序。ZooKeeper 是 Apache 软件基金会下的一个开源项目&#xff0c;它解决了维护分布式应用程序的配置信息、命名、分布式同步和组服务的复杂性。本文探讨了 ZooKeeper 的架构、功能、应…

商标字体的选择:企业和个人申请注册商标攻略!

对于汉字商标&#xff0c;就会涉及到字体的选择&#xff0c;普推商标老杨也经常看到企业因为文字商标字体侵权收到相关字体公司的律师函&#xff0c;所以商标字体选择上要特别注意。 建议选择可以商用的免费字体&#xff0c;常见的有黑体、宋体等&#xff0c;如果这些字体前面…

基于matlab的可乐标签模板匹配

1 建模思路 1.图像预处理&#xff1a; 如果目标图像和模板图像是彩色的&#xff08;即RGB图像&#xff09;&#xff0c;则将它们转换为灰度图像&#xff0c;以便在单通道上进行匹配。使用rgb2gray函数进行灰度化。 2.获取模板大小&#xff1a; 使用size函数获取模板图像的高…