zoukankan      html  css  js  c++  java
  • maven部署项目流程(区分环境)

    java项目区分环境打包部署到Linux 本文以一个简单的HelloWorld的项目为例,从pom.xml配置到打jar包,最后在linux上运行并验证来对maven部署的这套流程进行简单介绍。 为方便讲解,本文使用的时springboot框架,其运行函数入口程序如下:

    @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配置内容:

    env: dev
    server:
      port: 8081

    prod的yml配置内容:

    env: prod
    server:
      port: 8082

    项目目录:

    输入图片说明

     

    pom.xml配置过程:

    第一步,使用<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}对应:

    <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=true

    如果要给生产环境打包使用如下命令: mvn clean package -Pprod -Dmaven.test.skip=true

     

    第二步,使用<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来处理打包具体细节。 比如:

    <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)
  • 相关阅读:
    EC++学习笔记(五) 实现
    EC++学习笔记(三) 资源管理
    EC++学习笔记(一) 习惯c++
    EC++学习笔记(六) 继承和面向对象设计
    STL学习笔记(三) 关联容器
    STL学习笔记(一) 容器
    背包问题详解
    EC++学习笔记(二) 构造/析构/赋值
    STL学习笔记(四) 迭代器
    常用安全测试用例
  • 原文地址:https://www.cnblogs.com/chenjunjie12321/p/10046180.html
Copyright © 2011-2022 走看看