1. 程式人生 > >ava Maven項目之Nexus私服搭建和版本管理應用

ava Maven項目之Nexus私服搭建和版本管理應用

max 權限 環境 val 導致 type www. exit frame

目錄:

  • Nexus介紹
  • 環境、軟件準備
  • Nexus服務搭建
  • Java Maven項目版本管理應用
  • FAQ

1、Nexus介紹

Nexus是一個強大的Maven倉庫管理器,它極大地簡化了自己內部倉庫的維護和外部倉庫的訪問。利用Nexus你可以只在一個地方就能夠完全控制訪問 和部署在你所維護倉庫中的每個Artifact。我們可以在局域網搭建一個maven私服,用來部署第三方公共構件或者作為遠程倉庫在該局域網的一個代理。

2、環境、軟件準備

本次演示環境,我是在本機mac上操作,以下是我本地軟件及版本:

  1. Nexus:nexus-2.14.4-03
  2. Jdk:1.8.0_91
  3. Maven:3.3.9
  4. Git: 2.10.1
  5. GitLab:8.17.4

註意:Java Maven項目版本管理,這裏我們scm使用git來做版本管理,gitlab作為代碼存儲,這裏我們忽略Jdk、Maven、Git、GitLab的安裝過程,著重介紹下Nexus的搭建,以及Java Maven項目配置以及版本管理配置。

3、Nexus服務搭建

這裏我們使用Nexus OSS開源版本,官網下載地址:Nexus Repository Manager OSS,這裏我選擇2.x的tag.gz包下載安裝,安裝到我本地/Users/wanyang3目錄下。

1)解壓縮下載包

cd /Users/wanyang3
tar -zxvf nexus-2.14.4-03-bundle.tar.gz

解壓縮後,會在當前目錄nexus-2.14.4-03-bundle下出現兩個目錄:
nexus-2.14.4-03:nexus服務目錄,包括日誌,配置、啟動、應用。
sonatype-work:nexux存儲目錄,下載上傳的各個包存貯在這裏。

2) 修改配置並啟動服務

修改配置:
cd /Users/wanyang3/nexus-2.14.4-03-bundle/nexus-2.14.4-03/conf
vim nexus.properties

說明:該文件是nexus的配置屬性文件,application-port默認服務端口8081,因為本地8081端口已經占用,所以我們這裏修改為9998,即:application-port=9998,其他配置,如nexus-work、runtime、application-host、nexus-webapp等默認即可。

啟動:
cd /Users/wanyang3/nexus-2.14.4-03-bundle/nexus-2.14.4-03/bin
./Nexus start
Usage: ./nexus { console | start | stop | restart | status | dump }

註意:若啟動報錯,說沒有權限啟動,或者讓指定USER時,有兩種方法解決:
1. 使用RUN_AS_USER=root ./Nexus start命令啟動
2. 修改Nexus文件,設置打開註釋,並設置RUN_AS_USER=root,以後只需要執行./Nexus start即可。

3)設置Nexus
成功啟動Nexus後,我們可以瀏覽器訪問http://127.0.0.1:9998/nexus/,就可以看到Nexus服務Web管理頁面歡迎頁面了。

技術分享圖片

3.1 創建倉庫
點擊右上角Log In,輸入用戶名和密碼登錄,Nexus默認賬戶用戶名為admin,密碼為admin123,登錄以後,我們現在可以創建一個個人倉庫了。點擊左側Repositories,我們可以看到默認的所有的倉庫列表。

技術分享圖片

我們可以看到倉庫類型有四種:

  1. hosted(宿主倉庫):用來部署自己,第三方或者公共倉庫的構件
  2. proxy(代理倉庫):代理遠程倉庫
  3. virtual(虛擬倉庫):默認提供了一個Central M1虛擬倉庫,用來將maven 2適配為maven 1
  4. group(倉庫組):統一管理多個倉庫

這裏我們選擇類型為hosted的創建一個wanyang3的Repositories,註意選擇Deployment Policy時,如果該倉庫多次部署的話,請選擇Allow Redeploy,否則後續部署會報錯。

技術分享圖片

3.2 設置用戶及權限
點擊左側Security—》Users,設置用戶及權限。
我們可以看到有三個默認的賬號:

  1. Admin(管理員賬號):Nexus管理員權限,最高權限,什麽操作都可以做。
  2. Deployment(部署賬號):Nexus部署權限,以及所有倉庫的CRUDV操作權限。
  3. Anonymous(匿名賬號):Nexus匿名權限,以及所有倉庫只讀權限。

我們正常訪問倉庫的時候,是不需要這三個賬戶的,一般我們會把Deployment賬戶暴漏出來,方便開發或運維部署項目使用,我們可以直接使用該部署賬號,亦可以新創建一個自己的賬號信息,通過Add Role Management來控制該賬號的權限。

技術分享圖片

註意:這裏要記住設置的用戶名和密碼,下邊配置Maven Setting.xml的時候配置用戶名和密碼信息。

Java Maven項目版本管理應用

一、Java Maven項目基本配置

我們先來看一個最基礎的pom.xml文件,我們要達到的目的是,讓我們依賴的jar包,從我們剛配置的Nexus私服上拉取和存儲。

<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.wanynag3.efp</groupId>
  <artifactId>efp_demo</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>efp_demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>4.3.2.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-oxm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.7</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.10</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.10</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
  </dependencies>

  <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <finalName>efp_demo</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

從pom文件可以看出來,這個Maven項目是一個很常見的SpringMVC項目,我們想讓他依賴剛搭建的Nexus私服,那麽需要修改Maven的setting.xml的mirrors節點。

<mirrors>
    <mirror>
        <id>default</id>
        <mirrorOf>*</mirrorOf>
        <name>default maven nexus mirror</name>
        <url>http://127.0.0.1:9998/nexus/content/groups/public</url>
    </mirror>
</mirrors>

說明:這裏mirror表示鏡像庫,指定庫的鏡像,也就是覆蓋中央倉庫的默認地址,這裏<mirrorOf>*</mirrorOf>表示為所有的倉庫做鏡像,也可以指定某個或某幾個倉庫做鏡像,如central庫。

修改完成之後,以後我們修改或新增dependency時,都會先從本地私服拉取,如果沒有則去中央倉庫拉取並緩存到私服,下次使用就可以直接從本地私服拉取,速度就快的多啦!

二、Java Maven項目版本管理

我們先來了解一下Maven項目從1.0.0-SNAPSHOT到1.0.0(Release)在到1.0.1-SNAPSHOT的過程:

  1. 更新pom版本從1.0.0-SNAPSHOT到1.0.0
  2. 對該版本打一個1.0.0 tag推送到Git/SVN
  3. 針對該tag,執行mvn deploy,發布1.0.0正式版本,推送Maven倉庫
  4. 更新pom版本從1.0.0到1.0.1-SNAPSHOT

整個過程,是通過Maven插件maven-release-plugin來實現,該插件可以幫我們升級pom版本號,打tag並提交到scm,以及提交到Nexus倉庫,我們需要配置下pom.xml。

1、增加scm配置
<scm>
    <connection>scm:git:http://git.xx.xx.com/e_flows/efp_demo.git</connection>
    <developerConnection>scm:git:http://git.xx.xx.com/e_flows/efp_demo.git</developerConnection>
    <url>scm:git:http://git.xx.xx.com/e_flows/efp_demo.git</url>
</scm>

2、在plugins下增加plugin
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-release-plugin</artifactId>
    <version>2.5.3</version>
    <configuration>
        <tagNameFormat>v@{project.version}</tagNameFormat>
    </configuration>
</plugin>

說明:
    1. scm配置,配置該項目的git或svn地址,maven-release-plugin插件會幫我們完成一系列git或svn操作,如提交、打tag等,這裏我使用gitlab作為代碼管理,所以需要提前安裝好git和gitlab,否則maven執行會報錯。
    2. maven-release-plugin插件,tagNameFormat默認取artifactId-version作為tag的名稱,我們也可以指定tag的格式,例如這裏我指定以v開頭+pom中的version字段(v1.0.0),可以用v@{project.version}。

好了,我們現在開始使用插件執行版本管理了。

首先,我們來執行命令mvn release:prepare,執行過程中,我們會看到這樣的輸出提示:

1. What is the release version for "efp_demo"? (com.wanynag3.efp:efp_demo) 1.0.0: :
--意思是你想要將efp_demo發布為什麽版本,默認是1.0.0(按照pom中version走的),如果想發布為其他版本號,可以在:後邊輸入其他版本號。

2. What is SCM release tag or label for "efp_demo"? (com.wanynag3.efp:efp_demo) v1.0.0: :
--意思是你想要將efp_demo發布為什麽tag標簽,默認是v1.0.0(這裏我們在pom中設置tagNameFormat起作用啦!),如果想發布其他tag標簽,可以在:後邊輸入其他tag。

3. What is the new development version for "efp_demo"? (com.wanynag3.efp:efp_demo) 1.0.1-SNAPSHOT: :
--意思是你想要為efp_demo設置為什麽新的開發版本,默認是1.0.1-SNAPSHOT(默認在原版本+1),如果想設置為其他版本,比如升版本1.1.0,可以在:後邊輸入版本號。

執行完畢之後,在Gitlab中該項目對應倉庫中tag中,就可以看到maven-release-plugin剛剛打的v1.0.0的tag,同時可以看到pom.xml中版本自動升級為1.0.1-SNAPSHOT。

技術分享圖片

然後,我們需要將efp_demo:1.0.0正式版本發布到我們私服中,我們還需要修改一下pom.xml以及setting.xml,配置repository和snapshotRepository倉庫地址,Server認證信息等。

1、Maven setting.xml中設置server
<servers>
    <server>
      <id>wanyang3.release</id>
      <username>wanyang3</username>
      <password>******</password>
    </server>
    <server>
      <id>wanyang3.snapshot</id>
      <username>wanyang3</username>
      <password>******</password>
    </server>
</servers>

2、pom.xml中新增distributionManagement
<distributionManagement>
    <repository>
        <id>wanyang3.release</id>
        <name>Internal Release Repository</name>
        <url>http://127.0.0.1:9998/nexus/content/repositories/releases</url>
        <uniqueVersion>true</uniqueVersion>
    </repository>
    <snapshotRepository>
        <id>wanyang3.snapshot</id>
        <name>Internal Snapshot Repository</name>
        <url>http://127.0.0.1:9998/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
</distributionManagement>

註意:
    1. repository下的id,必須跟Maven setting.xml中server下的id保持一致,我們上邊新增的的Nexus賬號wanyang3,是具有Deployment權限的,這個地方有權限驗證,用戶名密碼不對,deploy時會認證不通過。
    2. repository和snapshotRepository的url一個是正式releases地址,一個是快照snapshots地址,這裏我們用Nexus默認地址,也可以改為自己新建的releases和snapshots地址。

接著,我們執行命令mvn release:perform,執行過程中,我們看到如下輸出,則說明deploy成功:

[INFO] Uploading: http://127.0.0.1:9998/nexus/content/repositories/releases/com/wanynag3/efp/efp_demo/1.0.0/efp_demo-1.0.0.war
......
[INFO] Uploaded: http://127.0.0.1:9998/nexus/content/repositories/releases/com/wanynag3/efp/efp_demo/1.0.0/efp_demo-1.0.0.war (6562 KB at 34717.1 KB/sec)
[INFO] Uploading: http://127.0.0.1:9998/nexus/content/repositories/releases/com/wanynag3/efp/efp_demo/1.0.0/efp_demo-1.0.0.pom
......
Uploaded: http://127.0.0.1:9998/nexus/content/repositories/releases/com/wanynag3/efp/efp_demo/1.0.0/efp_demo-1.0.0.pom (4 KB at 244.6 KB/sec)
......

該過程,maven-release-plugin會自動幫我們簽出剛才打的v1.0.0 tag,然後打包,最後上傳到私服Maven倉庫中指定位置。好了到這裏,整個版本的升級,打標簽,發布等工作全部完成。我們可以在私服Maven倉庫中看到正式發布的1.0.0版本啦!

技術分享圖片

至此,Maven項目版本自動化管理就完成了。

FQA

  1. 執行mvn release:prepare報錯 [Cannot prepare the release because …]:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:prepare (default-cli) on project qd_api: Cannot prepare the release because you have local modifications : 
    [ERROR] [pom.xml:modified]
  2. 這個報錯,是因為本地有代碼修改未提交,必須先提交修改之後,在執行該命令。

  3. 執行mvn release:prepare報錯 [Unable to commit files…]:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:prepare (default-cli) on project efp_demo: Unable to commit files
    [ERROR] Provider message:
    [ERROR] The git-push command failed.
    [ERROR] Command output:
    [ERROR] remote: HTTP Basic: Access denied
    [ERROR] fatal: Authentication failed for ‘http://git.xx.xx.com/e_flows/efp_demo.git/‘
  4. 這個報錯,是因為在執行git相關操作時,Gitlab認證失敗,請檢查一下git用戶名和密碼。

  5. 執行mvn release:perform報錯 [Deployment failed: repository element was …]:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project efp_demo: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1]
  6. 這個報錯,是因為pom.xm中沒有配置distributionManagement相關信息,我們可以在pom中增加distributionManagement信息,或者在命令後追加-DaltDeploymentRepository=id::layout::url

  7. 執行mvn release:perform報錯 [Failed to deploy artifacts: Could not transfer …]:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project efp_demo: Failed to deploy artifacts: Could not transfer artifact com.wanyang3.efp:efp_demo:war:1.0.0 from/to wanyang3.default (http://127.0.0.1:9998/nexus/content/repositories/releases): Failed to transfer file: http://127.0.0.1:9998/nexus/content/repositories/releases/com/wanyang3/efp/efp_demo/1.0.0/efp_demo-1.0.5.war. Return code is: 401, ReasonPhrase: Unauthorized.
  8. 這個報錯,是因為deploy時認證失敗,首先在確保Maven setting.xml中server配置的用戶名密碼正確的情況下,檢查server id跟pom.xml中repository id是否一致。

  9. 執行mvn release:perform報錯 [Request Entity Too Large …]:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project multimedia-web: Failed to deploy artifacts: Could not transfer artifact  Return code is: 413, ReasonPhrase: Request Entity Too Large.
  10. 這個報錯,是因為我們nginx代理默認客戶端最大允許body的size太小導致(默認2M),需要修改nginx.conf中proxy部分:client_max_body_size 500M

  11. 執行mvn release:perform報錯 [MavenReportException: Error while generating …]:

    [INFO] [ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.10.4:jar (attach-javadocs) on project efp_demo: MavenReportException: Error while generating Javadoc:
    [INFO] [ERROR] Exit code: 1 - /Users/wanyang3/git/e_flows/efp_demo/target/checkout/src/main/java/com/wanyang3/efp/efp_demo/controller/CommonController.java:25: 警告: mailTo沒有 @param
  12. 這個報錯,是因為我使用的jdk8,執行mvn clean install編譯是能通過,但是執行該命令時一直報Javadoc的錯誤,後來google查詢了下,需要增加一個maven-javadoc-plugin插件可解決。

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <configuration>
            <additionalparam>-Xdoclint:none</additionalparam>
        </configuration>
    </plugin>

參考資料:

  1. Nexus Documentation
  2. maven-release-plugin

ava Maven項目之Nexus私服搭建和版本管理應用