Maven~从入门到入坑。

Maven~从入门到入坑。



在这里插入图片描述


目前的技术在开发中存在的问题。(why)。

  • 一个项目就是一个工程。
    问题:如果项目非常庞大,就不适合继续使用 package 来划分模块。最好是第一个模块对应一个工程,利于分工协作。
    Maven:借助 Maven 就可以将一个项目拆分成多个工程。

  • 项目中需要的 jar 包必须手动“复制”、“粘贴”到 WEB\INF/lib 目录下。同样的 jar 包文件重复出现在不同的项目工程中,一方面浪费存储空间,另外也让工程比较臃肿。
    Maven:借助 Maven,可以将 jar 包仅仅保存在“仓库”中,有需要使用的工程“引用”这个文件,并不需要重复复制。(对比对象的引用理解)。

  • jar 包需要别人替我们准备好,或到官网下载。
    不同技术的官网提供 jar 包下载的形式是五花八门的。
    借助 Maven 可以以一种规范的方式下载 jar 包,因为所有知名框架或第三方工具的 jar 包已经按照统一的规范放在了 Maven 的中央仓库中。
    以规范方式下载的 jar 包,内容也是可靠的。

Tips:“统一的规范”不仅是对 IT 开发领域非常重要,对于整个人类社会都是非常重要的。eg. USB。—> USB 电灯,风扇。

  • 一个 jar 包依赖的其他 jar 包需要自己看手动加入到项目中。
    Maven 会自动将被依赖的 jar 包导入进来。
    如果所有 jar 包之间的依赖关系都需要程序员自己非常清楚的了解,那么会极大增加学习成本。

在这里插入图片描述


Maven ~ what。

Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。

服务于 Java 平台的自动化构建一具。
Make —> Ant —> Maven —> Gradle。

  • 构建。
    以“Java 源文件”、”框架配置文件“、”JSP“、”HTML“、”图片“等资源为”原材料“,去”生产“一个可以运行的项目的过程。
    • 编译
    • 部署
    • 搭建

编译:Java 源文件(User.java)—> 编译 —> Class 字节码文件(User.class)—> 交给 JVM 去执行。
部署:一个 B / S 项目最终运行折并不是动态 Web 工程本身,而是这个动态 Web 工程”编译“的结果。
eg. 生的鸡 —> 处理 —> 熟的鸡。
动态 Web 工程 —> 编译、部署 —> 编译结果。


Maven 运行时环境。

在这里插入图片描述


一只煮熟的鸡。

Java 源代码经过编译后会生成 .class 文件,这些文件会以和源码相同的目录结构存在与 target/ 目录下。

在这里插入图片描述

在这里插入图片描述


自动化构建和构建环节。

构建就是以我们写的 Java 代码、框架配置文件、国际化等其他资源文件、jsp 页面和图片等静态资源文件作为”源材料“,去”生产“一个可以运行的项目的过程。

  • 构建包含的环节。

清理:将以前编译得到的旧的 class 字节码文件删除,为下一次编译做准备。
编译:将 Java 源程序编译成 class 字节码文件。
测试:自动测试,自动调用 junit 程序。
报告:测试程序执行的结果。
打包:动态 Web 工程打 war 包,Java 工程打 jar 包。
安装:Maven 特定的概念——将打包得到的文件复制到”仓库“中的指定位置。
部署:将动态 Web 工程生成的 war 包复制到 Servlet 容器的指定目录下,使其可以运行。

  • 自动化构建。

在这里插入图片描述


Maven 使用。

  • JAVA_HOME 环境变量。
  • 解压 Maven。(放在无中文无空格路径下)。
  • 配置 Maven 环境变量。(MAVEN_HOME or M2_HOME(M2_HOME 是 2 版本的命名,3 版本也可以使用,向下兼容))。
geek@geek-PC:~$ vim ~/.bashrc 

# maven.
export PATH=/home/geek/geek/tools_my/apache-maven-3.5.4/bin:$PATH
geek@geek-PC:~$ mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14+08:00)
Maven home: /home/geek/geek/tools_my/apache-maven-3.5.4
Java version: 1.8.0_241, vendor: Oracle Corporation, runtime: /home/geek/geek/tools_my/jdk1.8.0_241/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-30deepin-generic", arch: "amd64", family: "unix"

Maven 核心概念。

  • 约定的目录结构。

  • POM。

  • 坐标。

  • 依赖。

  • 仓库。

  • 生命周期 / 插件 / 目标。

  • 继承。

  • 聚合。

  • Maven 约定目录结构。

根目录:工程名。
src 目录:源码。
pom.xml 文件:Maven 工程的核心配置文件。
main 目录:存放主程序。
test 目录:存放测试程序。
java 目录:存放 Java 源码文件。
resources 目录:存放框架或其他工具的配置文件。

为什么要遵循约定的目录结构。?

  • Maven 要负责我们这个项目的自动化构建,以编译为例,Maven 想要自动进行编译,那么 ta 必须知道 Java 源文件保存在哪里。
  • 如果我们自己自定义的东西想要让工具或框架知道在哪里,有两种方法:
    • 以配置文件的方式告诉框架。
      classpath:spring-context.xml
    • 遵守框架内部已经存在的约定。
      log4j.properties
      log4j.xml

约定 > 配置 > 编码。


Maven 常用命令。

mvn clean —> 清理。
mvn validate —> 证实。
mvn compile —> 编译主程序。
mvn test —> 编译测试程序。
mvn package —> 打包。
mvn verify —> 证实。
mvn install —> 安装。
mvn site —> 生成站点。
mvn deploy —> 部署。

打开 /apache-maven-3.5.4/conf,修改 settings.xml 配置文件。
<!-- --> 注释区域下添加 <localRepository> </localRepository> 标签对,在其中写入刚才创建的 maven_repository 完整路径。

  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
<localRepository>/home/geek/geek/tools_my/maven_repository</localRepository>

  • 更改 maven 仓库源。

打开 maven 的配置文件(一般在 maven 安装目录的 conf/settings.xml),在 <mirrors> </mirrors> 标签中添加 mirror 子节点。

<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>
  • POM。

POM。——Project Object Model。项目对象模型。

pom.xml 对象 Maven 工程是核心配置文件,与构建过程相关的一切设置都在这个文件中去设置。
重要程度相当于 web.xml 对象动态 Web 工程。

  • 坐标。
  • 数学中的坐标。
    在平面上,使用 X、Y 两个向量可以唯一定位平面中任何一个点。
    在空间上,使用 X、Y、Z 三个向量可以唯一定位空间中任何一个点。

  • Maven 中的坐标。
    使用以下三个向量在仓库中唯一定位一个 Maven 工程。

    groupId:公司或组织域名的倒序 + 项目名。
    artifactId:模块名。
    version:版本。

Maven 工程的坐标与仓库中路径的对应关系。

<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
~~~
org/framework/spring-context/5.0.2.RELEASE/spring-context-5.0.2.RELEASE.jar
  • 仓库。

仓库的分类。

本地仓库:当前电脑上部署的仓库目录,为当前电脑上所有 Maven 工程服务。
远程仓库:

私服(Nexus):架设在当前局域网环境下,为当前局域网内所有 Maven 工程服务。
中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
中央仓库的镜像:架设在各大洲,为中央仓库分担流量,减轻中央仓库的压力,同时更快的响应用户请求。

如果工作中电脑不能联网,就要用私服(Nexus)。

在这里插入图片描述

仓库中保存的内容:Maven 工程。

Maven 自身所需要的插件。
第三方框架或工具的 jar 包。(第一方:jdk。第二方:“我”)。
我们自己开发的 Maven 工程。

  • 依赖。

Maven 解析依赖信息时会到本地仓库中去查找被依赖的 jar 包。
// 对于我们自己开发的 Maven 工程,使用 install 命令安装后就可以进入仓库。
// > mvn install

依赖的范围。

在这里插入图片描述

compiled

对主程序是否有效:√
对测试程序是否有效:√
是否参与打包:√
是否参与部署:√

test

对主程序是否有效:×
对测试程序是否有效:√
是否参与打包:×
是否参与部署:×
典型 eg. junit

provided

对主程序是否有效:√
对测试程序是否有效:√
是否参与打包:×
是否参与部署:×
典型 eg. servlet-api.jar
如果不加 provided,运行后就会报 java.lang.NullPointerException

provided 理解。
当项目运行在服务器时,服务器已经提供了 Servlet(Tomcat),如果还用 Maven 工程中的 servlet-api.jar ,就会产生冲突。provided 仅表示在maven 工程中提供此 jar 包,在部署到服务器后就不再提供。

在这里插入图片描述

  • 生命周期。

各个构建环节执行的顺序。
Maven 的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务由插件来完成。
Maven 核心程序是为了更好的实现自动化构建,按照这一特点执行生命周期中的各个阶段。(不论现在要执行生命周期中的哪一个阶段,都是从该生命周期最初的位置开始执行)。

Maven 有三套相互独立的生命周期。

Clean Lifecycle —> 在执行真正的构建之前进行一些清理工作。
Default Lifecycle —> 构建的核心部分。编译,测试,打包,安装,部署等。
Site Lifecycle —> 生成项目报告、站点,发布站点。

ta 们是相互独立的,你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然也可以直接运行 mvn clean install site 运行所有这三套生命周期。

clean 生命周期。

pre-clean —> 执行一些需要在 clean 之前完成的工作。
clean —> 移除所有上一次构建生成的文件,
post-clean —> 执行一些需要在 clean 之后立即完成的工作。

site 生命周期。

pre-site —> 执行一些需要在生成站点文档之前完成的工作。
site —> 生成项目的站点文档。
post-site —> 执行一些需要在生成站点之后完成的工作,并且位部署做准备。
site-deploy —> 将生成的站点文档部署到特定的服务器上。
这里经常使用的是 site 阶段和 site-deploy 阶段,用以生成和发布 Maven 站点,这可是 Maven 相当强大的功能,Manager 比较喜欢,文档及统计数据自动生成。

Default 生命周期。

Default 生命周期是 Maven 生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里,只介绍一些比较重要和常用的阶段。

Validate
generate-sources
process-sources
generate-resources
process-resources —> 复制并处理资源文件,至目标目录,准备打包。
compile —> 编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources —> 复制并处理资源文件,至目标测试目录。
test-compile —> 编译测试源代码。
process-test-classes
test —> 使用合适的单元测试框架进行测试,这些测试代码不会被打包或部署。

  • 插件和目标。

生命周期的各个阶段仅仅定义了要执行的任务是什么。
各个阶段和插件的目标是对应的。
相似的目标由特定的插件来完成。

生命周期阶段 插件目标 插件
compile compile maven-compiler-plugin:3.8.1
test-compile testCompile maven-compiler-plugin:3.8.1

可以将目标看作“调用插件功能的命令”。


使用 Maven 项目运行程序时,报出警告

Warning:java: source value 1.5 is obsolete and will be removed in a future release
Warning:java: target value 1.5 is obsolete and will be removed in a future release
Warning:java: To suppress warnings about obsolete options, use -Xlint:-options.

这是因为 Maven 内置 jdk 编译环境是 1.5 版本。
使用 maven 开发项目时,不会使用 IDEA 设置的 jdk,而是使用 Maven 内置的 jdk 编译器。
如需使用较新的版本,需要我们自己指定版本号。

只要在项目的 pom 文件中加入
<project> </project> 标签内)。

<project>

<build>
    <!--[...]-->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
    <!--[...]-->
</build>

</project>

这样在下一次运行程序时就不会报出警告。


ps:jdk 1.5 和 jdk 1.8 主要差异。

List<String> list = new Array<>();
List<String> list = new Array<String>();// jdk 1.5 必须在 <> 中加入 泛形。

  • 依赖。

依赖的传递。

子工程可以继承父工程的依赖。
注意:非 compile 范围的依赖不能传递。(test, provided)。

依赖的排除。
也有传递性。
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>...</groupId>
            <artifactId>...</artifactId>
        </exclusion>
    </exclusions>
</dependency>

依赖的原则。

作用:解决模块工程之间的 jar 包冲突问题。

  • 就近原则 / 路径最短者优先。
  • 路径相同时标签先声明者优先。

统一管理依赖的版本。

<properties></properties> 标签内使用标签统一声明版本号。
在需要统一版本的位置,使用 ${自定义标签名} 引用。


    <properties>
        <geek.spring.version>5.0.2.RELEASE</geek.spring.version>
    </properties>


    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${geek.spring.version}</version>
            <!--<version>5.0.2.RELEASE</version>-->
        </dependency>

    </dependencies>

继承。

eg. junit 是 test 范围的依赖不能传递,所以必然会分散在各个模块中,很容易造成版本不一致。

=》 解决:将 junit 依赖版本统一提取到“父”工程中,在子工程中声明依赖时不指定版本,以父工程中统一设定的版本为准,同时便于修改。

注意:父工程打包方式:pom。
在子工程的 <parent></parent> 标签中要添加 <relativePath>../Parent/pom.xml</relativePath>,// 以当前工程的 pom.xml 文件为基准,写入父工程 pom.xml 文件的相对路径。

父工程中使用 <depenndencyManagement></depenndencyManagement>

<dependencyManagement>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

子工程中使用。就不需要 <version></version> 标签了。

<dependencies>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>


聚合。

如果没有聚合,例如 a <— b <— c。 b 依赖 a,c 依赖 b。
要运行 c,必须先 install a,再 install b。一个一个安装太麻烦。

聚合 —> 一键安装。
配置方式:。

<modules>
    <module>../spring_coupling</module>
    <module>../spring_factory</module>
</modules>

在此工程中运行 maven install。
所聚合的两个模块会一起安装。


Maven Web 工程自动部署。

将写好的工程打 war 包,放入 Tomcat 的 webapps 目录下,启动 Tomcat,Tomcat 会自动将 .war 包解压至当前目录下。

自动 ==》 cargo 插件。


Maven 仓库。

mvnrepository

发布了47 篇原创文章 · 获赞 1 · 访问量 1175

猜你喜欢

转载自blog.csdn.net/lyfGeek/article/details/104618654
今日推荐