Maven(一)

·  阅读 46

Maven

Maven的优势?

1 依赖管理【jar包管理】

​ 传统的jar包很容易造成大量的冗余【如a工程的jar包b工程也要用】,而且jar包之间可能会有依赖关系,需要找到所有的jar包。找jar不方便,也可能不安全。

​ maven可以解决这些问题。maven可以帮我们直接到统一的官方仓库中直接找到jar包。每个服务器上都有一个本地库,用来存放从官方库下载的jar包。这个服务器上的任意项目如果要用jar包,从本地库引用就可以了。同一台服务器上共用一份jar包。而且maven可以发现jar包的依赖关系,将依赖的包也下载下来。

2 项目管理

​ 可以将一个项目分成多个模块,每个模块可以分布到不同的服务器上。如何实现各个模块直接的管理调用,分布式部署。Maven可以搞定。

3 项目的目录结构

​ 约定大于配置,配置大于编码。Maven的项目结构是统一的。

maven是什么?

他是一款自动化构建【build】工具。

maven的核心?

Maven之所以能够实现自动化的构建,和它的设计是紧密相关的。我们对Maven的学习围绕它的九个核心概念展开。

① 仓库管理

② POM

③ 约定的目录结构

④ 坐标

⑤ 依赖管理

⑥ 生命周期

⑦ 插件和目标

⑧ 继承

⑨ 聚合

Maven构建的主要环节

构建过程包含的主要的环节:

①清理:删除以前的编译结果,为重新编译做好准备。

②编译:将Java源程序编译为字节码文件。

③测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。

④报告:在每一次测试后以标准的格式记录和展示测试结果。

⑤打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包。

⑥安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。

⑦部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。

仓库repository

仓库里有什么

放构件(artifact),包括以下三种

  1. 第三方框架或工具的jar包
  2. Maven的插件plugin
  3. 我们自己开发的项目模块

仓库分类

  1. 本地仓库
  2. 远程仓库
    • 中央仓库【默认】mvnrepository.com/
    • 镜像仓库【为了减轻中央仓库负担,更快响应用户请求,这个仓库就是把中央仓库所有文件复制了一份存起来,如阿里Maven镜像】
    • 私服【私服代理广域网上的远程仓库,供局域网内的用户使用】

访问仓库的步骤

Maven根据坐标寻找构件的时候,它会首先查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库没有,或者要查看是否有更新版本,就去访问远程仓库【去找私服,如果没有私服,就去找中央仓库】

Maven安装

1.检查JAVA_HOME是否正确

2.下载安装包

3.解压【安装路径不要有中文、空格等特殊字符】

bin:mvn(maven) mvn的执行文件

conf:settings.xml Maven的配置文件

4.配置环境变量

Java:JAVA_HOME PATH

Tomcat:CATALINA_HOME PATH

Maven : M2_HOME(低版本MAVEN_HOME) Maven主目录 PATH 可执行文件的路径bin

5.验证安装是否正确

C:\Users\Administrator>mvn -v
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: C:\Java\apache-maven-3.6.3\bin\..
Java version: 1.8.0_161, vendor: Oracle Corporation, runtime: C:\Java\jdk1.8.0_161\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

C:\Users\Administrator>mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: C:\Java\apache-maven-3.6.3\bin\..
Java version: 1.8.0_161, vendor: Oracle Corporation, runtime: C:\Java\jdk1.8.0_161\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

复制代码

注意:设置了环境变量,要重新启动cmd

6.指定本地仓库【可选】

本地仓库必须有,但是有默认位置:用户家目录/.m2/repository。

conf/settings.xml可以指定额外的位置

<localRepository>D:/repository</localRepository>
复制代码

7.配置阿里云提供的镜像仓库【可选】

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

8.配置Maven工程的基础JDK版本【可选】

该配置对当前服务器的所有的Maven工程有效,这是一个全局配置。

此处不配置,默认JDK编译版本是JDK5,但是可以在每个工程进行单独配置,局部的配置

<profile>
    <id>jdk-1.8</id>
    <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>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    </properties>
</profile>

复制代码

maven目录结构

Maven目录结构.png

Java项目的类型

Maven的项目类型有多种,和我们开发相关的项目类型主要有三种:

  • Java项目:被打包为jar包。

  • web项目:打包为war包

  • pom项目:pom项目中不写Java代码, 用来做父项目,用于进行子项目的管理

    其中Java项目是默认项目类型,在pom.xml中通过<packaging>来标记项目类型。这里先创建java项目。

maven命令

clean在一个生命周期中

compile test-compile test package install在一个生命周期中

执行同一个生命周期的后一个操作,会从第一个操作开始依次全自动执行。

命令作用
mvn compile只编译主代码,放入target目录
mvn clean删除target目录
mvn test-compile编译主代码和测试代码,放入target目录(resouces也会拷入target目录)
mvn test编译主代码和测试代码,放入target目录(resouces也会拷入target目录),并且运行测试用例
mvn package编译主代码和测试代码,放入target目录(resouces也会拷入target目录),并且运行测试用例,将当前项目打包成一个jar
mvn install完成mvn package的所有功能,并且将当前jar上传到本地库(其他项目也可以使用)
mvn deploy在install基础上,将当前的jar上传到远程库(需要更多的条件)

IDEA继承Maven

​ 我们安装了Maven之后需要在idea中将本地的Maven集成进来。

集成Maven-1.jpg ​ idea内嵌的Maven的支持,我们不使用它的内嵌版本,而是绑定我们刚刚安装的版本。需要指定Maven的安装目录、配置文件路径、本地仓库的路径。

集成Maven-2.jpg

优化配置:-DarchetypeCatalog=internal:每次创建项目时,IDEA要使用插件进行创建,这些插件当创建新项目时,它每次都会去中央仓库下载,这样使得创建比较慢。应该在创建时让它找本地仓库中插件进行创建项目。注意:-D<property>=<value>,-D代表要添加或覆盖属性。

集成Maven-3.jpg

在IDEA中创建Maven Java工程

![](pic\创建Maven Java工程-1.jpg)

创建Maven Java工程-1.jpg 指定项目的坐标:

  • GroupId:当前项目所属组织ID。一般采用分级结构,域名倒写。
  • ArtifactId:构件ID。当前项目的ID。
  • Version:当前项目的版本。SNAPSHOT是快照的意思,意为开发版;RELEASE 代表稳定版。

以上三项构成当前项目的唯一坐标。

![](pic\创建Maven Java工程-2.jpg)

创建Maven Java工程-2.jpg 如果弹出Maven project need to be import,是提示Maven项目需要导入变化,选择Import Changes即可。一般不选择Enable Auto-Import。

![](pic\创建Maven Java工程-3.jpg)

创建Maven Java工程-3.jpg

pom.xml中添加JUnit、lombok依赖

<?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.atguigu.maven</groupId>
    <artifactId>_01_maven_java</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
复制代码

Lombok

什么是Lombok

以前的Java项目中,充斥着太多不友好的代码:POJO的getter/setter/toString;异常处理;I/O流的关闭操作等等,这些样板代码既没有技术含量,又影响着代码的美观,Lombok应运而生。

Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注解实现这一目的。

@Data集成了@Getter和@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor这几个注解与一身,是一个非常强大的注解,这个注解更可以简化注解的代码量
@getter在JavaBean中使用,注解会生成对应的getter方法
@setter在JavaBean中使用,注解会生成对应的setter方法
@NoArgsConstructor在JavaBean中使用,注解会生成对应的无参构造方法
@AllArgsConstructor在JavaBean中使用,注解会生成对应的有参构造方法
@ToString在JavaBean中使用,注解会自动重写对应的toStirng方法
@ToString(exclude={"column1","column2"})排除多个column列所对应的元素
@ToString(of={"column1","column2"})只生成包含多个column列所对应的元素
@EqualsAndHashCode在JavaBean中使用,注解会自动重写对应的equals方法和hashCode方法
@Slf4j在需要打印日志的类中使用,项目中使用slf4j日志框架
@Log4j在需要打印日志的类中使用,项目中使用log4j日志框架

如何在idea中使用lombok

第一步:导入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
复制代码

第二步:添加插件

Lombok插件-1.png 第三步:进行配置

Lombok插件-2.png 第四步:使用lombok

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer userId; //Integer  0 null  int  null
    private String userName;
    private Integer age;//阿里开发规范中规定,不使用基本数据类型作为成员变量的类型
    private String address;

}
复制代码

使用Maven创建Java Web

方法1【重要】

  1. 创建Maven的Java项目

  2. pom.xml指定类型为war包

    <packaging>war</packaging>
    复制代码
  3. 添加web支持

1-web-1.jpg

  1. 指定web.xml的位置

1-web-2.jpg 5. 指定web项目的根目录

1-web-3.jpg

  1. 添加web资源

    • 静态网页
    • Thymeleaf模板文件
    • 图片

    注意:

    • WEB-INF/下的内容无法在客户端直接输入网址来访问,必须间接访问。先访问服务器端的一个可以访问的资源,然后再转发(不可以是重定向,重定向其实是客户端的访问)到WEB-INF下的资源。
    • Thyemeleaf其中的动态标签<th>必须经过Thymeleaf解析器解析后才可以看到最终的结果,如果直接访问,动态标签<th>没有进行处理。所以在项目中一般把thymeleaf也放入到WEB-INF/tempates下。
  2. 部署到服务器并进行访问

    1. 配置tomcat

    2. 增加新的Tomcat

    3. 服务器配置

    4. 部署配置

    5. 运行tomcat

    6. 访问资源:

      • 静态网页 :可以直接访问
      • Thymeleaf模板文件:即使没有放在WEB-INF下,也不要直接访问
      • 图片:可以直接访问
      • WEB-INF/ 不可以访问
    7. 解决控制台乱码

      1. 点击Help => Edit custom VM Options,在最后面添加 “-Dfile.encoding=UTF-8”

      2. 点击右上角 Edit Configurations,在tomcat配置中的 VM option中添加 “-Dfile.encoding=UTF-8”

      在第二步的Startup/Connection页签的Run和Debug添加一个key为JAVA_TOOL_OPTIONS, value为“-Dfile.encoding=UTF-8”

      的环境变量

      1. 保存后重启idea,可以发现控制台中文乱码显示正常了

      如果还不行,那要放大招了(其实可以直接放大招的):

      其实出现乱码的是Tomcat的日志乱码,到tomcat8的conf/logging.properties,找到一行java.util.logging.ConsoleHandler.encoding = UTF。将其编码类型修改为另外一个即可。

方法2【需要下载插件】

  1. 下载JBLJavaToWeb插件【如果有就不用了】

打开setting

2-web-1.jpg 2. 创建普通java maven项目

  1. 右键选中项目模块,点击“JBLJavaToWeb”

2-web-2.jpg 4. 结果如图所示,增加了Web项目的目录支持,并在pom.xml中添加<packaging>war</packaging>

方法3【使用骨架,有不足】

  1. 选择Maven的项目类型

3-web-1.jpg 2. 输入坐标 3. 确认配置

3-web-2.jpg

  1. 保存项目

注意:此时项目的类型为war类型,而不再是jar类型了。

项目结构是

3-web-3.jpg

可以发现,不是标准项目结构,需要手动解决。

  1. 手动解决项目问题
  • main目录下没有java、resources目录
  • 没有test目录
  • web.xml中dtd版本低(将无法解析EL)
  • pom.xml中内容可以精简,build内容可以删除
  • pom.xml中没有Servlet、JSP依赖

手动解决这些问题吧,记得将java、resouces目录标记为相应的Root目录。

坐标

Maven的坐标

Maven的坐标元素包括groupId、artifactId、version、packaging、classfier等,

其中groupId、artifactId、version是必须定义的,即可唯一的标记一个坐标,称为坐标三要素,简称GAV。

[1]groupId:公司或组织的域名倒序+当前项目名称

[2]artifactId:当前项目的模块名称

[3]version:当前模块的版本

<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
复制代码

坐标和仓库中jar包的存储路径之间的对应关系

以当前定义的Java项目的坐标为例说明对应关系。

<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
复制代码

[1]将gav三个向量连起来

com.atguigu.maven+Hello+0.0.1-SNAPSHOT
复制代码

[2]以连起来的字符串作为目录结构到仓库中查找。jar的名称是artifactId-version.jar

com/atguigu/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
复制代码

※注意:我们自己的Maven工程必须执行安装操作才会进入仓库。安装的命令是:mvn clean install

使用tomcat7-maven-plugin运行web项目

  1. 在pom.xml中添加配置信息。

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.tomcat.maven</groupId>
          <artifactId>tomcat7-maven-plugin</artifactId>
          <version>2.2</version>
          <configuration>
            <!--配置tomcat启动的端口号-->
            <port>8080</port>
            <!--配置项目的上下文路径-->
            <path>/mvnweb</path>
          </configuration>
        </plugin>
      </plugins>
    </build>
    复制代码
  2. 在Maven窗口中选择tomcat7插件,利用其中的tomcat7:run来启动服务器。

此处的tomcat7只是为了和正在使用的tomcat8.5区分开来,正式开发中尽量不要使用tomcat7来开发,它有很多不足。

Maven生命周期

Maven有三套相互独立的生命周期,分别是:

①Clean Lifecycle 在进行真正的构建之前进行一些清理工作。

②Default Lifecycle构件的核心部分,编译,测试,打包,安装,部署等等。

③Site Lifecycle生成项目报个,站点,发布站点。

​ 前面三个生命周期是彼此独立的。在任何一个生命周期内部,执行任何一个具体环节的操作,都是从本周期最初的位置开始执行,直到指定的地方。

​ 但是注意:执行install命令时,会执行default生命周期的前面的所有阶段。但是不会执行clean阶段,因为不是同一套生命周期。

​ Maven之所以这么设计其实就是为了提高构建过程的自动化程度:让使用者最关心最终要干的事情即可,过程中的各个环节是自动执行的。

插件

​ Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。

​ 每个生命周期中都包含着一系列的阶段。这些阶段就相当于Maven提供的统一的接口,然后这些阶段的实现由Maven的插件来完成。

​ 每个插件都能实现多个功能,每个功能就是一个插件目标。

​ 我们在输入mvn命令的时候,比如mvn clean,clean对应的就是clean生命周期中的clean阶段。clean的具体操作就是由maven-clean-plugin来实现的。

​ 所以说Maven生命周期的每一个阶段的具体实现都是由Maven插件实现的。Maven实际上是一个依赖插件执行的框架,每个任务实际上都是由插件完成的。

Maven插件列表的官网页面:maven.apache.org/plugins/

Maven插件的下载位置:本地仓库:\org\apache\maven\plugins

可以将该目录下所有插件全部删掉,然后一次执行各个命令,可以清楚的看到Maven远程仓库下载对应插件的过程。

依赖传递

依赖和范围

依赖范围编译(main)测试(test)运行示例
compilelog4j
provided×servlet-api lombok
test××junit
runtime×JDBC驱动类
system×
import×××

如何建立两个项目之间的依赖关系:moduleB依赖于moduleC

<dependencies>
    <dependency>
        <groupId>com.atguigu.maven</groupId>
        <artifactId>pro03_moduleC</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

复制代码

C的资源,B可以使用哪些?

依赖可见范围.png

依赖冲突

路径最短者优先路径相同时先声明者优先。

依赖排除

<dependency>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro03_moduleB</artifactId>
    <version>1.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

复制代码

排除jar时,不需要写version.

统一管理依赖版本

<properties>
    <spring-version>5.2.5.RELEASE</spring-version>
    <moduleB-version>1.0-SNAPSHOT</moduleB-version>
    <moduleD-version>1.0-SNAPSHOT</moduleD-version>
</properties>

复制代码

好处:统一的管理依赖的版本,便于对版本的修改。

继承

问题:有了依赖,为什么还要有继承

因为:依赖,只能使用compile的依赖,test、provided无法使用。

特点

  1. 父项目必须是pom类型
  2. 父项目本身不提供新的源码功能,src目录可以删除
  3. 子项目可以从父项目中继承test、compile、provided依赖
  4. 父项目建议发布到本地库
  5. 缺点:父项目子项目是父子关系,但是在其实是并列的项目,需要分别构建。

问题:父项目的全部资源会自动的被子项目继承。但是不同的子项目可能只需要其中的一部分。怎么办:

解决:dependencyManagement

父项目:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
</dependencyManagement>

复制代码

子项目:需要就引入,不引人就无法使用;如果版本一致,引入是省略版本号。

好处:便于以后的版本修改,只要修改父项目的版本即可。

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.9</version>
    </dependency>
</dependencies>

复制代码

聚合

问题:有了继承,为什么还需要聚合

父项目子项目是父子关系,但是在其实是并列的项目,需要分别构建。

​ 聚合关系是指多个项目共同组成一个项目。 用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。对外看起来是一个项目。

​ 对父项目进行构建,会自动的对所有的子项目构建。

​ 聚合关系首先是一种继承关系

父项目:

<groupId>com.atguigu.maven</groupId>
<artifactId>pro05_shopping</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
    <module>order</module>
    <module>product</module>
    <module>payment</module>
</modules>


复制代码

子项目

<parent>
    <artifactId>pro05_shopping</artifactId>
    <groupId>com.atguigu.maven</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>order</artifactId>

复制代码

子项目的坐标可以省略groupid和version

对父项目进行构建,会对所有的子项目进行构建。

如果对一个子项目进行构建,不会影响其他子项目。

Jar下载失败的问题分析

正常下载的情况

​ jar包在下载过程中,jar包的扩展名是xxx.jar.lastUpdated。jar包下载成功后,Maven会将lastUpdated扩展名删除,让jar包恢复为xxx.jar这样的名称

下载失败的第一种情况

1、Maven的行为描述

jar包在下载过程中,jar包的扩展名是xxx.jar.lastUpdated

网络连接丢失,无法继续下载

jar包没有下载完,lastUpdated扩展名不会被删除

当我们要求Maven重新下载时,Maven看到这个jar包的扩展名是lastUpdated,Maven就不管了

2、解决办法

手动删除所有以lastUpdated结尾的文件,然后让Maven重新下载。可是当仓库中lastUpdated文件太多的时候,手动删除不可行,所以我们需要借助批处理文件:clearLastUpdated.bat。使用方法:

  • 将clearLastUpdated.bat文件复制到本地仓库的根目录
  • 使用文件编辑打开clearLastUpdated.bat文件
  • 修改下面的内容

SET CLEAR_PATH=设置为本地仓库所在的盘符 SET CLEAR_DIR=设置为本地仓库的根目录的路径

例如:

SET CLEAR_PATH=D: SET CLEAR_DIR=D:\maven-rep1026

  • 在想要执行清理时,双击运行这个文件即可

然后要求Maven重新下载jar包。

失败的第二种情况

1、文件校验工具

​ jar包表面上看起来是下载完的状态,结尾并没有“.lastUpdated”扩展名。但是程序运行时找不到这个jar包中的类。例如:针对jar包中的类出现ClassNotFoundException。

​ 遇到类似问题需要先确认一下“有嫌疑”的jar包是否存在内部损坏问题。此时可以使用上面的文件校验工具。

2、用法

  • 打开文件校验工具
  • 将待校验的jar包拖拽到文件校验工具窗口内
  • 将待校验的jar包旁边的*.sha1文件打开
  • 比较两个SHA1值
  • 一致:jar包完好
  • 不一致:jar包损坏

3、原理

HASH加密包括很多具体加密算法,但是所有HASH算法都满足下面特征:

  • 只要输入数据不变,任何时候执行加密,输出不变
  • 输入数据有细微变化,输出数据跟着变化
  • 不可逆,不能通过密文反推回明文
  • 每一种具体的HASH加密算法加密后长度固定

4、找到有嫌疑的jar包

假设现在出现了一个ClassNotFoundException,提示找不到类:org.springframework.expression.Expression。此时我们怀疑这个类所在的jar包下载失败。

  • 窍门1:类所在的package命名往往和jar包坐标的groupId部分类似。
  • 窍门2:在IDEA中按两下Shift键,使用全类名搜索

为什么不建议删整个库

​ 1. 整个库删除后,需要重新下载整个库。此时东边的jar包没有失败,可能西边的jar包会失败。

​ 2. 整个库整体重新下载时,会有很多jar包并行下载的,相对来说并行下载本身就容易丢失数据。

分类:
后端
标签:
分类:
后端
标签: