Maven基礎

前言

本文以當前最新發布版maven-3.6.3爲例.酌情參考.

倉庫

得益於座標機制,任何Maven項目使用任何一個構建的方式都是完全相同的。在此基礎上,Maven可以在某個位置統一存儲所有Maven項目共享的構件。這個統一的位置就是倉庫。實際的Maven項目將不再各自存儲其依賴文件,它們只需要聲明這些依賴的座標,在需要的時候Maven會自動根據座標找到相應的構件。

分類

Maven倉庫的分類不能一概而論,根據不同的角度可以大致羅列如下:

位置分類

Maven實戰》中將倉庫分爲:

本地倉庫主要起緩存作用,默認在~/.m2/repository

可以通過~/.m2/settings.xml中的<localRepository>修改。

發佈分類

根據是否發佈,可以分爲SNAPSHOTRELEASE兩類。

性質分類

私服Nexus中將倉庫分類爲hostedgroupproxy

hosted

一般只包含SNAPSHOTRELEASE兩類。因此Nexus內置了maven-snapshotsmaven-releases

group

顧名思義就是組,可以自由組合,類型不限。Nexus內置了maven-public

proxy

proxy只能一次代理一個目標倉庫。一般都是將生成某一類proxy地址歸併到一個group中,形成類似Nginx反向代理的效果。

proxy類型應該是私服用的最多的類型。

Nexus內置了maven-central,它默認代理的是https://repo1.maven.org/maven2/

結構

Maven的目錄結構看起來比較簡單,包括:

├── bin
├── boot
├── conf
│   └── logging
└── lib
    ├── ext
    └── jansi-native
        ├── freebsd32
        ├── freebsd64
        ├── linux32
        ├── linux64
        ├── osx
        ├── windows32
        └── windows64

bin

bin主要存放命令行的執行腳本,包括mvnmvnDebug。此外還有m2.conf文件.這是classworlds的配置文件.

boot

只有一個文件plexus-classworlds-x.x.x.jar,是一個類加載器框架.一般不用關心.

conf

配置文件夾.包含最重要的settings.xml.

lib

用以存放maven運行時需要的Java類庫.包含maven自身及第三方依賴.

在當前版本3.6.3中,該目錄下的maven-model-builder-3.6.3.jarorg.maven.model下存放了全局的pom-4.0.0.xml,它定義了默認的central倉庫鏈接:https://repo.maven.apache.org/maven2.

座標

項目座標

指的是pom.xml最外一層的xml元素,常用的包括groupId,artifactId,version,packaging,dependencyManagementbuild.

packaging

該元素定義Maven項目的打包方式.首先,打包方式通常與所生成構件的文件擴展名稱對應.默認爲jar,可供選類型包括但不限於jar,war,earpom.之所以不限是因爲打包插件可以自定義類型.

依賴座標

依賴座標是最最常用的元素了,這裏指對應pom.xml<dependency>.

包括groupId,artifactId,version,classifier,typeexclusions.

type

一個依賴座標對應的文件格式一般爲$artifactId-$version-$classifier,擴展名一般是$type,它的默認值是jar,不過儘管它通常表示依賴項文件名的擴展名,但並非總是如此。 可以將類型映射到其他擴展名和classifier。 這種類型通常對應於所使用的包裝,儘管並非總是如此。 可供選項包括jarwarejb-clienttest-jar。 可以通過將擴展名設置爲true的插件來自定義新類型,因此這不是完整列表。

classifier

幫助定義構件輸出的一些附屬構件.比如文檔和源代碼.對應的classifier就分別是javadocsources.

另外,常用的選項還有pom,通常表示一些父依賴.

比較經典的應用是net.sf.json-lib:json-lib,必須指定classifier纔可正常工作.

    <dependency>
      <groupId>net.sf.json-lib</groupId>
      <artifactId>json-lib</artifactId>
      <version>2.4</version>
      <classifier>jdk15</classifier>
    </dependency>

注意:

不能直接定義項目的classifier因爲附屬構件不是項目直接默認生成的,而是由附加的插件幫助生成.

scope

依賴範圍:

依賴範圍 編譯 測試 運行 例子
compile Y Y Y spring-core
test - Y - Junit
provided Y Y - servlet-api
runtime - Y Y oracle-jdbc驅動
system Y Y - 本地的,Maven倉庫之外的類庫文件
<systemPath>搭配使用

配置文件

$MAVEN_HOME/conf/settings.xml是全局配置文件。一般不建議修改

當我們初次執行操作,如mvn help:system時會創建~/.m2repository目錄,同時生成空的settings.xml用以存放用戶級別的配置。用戶根據需要修改~/.m2/settings.xml

<settings>
  <!-- 本地倉庫位置,默認路徑: ${user.home}/.m2/repository -->
  <localRepository>/path/to/local/repo</localRepository>
  <!-- 交互模式,默認開啓  -->
  <interactiveMode>true</interactiveMode>
  <!-- 離線模式,默認關閉-->
  <offline>false</offline>
  <!-- 插件組-->
  <pluginGroups> </pluginGroups>
  <!-- 代理-->
  <proxies></proxies>
  <!-- 認證 -->
  <servers></servers>
  <!-- 鏡像-->
  <mirrors> </mirrors>
  <!-- 環境 -->
  <profiles> </profiles>
  <activeProfiles> </activeProfiles>
</settings>

localRepository

用以指定本地倉庫位置.

pluginGroups

當插件的組織Id(groupId)沒有顯式提供時,供搜尋插件組織Id(groupId)的列表。該元素包含一個pluginGroup元素列表,每個子元素包含了一個組織Id(groupId)。當我們使用某個插件,並且沒有在命令行爲其提供組織Id(groupId)的時候,Maven就會使用該列表。默認情況下該列表包含了org.apache.maven.pluginsorg.codehaus.mojo.

proxy

有時候所在公司基於安全考慮,要求使用通過安全認證的代理訪問互聯網.這時候就需要爲其配置HTTP代理,才能正常訪問和下載.可供配置標籤:

<proxies> 
	<proxy>
      <!-- 可選 -->
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
</proxies>

proxies下可以有多個proxy元素,如果聲明瞭多個,則默認情況下第一個被激活的會生效.

nonProxyHosts用來指定哪些主機不需要被代理.可以使用|符號來分隔多個,同時支持通配符*,比如*.aliyun.com.

servers

用來配置遠程倉庫的認證信息,其中serveridpom.xml中的repositoryid一一對應.

    <servers>
        <server>
            <id>swb</id>
            <username>admin</username>
            <password>XXXX</password>
            <privateKey>~/.ssh/id_rsa</privateKey>
            <!--私鑰密碼-->
            <passphrase>XXX</passphrase>
        </server>
    </servers>

profiles

類似springboot中的profile,針對不同的環境開啓不同的配置,比如在settings.xml中設置統一的默認編譯版本:

    <profiles>
        <profile>
            <id>java8</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>
            </properties>
        </profile>
        <profile>
            <id>java9</id>
            <activation>
                <activeByDefault>false</activeByDefault>
                <jdk>9</jdk>
            </activation>
            <properties>
                <maven.compiler.source>9</maven.compiler.source>
                <maven.compiler.target>9</maven.compiler.target>
                <maven.compiler.compilerVersion>9</maven.compiler.compilerVersion>
            </properties>
        </profile>
    </profiles>

    <activeProfiles>
        <activeProfile>java8</activeProfile>
<!--        <activeProfile>java9</activeProfile>-->
    </activeProfiles>

除此之外,還可以通過命令行-P參數指定:mvn compile -Pjava8.

pom.xml

就像makeMakefile,Antbuild.xml一樣,pom.xmlMaven項目的核心.

<?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>org.example</groupId>
    <artifactId>maven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies></dependencies>
</project>

repositories

有些情況下,默認的中央倉庫無法滿足項目的需求,可能項目需要的構件存在於另外一個遠程倉庫中,如JBoss Maven.這時,可以在POM中配置該倉庫.

repositories元素下,可以使用repository子元素聲明一個或者多個遠程倉庫.比如在超級POM(位於maven-model-builder-3.6.3.jar)中默認的倉庫配置:

  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

使用的idcentral,如果其他倉庫聲明的id也一樣,就會覆蓋中央倉庫的配置.

這裏的snapshots比較重要,定義了是否提供快照版本下載支持.對應的還有releases,它們都是對應的xsd規定的RepositoryPolicy類型,默認爲真.

RepositoryPolicy還包括updatePolicychecksumPolicy,表示更新頻率和文件校驗策略.

updatePolicy

默認的值是daily,表示每天檢查一次.其他可用的值包括:

  1. never-從不檢查更新
  2. always-每次構建都檢查更新
  3. interval: X-每隔X分鐘就檢查一次更新,X爲任意整數.

checksumPolicy

  1. warn,默認值,校驗不通過給出提示
  2. ignore,忽略
  3. fail,校驗不通過構建失敗.

layout

表示佈局,兩個可選項:legacydefault.

legacy對應的是maven1的佈局,一般不用.

default對應的是maven2maven3的佈局,是目前來說最常用的,因此也是默認值.

認證

有時出於安全考慮,需要認證後提供下載和部署服務,比如很多公司內部的私服不允許匿名拉取文件的.

但認證信息在settings.xmlservers的子元素server中配置,通過id與此處的repositoryid一一對應.

其他Maven配置

除了全局的settings.xml和項目級別pom.xml,還有其他一些配置,比如MAVEN_OPTS,項目根目錄下的.mvn文件夾.具體參考官網configure

生命週期

Maven擁有三套相互獨立的生命週期:clean,defaultsite.

每個生命週期都包含多個階段(phase),這些階段是有順序的.

clean

目的是清理項目,包含三個階段:.

階段 可執行
pre-clean F
clean T
post-clean F

default

定義了真正構件時所需要執行的所有步驟,它是所有生命週期中最核心的部分.它包含的階段較多,這裏僅僅列舉一些關鍵階段,它們均可在命令行顯式執行:

  • validate 驗證項目是否正確並且所有必要的信息均可用
  • compile
  • test
  • package
  • verify 對集成測試的結果進行任何檢查,以確保符合質量標準
  • install 將生成的包安裝到本地存儲庫中,以作爲本地其他項目中的依賴項
  • deploy 在構建環境中完成後,將最終程序包部署到遠程存儲庫,以便與其他開發人員和項目共享。

site

目的是建立和發佈項目站點,Maven能夠基於POM所包含的信息,執行mvn site命令會自動生成一個友好的站點,位於target/site目錄下的靜態頁面,包含如下階段:

  • pre-site
  • site
  • post-site
  • site-deploy 將生成的項目站點發布到服務器上

本生命週期不常用,用到再補充.

插件

爲了達到開箱即用的效果,Maven內置了許多常用插件:

name phase more details
maven-clean-plugin clean clean_Lifecycle
maven-resources-plugin default default-bindings
maven-compiler-plugin
maven-surefire-plugin
maven-jar-plugin
maven-install-plugin
maven-deploy-plugin
maven-site-plugin site site_Lifecycle

插件目標

Maven的核心僅僅定義了抽象的生命週期,具體的任務是交給插件完成的,插件爲了功能複用,又將其分爲多個目標.

比如maven-compiler-plugin包含三個目標:

Goal Description
compiler:compile 綁定到編譯階段,用於編譯主要源文件。
compiler:help maven-compiler-plugin上顯示幫助信息。 調用mvn compiler:help -Ddetail=true -Dgoal=<goal-name>以顯示參數詳細信息。
compiler:testCompile 綁定到測試編譯階段,用於編譯測試源文件。

如果想查看其他插件目標,直接訪問官網,找到想了解的插件,查看:

插件綁定

Maven的生命週期與插件相互綁定,用以完成實際的構建任務.

具體而言,是生命週期的階段與插件目標相互綁定.

內置綁定

爲了讓用戶幾乎不用任何配置就能構建Maven項目,所以內置了一些綁定,官網中給出了一系列對應關係.

其中cleansite階段的綁定關係比較簡單,直接列舉出來了,default階段的默認綁定比較複雜,是根據打包類型對應的,可以查看其給出的default-bindings.

POM配置

Maven幫我們內置了一些插件,一般足夠滿足我們的需求,只有在很少的情況下,項目使用的插件無法在中央倉庫找到,或者自己編寫了插件,就必須考慮配置其他的遠程插件倉庫了.

pom.xml爲我們提供了條件:

使用pluginRepositories+pluginRepository,其他配置則與repositories+repository相同.

命令行

命令行可以直接激活生命週期階段,也可以調用插件目標.

生命週期調用

mvn clean
mvn test

mvn clean install
mvn clean deploy site-deploy

插件目標調用

有些任務不適合綁定在生命週期上,所以Maven提供了調用插件目標的方式:

mvn help:describe -Dplugin=compiler -Ddetail
mvn dependency:tree

describe是插件目標沒錯,那help是什麼呢,其實它是目標前綴,是Maven爲了簡化調用而設定的.它的完整命令是:

mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:describe -Dplugin=compiler -Ddetail

其中版本號可選.第二條命令同理.

插件前綴

一般的前綴與它的插件名稱對應:maven-XXX-plugin,如果不一樣的話,以groupIdorg.apache.maven.plugins的官方插件爲例,可以通過遠程倉庫maven-metadata.xml查看所有插件的前綴.

聚合與繼承

聚合

對於複雜的Maven項目,一般建議採用多模塊的方式來設計開發,便於後期維護管理。但是構建項目時,如果每次都需要按模塊一個一個進行構建會十分麻煩,而Maven的聚合功能就可以很好的解決這個問題,當用戶對聚合模塊執行構建任務時,會對所有被其聚合的模塊自動地依次進行構建任務.

一個聚合項目,其packaging必須定義爲pom.然後使用modules列舉其他模塊.

繼承

父模塊packaging必須爲pom.

主要涉及的元素是properties,dependencyManagementpluginManagement.

properties

預置屬性,子模塊可以直接使用.

dependencyManagement

定義一些可能涉及的不衝突的依賴,子模塊在使用相同的依賴時,可以忽略版本,防止衝突.

子模塊可以選擇不使用,顯式配置依賴時纔會生效.

當子模塊定義了不同的版本時,會覆蓋.

pluginManagement

dependencyManagement起相同作用.

公共依賴

如果有公共依賴,可以提取到這裏,以便統一管理.

可繼承元素

上述properties,dependencyManagementpluginManagement都是可繼承元素,但這不是全部.

所有可繼承元素:

  • groupId
  • version
  • description
  • organization
  • inceptionYear 創始年份
  • url
  • developers
  • contributors
  • distributionManagement 部署配置
  • issueManagement 缺陷跟蹤
  • ciManagement 持續集成(Continuous Integration)管理
  • scm 版本控制信息
  • mailingLists 郵件列表信息
  • properties
  • dependencies
  • dependencyManagement
  • pluginManagement
  • repositories
  • build
  • reporting

通過parent引入就可以享受父模塊提供的便利.

parent中有一個relativePath元素用於指定父模塊的pom.xml位置,默認值是../pom.xml,如果不符合這種結構,可以另行指定.

import 依賴範圍

我們在一個新的項目/模塊中,如果期望複用其他POMdependencyManagement元素的所有配置,我們可以通過繼承或拷貝該配置實現.

因爲maven只支持單繼承,如果當前項目已經繼承了一個父模塊,此時即可通過import導入的方式來複用其他POM中的dependencyManagement配置。需要注意的是,由於import依賴範圍的特殊性,其一般指向的是打包類型爲pom的模塊。故其type只能爲pom.

    <parent>
        <groupId>com.yan</groupId>
        <artifactId>xxx-parent</artifactId>
        <version>xxxx</version>
        <relativePath/>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.1.4.RELEASE</version>
                <!-- 必須是pom -->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

聚合與繼承的比較

  1. 不同
  • 目的不同,聚合是爲了集成構建,繼承是爲了消除重複
  • 聚合知道被聚合的模塊,反之不知;繼承則是子知父,父不知子
  1. 相同
  • packaging均爲pom,這意味着項目可以同時是聚合模塊和父模塊.
  • 都爲構建提供方便

反應堆

就是決定構建順序的構建結構.

單模塊的反應堆就是它本身,如果有父模塊,先構建父模塊.

如果是聚合模塊,那麼module定義的順序決定了構建順序.

靈活構建

大多數時候,用戶都是一次性構建整個項目,但有些時候用戶可能僅僅需要構建某個模塊,即用戶需要裁剪反應堆來實現構建指定模塊的目的。在Maven命令行中可通過相關選項參數實現反應堆的裁剪

  1. -pl,projects:構建指定模塊,多個模塊用逗號進行分隔

    mvn package -pl m_a, m_b
    
  2. -am,-also-make:同時構建所列模塊的父模塊

    mvn package -pl m_a -am 
    
  3. -amd,-also-make-dependents:同時子模塊

    mvn package m_parent -amd
    
  4. -rf,-resume-from:從指定模塊開始構建

    mvn -rf
    

Maven屬性

內置屬性

主要有兩個常用內置屬性:

  • basedir:項目根目錄,即包含pom.xml的目錄
  • version:表示項目版本

POM屬性

  • project.build.sourceDirectory:項目的主源碼目錄,默認爲src/main/java.
  • project.build.testSourceDirectory:項目的測試源碼目錄,默認爲src/test/java.
  • project.build.directory:項目構建輸出目錄,默認爲target.
  • project.outputDirectory:項目主代碼編譯輸出目錄,默認爲target/classes
  • project.testOutputDirectory:項目測試代碼編譯輸出目錄,默認爲target/testclasses
  • project.groupId
  • project.artifactId
  • project.version
  • project.build.finalName:項目打包輸出文件的名稱,默認爲${project.artifactId}-${project.version}

自定義屬性

用戶可以在POMproperties元素下自定義屬性

settings屬性

可以用以settings.開頭的屬性引用settings.xml中的值,如settings.localRepository指向本地倉庫的地址.

Java系統屬性

所有Java系統都可以使用Maven屬性引用.使用mvn help:system查看所有的Java系統屬性.

環境變量屬性

所有環境變量都可以使用以env.開頭的Maven屬性引用.使用mvn help:system查看所有的環境變量屬性.

資源過濾

Maven屬性默認只有在POM中才會被解析,因此有時會需要讓Maven解析資源文件(位於src/main/resources)中的Maven屬性.

資源文件的處理需要通過maven-resources-plugin,它默認的行爲只是將項目主資源文件複製到主代碼編譯輸出目錄中,將測試資源文件複製到測試代碼編譯輸出目錄中.若要開啓資源過濾,需要配置<filtering>爲真:

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <resources>
                        <resource>
                            <directory>${project.build.sourceDirectory}</directory>
                            <filtering>true</filtering>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

ToolChains

默認路徑是~/.m2/toolchains.xml.

工具鏈是一個預配置的對象,Maven插件可將其用於工具配置檢索(位置和其他信息)。

最常用的就是Jdk版本的選擇,還提供了自定義工具鏈的方法.

使用工具鏈,需要配置兩個基本組件:

  1. 項目POM中的maven-toolchains-plugin
  2. 本機上的toolchains.xml文件。

實戰

Jdk版本工具鏈示例:

  1. ~/.m2/toolchains.xml中:

    <?xml version="1.0" encoding="UTF8"?>
    <toolchains>
      <!-- JDK toolchains -->
      <toolchain>
        <type>jdk</type>
        <provides>
          <version>1.5</version>
          <vendor>sun</vendor>
        </provides>
        <configuration>
          <jdkHome>/path/to/jdk/1.5</jdkHome>
        </configuration>
      </toolchain>
      <toolchain>
        <type>jdk</type>
        <provides>
          <version>1.6</version>
          <vendor>sun</vendor>
        </provides>
        <configuration>
          <jdkHome>/path/to/jdk/1.6</jdkHome>
        </configuration>
      </toolchain>
    
      <!-- other toolchains -->
      <toolchain>
        <type>netbeans</type>
        <provides>
          <version>5.5</version>
        </provides>
        <configuration>
          <installDir>/path/to/netbeans/5.5</installDir>
        </configuration>
      </toolchain>
    </toolchains>
    
  2. pom.xml

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-toolchains-plugin</artifactId>
        <version>1.1</version>
        <executions>
          <execution>
            <goals>
              <goal>toolchain</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <toolchains>
            <jdk>
              <version>1.5</version>
              <vendor>sun</vendor>
            </jdk>
          </toolchains>
        </configuration>
      </plugin>
    </plugins>
    

    3.3.1版本開始可以使用--global-toolchains file來指定toolchains的配置位置,但還是強烈建議放在默認目錄~/.m2下.

可執行jar包

maven-jar-plugin打的jar包不可執行,需要藉助maven-shade-plugin來配置:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>${你的主類全類名}</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

更多信息參考:maven-shade-plugin.

部署

pom.xml中加入

    <distributionManagement>
        <!--release倉庫-->
        <repository>
            <id>swb</id>
            <url>http://repo.cnswb.com/repository/maven-releases/</url>
        </repository>
        <!--快照倉庫-->
        <snapshotRepository>
            <id>swb</id>
            <url>http://repo.cnswb.com/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

執行命令mvn clean deploy,如果當前項目版本爲快照版本則發佈至snapshotRepository,否則是repository.

升級

普通升級都是從官網下載最新安裝包到本機解壓後從新指定環境變量PATH

但還有更好的方式,即創建一個軟連接用來統一代理,這樣每次只需改變軟連接的目標地址實現升級了。

/opt/apache目錄下創建一個軟連接maven,用它來指向想要升級的Maven目錄,環境變量中的M2_HOME設置爲/opt/apache/maven

比如從當前爲3.6.1

ln -s /opt/apache/apache-maven-3.6.1  /opt/apache/maven

升級爲3.6.3

rm -rf /opt/apache/maven
ln -s /opt/apache/apache-maven-3.6.3  /opt/apache/maven

升級後查看:

yan@yan-PC:/opt$ ll /opt/apache
總用量 16
drwxr-xr-x  4 yan yan 4096 3月  25 14:37 .
drwxr-xr-x 26 yan yan 4096 3月  25 10:52 ..
drwxr-xr-x  6 yan yan 4096 3月  25 14:37 apache-maven-3.6.1
drwxr-xr-x  6 yan yan 4096 3月  25 10:57 apache-maven-3.6.3
lrwxrwxrwx  1 yan yan   30 3月  25 10:56 maven -> /opt/apache/apache-maven-3.6.3

私服

目前,我們的私服倉庫結構如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章