02-Maven

1. 什么是Maven

  • 目前无论使用IDEA还是Eclipse等其他IDE,都使用ANT工具。ANT工具帮助我们进行编译、打包、运行等工作
  • Apache基于ANT进行了升级,研发出了全新的自动化构建工具Maven。Maven是Apache的一款开源的项目管理工具
  • 以后无论是普通JavaSE项目还是JavaEE项目,创建的都是Maven项目
  • Maven使用项目对象模型(POM-Project Object Model),通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具
    • 在Maven中每个项目都相当于是一个对象,对象(项目)和对象(项目)之间是有关系的
    • 关系包含了:依赖、继承、聚合,实现Maven项目可以更加方便的实现导jar包、拆分项目等效果

2. Maven下载-目录结构

  1. IDEA默认自带并整合了Maven
22641701435195_.pic
  • 在IDEA中可以自定义集成Maven
22681701435241_.pic
  1. 下载地址:Welcome to Apache Mavenopen in new window
22651701435213_.pic
22661701435225_.pic
  1. 目录结构
    • bin:存放的是执行文件,命令
    • conf:下面有一个非常重要的配置文件 => settings.xml => maven的核心配置文件/全局配置文件
22671701435234_.pic
  1. 如果没有.m2目录 ,自己手动执行mvn命令:mvn help:system

3. Maven仓库

  • Maven仓库是基于简单文件系统存储的,集中化管理Java API资源(构件)的一个服务
  • 仓库中的任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径。得益于Maven的坐标机制,任何Maven项目使用任何一个构件的方式都是完全相同的
  • Maven可以在某个位置统一存储所有的Maven项目共享的构件,这个统一的位置就是仓库,项目构建完毕后生成的构件也可以安装、部署到仓库中,供其它项目使用
  • 对于Maven来说,仓库分为两类:本地仓库、远程仓库
  • settings.xml中,配置了三个信息:
    1. 本地仓库
    2. 镜像仓库
    3. JDK

1. 远程仓库

  • 不在本机的一切仓库,都是远程仓库:分为中央仓库、本地私服仓库
  • 远程仓库指通过各种协议如file://http://访问的其它类型的仓库
    • 第三方搭建的真实的远程仓库,用来提供他们的构件下载(eg:repo.maven.apache.orguk.maven.org是Maven的中央仓库)
    • 其它”远程“仓库,可能是公司拥有的建立在文件/HTTP服务器上的内部仓库(不是Apache的中央仓库,而是公司的私服,在局域网搭建的maven仓库),用来在开发团队间共享私有构件和管理发布
  • 默认的远程仓库使用的Apache提供的 中央仓库open in new window
22701701435703_.pic
22711701435715_.pic

2. 本地仓库

本地仓库指本机的一份拷贝,用来缓存远程下载,包含开发尚未发布的临时构件

3. 仓库配置

1. 配置本地仓库

本地仓库是开发者本地电脑中的一个目录,用于缓存从远程仓库下载的构件。默认的本地仓库是${user.home}/.m2/repository。用户可使用settings.xml文件修改本地仓库。具体内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <!-- 本地仓库配置 -->
  <localRepository>具体本地仓库位置</localRepository>
  <!-- 省略,具体信息参考后续内容 -->
</settings>

2. 配置镜像仓库

  • 如果仓库A可以提供仓库B存储的所有内容,那么就可以认为A是B的一个镜像
  • eg:在国内直接连接中央仓库下载依赖,由于一些特殊原因下载速度非常慢
    • 使用阿里云提供的镜像 http://maven.aliyun.com/nexus/content/groups/public/ 来替换中央仓库 http://repol.maven.org/maven2/ 。修改maven的 setting.xml
<mirror>
    <!-- 指定镜像ID(可自己改名) -->
    <id>nexus-aliyun</id>
    <!-- 匹配中央仓库(阿里云的仓库名称,不可以自己起名,必须这么写)-->
    <mirrorOf>central</mirrorOf>
    <!-- 指定镜像名称(可自己改名) -->
    <name>Nexus aliyun</name>
    <!-- 指定镜像路径(镜像地址) -->
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

4. 仓库优先级

  1. 本地仓库
  2. 镜像仓库
  3. 中央仓库

4. JDK的配置

  • 当idea中有多个JDK时,就需要指定编译和运行的JDK。settings.xml中配置
  • 配置的前提是你的idea中要有1.8的jdk
<profile>
    <!-- settings.xml中的id不能随便起的 -->
    <!-- 告诉maven用jdk1.8 -->
    <id>jdk-1.8</id>
    <!-- 开启JDK的使用 -->
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
    </activation>
    <properties>
        <!-- 配置编译器信息 -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
    </properties>
</profile>

5. Maven工程类型

  1. POM工程
    • POM工程是逻辑工程。用在父级工程或聚合工程中。用来做jar包的版本控制
  2. JAR工程
    • 将会打包成jar,用作jar包使用。即常见的本地工程 => Java Project
  3. WAR工程
    • 将会打包成war,发布在服务器上的工程

6. IDEA创建Maven工程

过程:

22731701436018_.pic
22741701436037_.pic
22751701436048_.pic

7. Maven项目结构

标准目录结构:

22781701436357_.pic
  1. src/main/java
    • 这个目录下储存java源代码
  2. src/main/resources
    • 储存主要的资源文件。eg:xml配置文件、properties文件
  3. src/test/java
    • 储存测试用的类。eg:JUNIT的测试一般就放在这个目录下面
    • 因为测试类本身实际是不属于项目的,所以放在任何一个包下都显得很尴尬,所以maven专门创建了一个测试包,用于存放测试的类
  4. src/test/resources
    • 需要自己创建,储存测试环境用的资源文件
  5. src
    • 包含了项目所有的源代码、资源文件,以及其他项目相关的文件
  6. target
    • 编译后内容放置的文件夹
  7. pom.xml
    • 是Maven的基础配置文件。配置项目和项目之间关系,包括配置依赖关系等等

结构图:

|-- MavenDemo:项目名
    |-- .idea:项目的配置,自动生成的,无需关注
    |-- src
        |-- main:实际开发内容
            |-- java:写包和java代码,此文件默认只编译.java文件
            |-- resource:所有配置文件。最终编译把配置文件放入到classpath中
        |-- test:测试时使用,自己写测试类或junit工具等
            |-- java:储存测试用的类
    |-- pom.xml:整个maven项目所有配置内容

注意:目录名字不可以随便改,maven进行编译、jar包生成操作时,是根据这个目录结构进行的

8. POM模式

  • Maven工具基于项目对象模型(POM-Project Object Model)实现
  • 在Maven中每个项目都相当于是一个对象,对象(项目)和对象(项目)之间是有关系的
  • 关系包含了:依赖、继承、聚合,实现Maven项目可以更加方便的实现导jar包、拆分项目等效果

1. 依赖

  1. 依赖关系
    • 即A工程开发、运行过程中需要B工程提供支持,则代表A工程依赖B工程。通俗理解:就是导jar包。B工程可以是自己的项目打包后的jar包,也可以是中央仓库的jar包
    • 需要在A项目的pom.xml文件中增加下属配置,定义依赖关系
image-20231201211602568
  1. 如何注入依赖
    • pom.xml文件,根元素project下的<dependencies>标签中,配置依赖信息,其内可以包含多个<dependency>
22821701436545_.pic
  1. 依赖的好处
    • 省去了手动添加jar包操作,省事!!
    • 解决jar包冲突问题
22831701436555_.pic

1. 依赖的传递性

如果B依赖了C,那么A依赖B时,会自动把B和C都导入进来

22841701436668_.pic
  • 传递性是Maven2.0的新特性。假设项目依赖于一个库,这个库又依赖于其他库。不必去找出所有这些依赖,只需要加上直接依赖的库,Maven会隐式的把直接库中,间接依赖的库也加入到项目中
  • 这个特性是靠解析远程仓库中获取的依赖库的项目文件实现的。一般的,这些项目的所有依赖都会加入到项目中,或从父项目继承,或通过传递性依赖

创建A项目后,选择IDEA最右侧Maven面板Lifecycle,双击install后就会把项目安装到本地仓库中,其他项目就可以通过坐标引用此项目

  1. 项目1:MavenDemo项目依赖了Mybatis的内容:
    • 注意:请将项目1打包为jar包 => 重新打包
22851701436679_.pic
  1. 创建项目2:让项目2依赖项目1:
    • 可以证明:项目2依赖项目1,项目1依赖Mybatis工程 => 传递性 => 项目2可以直接使用Mybatis
22861701436690_.pic

2. 两个原则

  1. 第一原则:最短路径优先原则
    • 意味着项目依赖关系树中路径最短的版本会被使用
    • eg:假设A、B、C之间的依赖关系是A->B->C->D(2.0)A->E->(D1.0),那么D(1.0)会被使用
  2. 第二原则:最先声明原则
    • 依赖路径长度一样时,第一原则不能解决所有问题。eg:A–>B–>Y(1.0)A–>C–>Y(2.0)Y(1.0)Y(2.0)的依赖路径长度一样。谁会被解析使用呢?在maven2.0.8及之前的版本中,这是不确定的
    • maven2.0.9开始,为了尽可能避免构建的不确定性,maven定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,POM中依赖声明的顺序决定了谁会被解析使用

3. 排除依赖

  • <exclusion>:用来排除传递性依赖。标签里面对应的有g, a两项基本元素,不用写版本号。可配置多个<exclusion>
  • eg:A -> B -> C (Mybatis.jar) 排除C中的Mybatis.jar
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4. 依赖范围

依赖范围决定了依赖的坐标,在什么情况下有效

  • compile
    • 默认范围。如果没有指定,就会使用该依赖范围。表示该依赖在编译、运行时都生效
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
    <scope>compile</scope>
</dependency>
  • provided
    • 已提供。典型的例子是servlet-api,编译和测试项目时需要该依赖,但在运行项目时,由于容器已经提供,就不需要Maven重复引入一遍
  • runtime
    • 表明编译时不需要生效,而只在运行时生效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或运行项目时才需要实现上述接口的具体JDBC驱动
  • system
    • 与provided类似,不过必须显式指定一个本地系统路径的JAR,此类依赖应该一直有效,Maven也不会去仓库中寻找它
    • system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径
  • test
    • 表明只在编译测试代码和运行测试时需要,应用的正常运行不需要此类依赖
    • Junit的jar包在测试阶段用就可以了,导出项目时没必要带junit的东西
  • Import
    • 表明指定的POM必须使用<dependencyManagement>部分的依赖
    • 注意:import只能用在<dependencyManagement>的scope里
1. import
  1. 定义一个父工程 -> POM工程
    • 注意:父工程要打成jar包
<groupId>com.msb</groupId>
<artifactId>MavenDemo</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <banben>3.5.4</banben>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${banben}</version>
        </dependency>
    </dependencies>
</dependencyManagement>







 







 
  1. 定义一个子工程
    • <relativePath>../MavenDemo/pom.xml</relativePath>
<groupId>com.msb</groupId>
<artifactId>MavenDemo2</artifactId>
<version>1.0-SNAPSHOT</version>

<parent>
    <groupId>com.msb</groupId>
    <artifactId>MavenDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../MavenDemo/pom.xml</relativePath>
</parent>
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.1</version>
    </dependency>
</dependencies>








 








  1. 如果父工程中加入<scope>import</scope>,相当于强制指定了子工程的版本号
<groupId>com.msb</groupId>
<artifactId>MavenDemo</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <banben>3.5.4</banben>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${banben}</version>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>













 



2. system
  • 引入外部jar
image-20240605112258073
<dependency>
    <groupId>com.listao</groupId>
    <artifactId>fusion-data-trans</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/lib/fusion-data-trans-2023.1.1-RELEASE.jar</systemPath>
</dependency>





 

  • build
  • <targetPath>BOOT-INF/lib/</targetPath> 会将 gav_jar手动_jar 都放到 BOOT-INF/lib
<build>
    <resources>
        <resource>
            <directory>${project.basedir}/src/lib</directory>
            <targetPath>BOOT-INF/ooxx/</targetPath>
        </resource>
    </resources>
</build>




 



image-20240605143240475
  • <resources>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.3.7.RELEASE</version>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/**</include>
            </includes>
        </resource>
        <!-- 打包成jar静态资源必须指明路径,打包成war可以不用 -->
        <resource>
            <directory>${basedir}/src/main/webapp</directory>
            <targetPath>META-INF/resources/</targetPath>
            <includes>
                <include>**/**</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/**</include>
            </includes>
            <filtering>false</filtering>
            <!--<filtering>true</filtering>-->
            <!--<excludes>-->
            <!--    <exclude>rebel.xml</exclude>-->
            <!--</excludes>-->
        </resource>
    </resources>
</build>

2. 继承

  • 本质上:POM文件的继承
  • 如果A工程继承B工程,则代表A默认依赖B依赖的所有资源,且可以应用B中定义的所有资源信息
  • 被继承的工程(B工程)只能是POM工程
  • 父项目中<dependencyManagement>
    • 不被子项目继承,不可以直接使用
    • 主要目的是进行版本管理。里面的内容在子项目中依赖时坐标只需要填写<groupId><artifactId>
    • 子项目不希望使用父项目控制的版本,可以明确配置<version>
  1. 父工程是一个POM工程
22931701437289_.pic
  1. 创建子工程
22951701437381_.pic

3. 聚合

  • 当开发的工程拥有2个以上模块时,每个模块都是一个独立的功能集合。都可以独立编译、测试、运行。就需要一个聚合工程
    • eg:某大学系统中拥有搜索平台,学习平台,考试平台等
  • 创建聚合工程的过程中,总的工程必须是一个POM工程(Maven Project)(聚合项目必须是一个pom类型的项目,jar、war项目是没有办法做聚合工程的)
    • 各子模块可以是任意类型模块(Maven Module)
  • 聚合包含了继承的特性
  • 聚合时多个项目的本质还是一个项目。这些项目被一个大的父项目包含。且父项目为pom类型,同时pom.xml中出现<modules>表示包含的所有子模块
  1. 总项目:<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>

<groupId>com.msb</groupId>
<artifactId>ParentPro</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
    <module>ChildPro</module>
</modules>
<!-- 定义为pom项目 -->
<packaging>pom</packaging>
<!-- 定义版本号 -->
<properties>
    <mybatis.version>3.5.4</mybatis.version>
    <spring.version>5.1.11.RELEASE</spring.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>









 

























  1. 具体模块
<parent>
    <artifactId>ParentPro</artifactId>
    <groupId>com.msb</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>ChildPro</artifactId>

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
    </dependency>
</dependencies>

9. 常见插件

1. 编译器插件

通过编译器插件,可以配置使用具体JDK版本

  1. settings.xml文件中配置全局编译器插件
<profile>
    <!-- 定义的编译器插件ID,全局唯一,名字随便起 -->
    <id>jdk-1.7</id>
    <!-- 插件标记,activeByDefault: true默认编译器,jdk提供编译器版本 -->
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.7</jdk>
    </activation>
    <!-- 配置信息source-源信息,target-字节码信息,compilerVersion-编译过程版本 -->
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <maven.compiler.compilerVersion>1.7</m aven.compiler.compilerVersion>
    </properties>
</profile>
  1. 配置当前项目编译器插件:pom.xml
    • JDK1.7不支持 interface 中的非抽象方法
public interface TestInf {
    default void eat() {
    }
}
<!-- 配置maven的编译插件 -->
<build>
    <plugins>
        <!-- JDK编译插件 -->
        <plugin>
            <!-- 插件坐标 -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
                <!-- 源代码使用JDK版本 -->
                <source>1.7</source>
                <!-- 源代码编译为class文件的版本,保持跟上面版本一致 -->
                <target>1.7</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

2. 资源拷贝插件

  • Maven在打包时,默认只将 src/main/resources 里的配置文件,拷贝到项目中并做打包处理,而非 resource 目录下的配置文件在打包时不会添加到项目中
  • 打包后配置文件就会在 target/classes 下面放着
23021701440848_.pic
  • 把非resources下面的文件也打包到classes下面:
<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>
  • 配置好以后,那么你设置的位置下的配置文件都会被打包了:
23031701440861_.pic

3. Tomcat插件

创建war项目,必然要部署在服务器上,方式:

  1. 部署在远程服务器上
  2. 将IDEA和外部tomcat产生关联,然后将项目部署在外部tomcat上
  3. 不再依赖外部的tomcat,maven提供了tomcat插件,配置来使用
23041701441070_.pic
23051701441084_.pic
23061701441094_.pic
23071701441117_.pic
23081701441124_.pic

index.jsp中随便写点东西:

23091701441131_.pic
  • 使用Tomcat插件发布部署并执行war工程时,需要使用启动命令:tomcat7:run
    • 命令中的tomcat7是插件命名,由插件提供商决定
    • run为插件中的具体功能
  • (注意:之前的编译器插件、资源拷贝插件,不是可运行的插件。Tomcat属于可运行插件,它什么时候工作需要程序员来控制,必须通过命令来运行控制)

具体pom.xml文件的配置如下:

<plugins>
    <!-- 配置Tomcat插件 -->
    <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
            <!-- 配置Tomcat监听端口 -->
            <port>8080</port>
            <!-- 配置项目的访问路径(Application Context) -->
            <path>/</path>
        </configuration>
    </plugin>
</plugins>
  1. 执行命令
23101701441141_.pic
  1. 显示Tomcat启动成功
23111701441151_.pic
  1. 在浏览器中访问index.jsp页面:
23121701441159_.pic

10. Maven常用命令

  1. clean
    • 清除已编译信息
    • 删除工程中的target目录
23131701441345_.pic
  1. compile
    • 只编译。javac命令
  2. package
    • 打包。包含编译,打包两个功能
  3. install
    • 本地安装。包含编译、打包、安装到本地仓库
    1. 编译 - javac
    2. 打包 - jar, 将java代码打包为jar文件
    3. 安装到本地仓库 - 将打包的jar文件,保存到本地仓库目录中