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)

maven部署项目流程(区分环境)的更多相关文章

  1. 一些基本的操作,编译,构建,单元测试,安装,网站生成和基于Maven部署项目。

    一些基本的操作,编译,构建,单元测试,安装,网站生成和基于Maven部署项目. 使用Maven构建项目“mvn package” 来构建项目 使用Maven清理项目“mvn clean” 来清理项目 ...

  2. maven部署项目遇到的问题

    在构建maven hibernate时候的exception 错误原因:通过maven dependency引入了hibernate5.2.10 final 而hibernate-core中没有上述该 ...

  3. Maven部署项目到Tomcat

    首先需要用MyEclipse建立一个Maven项目 为了不报403错误,tomcat目录下的tomcat-user.xml文件的配置如下: setting.xml配置如下,大家关注下Server的配置 ...

  4. Linux系统下部署项目流程

    一.系统架构 linux系统 centOS 6.9 应用服务器:Tomcat /JDK 数据库服务器:MySQL 二.连接远程工具FinalShell 1.Centos 6: 启动服务:service ...

  5. idea远程调试tomcat部署项目(windows环境)

    1.tomcat启动之前,修改apache-tomcat-8.5.34\bin\catalina.bat文件,设置调试端口 如下设置(windows环境): rem ----------------- ...

  6. IDEA远程快速部署SpringBoot项目到Docker环境

    一:基础准备 1.首先在linux服务器安装Docker环境,具体安装步骤及Docker使用参考官网或网络资料(这里重点是快速部署项目到Docker环境) 2.配置Docker远程连接端口 1.vim ...

  7. jenkins+git+maven搭建自动化部署项目环境

    简介    折腾了两个晚上,趁着今晚比较有空,把jenkins+git+maven搭建自动化部署项目环境搭建的过程记录一下,这里我把github作为git的远程仓库(https://github.co ...

  8. Java WEB开发环境搭建以及创建Maven Web项目

    根据此链接博文学习配置: http://www.cnblogs.com/zyw-205520/p/4767633.html 1.JDK的安装 自行百度,(最好是jdk1.7版本的) 测试如下图,即完成 ...

  9. Spring+SpringMVC+Mybatis+MAVEN+Eclipse+项目完整环境搭建

    1.新建一个Maven项目,创建父项目. 2.创建子项目模块 3.创建javaWeb项目 4.创建后的项目目录结构 5.Maven文件配置 parent父项目pom.xml文件配置 <?xml ...

随机推荐

  1. orace学习操作(4)

    Orace游标: 一.游标简介: 使用游标,我们可以对具体操作数据,比如查询的结果,对行,列数据进行更加细致的处理.以及对其他DML操作进行判断等操作: 二.显示游标: 1.静态的指定变量类型: SQ ...

  2. 转!!!解释Eclipse下Tomcat项目部署路径问题(.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps)

    1.配置eclipse的开发环境,配置jdk的安装路径和tomcat安装路径. 2.在eclipse下建立Dynamic Web Project工程zhgy,在使用eclipse中new一个tomca ...

  3. 学习笔记之.NET Core

    source code https://github.com/haotang923/dotnet/tree/master/src .NET Documentation | Microsoft Docs ...

  4. RESTful Java client with Apache HttpClient / URL /Jersey client

    JSON example with Jersey + Jackson Jersey client examples RESTful Java client with RESTEasy client f ...

  5. 【转载】深入浅出REST

    英文原文:A Brief Introduction to REST 作者:Stefan Tilkov ,译者:苑永凯,发布于 2007-12-25 不知你是否意识到,围绕着什么才是实现异构的应用到应用 ...

  6. java接口定义和作用

    接口语法 1.接口是一种引用类型,可以等同看作类.修饰符 interface 接口名 2.接口中只能出现常量和抽象方法 3.接口其实是一个特殊的抽象类,特殊在接口是完全抽象的 4.接口中没有构造方法, ...

  7. Linux 期中架构 inotify

    全网备份数据同步方案 备份网站内部人员信息  不能解决外部(人员)上传数据的备份 定时任务最短执行的周期为一分钟,采用定时任务方式,有时可能造成一分钟内的数据丢失 因此对于重要数据需要采用实时同步的方 ...

  8. 1085 Perfect Sequence (25 分)

    1085 Perfect Sequence (25 分) Given a sequence of positive integers and another positive integer p. T ...

  9. linux中的ftp命令

    转载至:https://www.cnblogs.com/mingforyou/p/4103022.html 一.ftp的get命令和mget命令有何不同? get一次只下载一个文件:mget一次可以下 ...

  10. tensorflow定义神经网络损失函数MSE

    import numpy as np import tensorflow as tf y_pred = np.array([[1], [2], [3]],dtype=np.float32) y_rea ...