maven部署項目流程(區分環境)

java項目區分環境打包部署到Linux 本文以一個簡單的HelloWorld的項目爲例,從pom.xml配置到打jar包,最後在linux上運行並驗證來對maven部署的這套流程進行簡單介紹。 爲方便講解,本文使用的時springboot框架,其運行函數入口程序以下:java

@SpringBootApplication
public class ProjectApplication {
    private static String env;

    public static void main(String[] args) {
        SpringApplication.run(ProjectApplication.class, args);
        System.out.println("hello world!");
        System.out.println("current environment is: " + env);
    }

    @Value("${env}")
    private void setEnv(String v) {
        env = v;
    }
}

爲驗證分環境打包功能,這裏使用你了兩個目錄,分別存放配置文件,分別時開發環境dev目錄下的中的application.yml,以及生產環境prod目錄下的application.yml dev的yml配置內容:linux

env: dev
server:
  port: 8081

prod的yml配置內容:spring

env: prod
server:
  port: 8082

項目目錄:express

輸入圖片說明

 

pom.xml配置過程:apache

第一步,使用<profiles>標籤

<profiles>
    <!-- 開發環境 -->
    <profile>
        <id>dev</id>
        <properties>
            <profile.dir>${profiles.dir}/dev</profile.dir>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault> <!--將dev設置爲默認環境-->
        </activation>
        <build>
            <resources>
                <resource>
                    <directory>${profile.dir}/dev</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>

    <!-- 生產環境 -->
    <profile>
        <id>prod</id>
        <properties>
            <profile.dir>${profiles.dir}/prod</profile.dir>
        </properties>
    </profile>
</profiles>

注意這裏${profiles.dir}對應:vim

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <profiles.dir>src/main/profiles</profiles.dir>
</properties>

若是要給開發環境打包使用以下命令: mvn clean package -Pdev -Dmaven.test.skip=trueapi

若是要給生產環境打包使用以下命令: mvn clean package -Pprod -Dmaven.test.skip=truespringboot

 

第二步,使用<build>標籤

  1. 引入maven-jar-plugin
  2. 引入maven-assembly-plugin

先說maven-assembly-plugin,顧名思義,就是整合的意思,好比bulid項目以後,會在target目錄下生成不少零碎的文件,好比jar,config配置,bin目錄等,若是想將這些文件打包成一個壓縮包就可使用這個插件來實現,例如它打包能夠爲zip,tar.gz,dir等等形式。 通常maven-assembly-plugin以以下方式執行:服務器

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <!-- not append assembly id in release file name -->
        <appendAssemblyId>false</appendAssemblyId>
        <descriptors>
            <descriptor>src/main/assembly/assembly.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal><!-- 只運行一次 -->
            </goals>
        </execution>
    </executions>
</plugin>

而後對應的assembly.xml來處理打包具體細節。 好比:app

<assembly>
    <id>assembly</id>
    <formats>
        <format>dir</format>         <!-- 打包爲文件 -->
        <format>tar.gz</format>   <!-- 打包爲tar.gz -->
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <fileSets>
        <fileSet>      <!-- 將bin目錄的文件存放到整合文件的bin目錄下 -->
            <directory>src/main/assembly/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <fileMode>0755</fileMode>
            <filtered>true</filtered>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>     <!-- 將全部的依賴放到lib目錄下 -->
            <outputDirectory>lib</outputDirectory>     
        </dependencySet>
    </dependencySets>
</assembly> 

這樣使用mvn clean package -Pprod -Dmaven.test.skip=true打包整合的目錄結構大體以下:

project-0.0.1-SNAPSHOT ├── bin │ ├── start.sh │ └── stop.sh └── lib ├── javax.annotation-api-1.3.2.jar ├── jul-to-slf4j-1.7.25.jar ├── log4j-api-2.11.1.jar ├── log4j-to-slf4j-2.11.1.jar ├── logback-classic-1.2.3.jar ├── logback-core-1.2.3.jar ├── project-0.0.1-SNAPSHOT.jar ├── slf4j-api-1.7.25.jar ├── snakeyaml-1.23.jar ├── spring-aop-5.1.2.RELEASE.jar ├── spring-beans-5.1.2.RELEASE.jar

只使用maven-assembly-plugin即可以造成tar.gz包,可是運行的時候會出問題:

「no main manifest attribute, in /hom......jar」

這是由於:只使用maven-assembly-plugin打包成jar包須要在MANIFEST.MF中指定沒有指定Main-Class項,程序不知道運行入口。當前MANIFEST.MF信息以下:

Manifest-Version: 1.0
Implementation-Title: project
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: youai
Implementation-Vendor-Id: cjj.example
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_181
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/project

此時,就要引入maven-jar-plugin來問題解決 maven-jar-plugin主要爲配置MANIFEST.MF而生。一個MANIFEST.MF文件,裏面記錄了可執行文件的一些相關配置。 所以在pom.xml中的添加內容以下:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>./</classpathPrefix>
                <mainClass>cjj.example.project.ProjectApplication</mainClass>
            </manifest>
        </archive>
        <excludes>
            <exclude>*</exclude>
        </excludes>
    </configuration>
</plugin>

其中:

  • mainClass :哪一個class做爲程序的入口來執行;
  • addClasspath: 是否將依賴的classpath一塊兒打包 ;
  • classpathPrefix:依賴的classpath的前綴,也就是打包後生成的MANIFEST.MF文件裏,引入的jar文件都會加上前綴, 本項目裏指都加上前綴「./」,好比 spring-boot-2.1,在mainfest文件裏就會是./spring-boot-2.1 。
  • excludes:排除哪些文件不被打包進去。所以在本項目中的lib包中不會存在文件夾。

此時打包出來的目錄結構沒變,只是當前MANIFEST.MF有了變化,信息以下:

Manifest-Version: 1.0
Implementation-Title: project
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: youai
Implementation-Vendor-Id: cjj.example
Class-Path: ./spring-boot-starter-2.1.0.RELEASE.jar ./spring-boot-2.1.
 0.RELEASE.jar ./spring-context-5.1.2.RELEASE.jar ./spring-aop-5.1.2.R
 ELEASE.jar ./spring-beans-5.1.2.RELEASE.jar ./spring-expression-5.1.2
 .RELEASE.jar ./spring-boot-autoconfigure-2.1.0.RELEASE.jar ./spring-b
 oot-starter-logging-2.1.0.RELEASE.jar ./logback-classic-1.2.3.jar ./l
 ogback-core-1.2.3.jar ./log4j-to-slf4j-2.11.1.jar ./log4j-api-2.11.1.
 jar ./jul-to-slf4j-1.7.25.jar ./javax.annotation-api-1.3.2.jar ./spri
 ng-core-5.1.2.RELEASE.jar ./spring-jcl-5.1.2.RELEASE.jar ./snakeyaml-
 1.23.jar ./slf4j-api-1.7.25.jar
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_181
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/project
Main-Class: cjj.example.project.ProjectApplication

一切準備好後,激動地準備啓動腳本,也能夠執行命令:

java -jar project-0.0.1-SNAPSHOT.jar

運行文件,會出現以下錯誤:

ith name 'projectApplication': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'env' in value "${env}" 2018-11-30 15:22:16.897 INFO 12528 --- [ main] ConditionEvaluationReportLoggingListener : Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2018-11-30 15:22:16.901 ERROR 12528 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'projectApplication': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'env' in value "${env} "

緣由application.yml文件並無加載進去。

所以須要將配置文件關聯起來,方式以下: maven-jar-plugin中加入manifestEntries,將application.yml文件關聯到jar的啓動更目錄下:

<archive>
    <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>./</classpathPrefix>
        <mainClass>cjj.example.project.ProjectApplication</mainClass>
    </manifest>
    <manifestEntries>
        <Class-Path>../config/</Class-Path>
    </manifestEntries>
</archive>

從新打包,當前MANIFEST.MF信息以下:

Manifest-Version: 1.0
Implementation-Title: project
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: youai
Implementation-Vendor-Id: cjj.example
Class-Path: ./spring-boot-starter-2.1.0.RELEASE.jar ./spring-boot-2.1.
 0.RELEASE.jar ./spring-context-5.1.2.RELEASE.jar ./spring-aop-5.1.2.R
 ELEASE.jar ./spring-beans-5.1.2.RELEASE.jar ./spring-expression-5.1.2
 .RELEASE.jar ./spring-boot-autoconfigure-2.1.0.RELEASE.jar ./spring-b
 oot-starter-logging-2.1.0.RELEASE.jar ./logback-classic-1.2.3.jar ./l
 ogback-core-1.2.3.jar ./log4j-to-slf4j-2.11.1.jar ./log4j-api-2.11.1.
 jar ./jul-to-slf4j-1.7.25.jar ./javax.annotation-api-1.3.2.jar ./spri
 ng-core-5.1.2.RELEASE.jar ./spring-jcl-5.1.2.RELEASE.jar ./snakeyaml-
 1.23.jar ./slf4j-api-1.7.25.jar ../config/
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_181
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/project
Main-Class: cjj.example.project.ProjectApplication

可知在Class-Path: 下加入了 ../config/,所以咱們只要將對應環境的application.yml打包時放入config目錄內就能夠解決上面的問題,如何放入config可使用resource標籤。須要在pom.xml的build模塊下時,引入resources標籤。

<resources>
    <resource>
        <directory>${profile.dir}</directory>
        <filtering>true</filtering>
        <targetPath>${project.build.directory}/config</targetPath>
    </resource>
</resources> 

同時更新assembly.xml文件,在 <fileSets>標籤下加入

<fileSet>
    <directory>${project.build.directory}/config</directory>
    <outputDirectory>config</outputDirectory>
    <fileMode>0644</fileMode>
</fileSet> 

這樣在從新打包後會在生成的target目錄下產生一個conofig目錄,裏面存放的內容爲${profile.dir}目錄下的文件。而後經過assembly插件能夠將config目錄打包到打包壓縮文件tar.gz中了 以下:

輸入圖片說明

將執行mvn clean package -Pprod -Dmaven.test.skip=true生成的project-0.0.1-SNAPSHOT.tar.gz包上傳到linux服務器,而後運行start.sh

運行結果:

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.0.RELEASE) 2018-11-30 14:51:28.707 INFO 18601 --- [ main] cjj.example.project.ProjectApplication : Starting ProjectApplication v0.0.1-SNAPSHOT on datahub2 with PID 18601 (/home/dmadmin/cjj/project-0.0.1-SNAPSHOT/lib/project-0.0.1-SNAPSHOT.jar started by dmadmin in /home/dmadmin/cjj/project-0.0.1-SNAPSHOT/bin) 2018-11-30 14:51:28.714 INFO 18601 --- [ main] cjj.example.project.ProjectApplication : No active profile set, falling back to default profiles: default 2018-11-30 14:51:29.776 INFO 18601 --- [ main] cjj.example.project.ProjectApplication : Started ProjectApplication in 1.676 seconds (JVM running for 2.27) hello world! current environment is: prod

注意:在linux環境下運行start.sh,若是star.sh的文件類型爲dos, 能夠經過vim start.sh中set fileformat=unix來解決。

 

參考:

  1. http://maven.apache.org/plugins/maven-assembly-plugin/
  2. https://blog.csdn.net/mrluzle/article/details/79164342(SpringBoot 配置文件存放位置及讀取順序)
  3. https://www.java-success.com/maven-assembly-plugin-example/ (同時運行多個assembly.xml,如dev-assembly.xml,test-assembly.xml, prod-assembly.xml。goal標籤<goal>shade</goal> )
  4. https://www.mkyong.com/maven/create-a-fat-jar-file-maven-assembly-plugin/ (Create a fat Jar file – Maven Assembly Plugin)
相關文章
相關標籤/搜索