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>标签
- 引入
maven-jar-plugin
- 引入
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来解决。
参考:
- http://maven.apache.org/plugins/maven-assembly-plugin/
- https://blog.csdn.net/mrluzle/article/details/79164342(SpringBoot 配置文件存放位置及读取顺序)
- https://www.java-success.com/maven-assembly-plugin-example/ (同时运行多个assembly.xml,如dev-assembly.xml,test-assembly.xml, prod-assembly.xml。goal标签<goal>shade</goal> )
- https://www.mkyong.com/maven/create-a-fat-jar-file-maven-assembly-plugin/ (Create a fat Jar file – Maven Assembly Plugin)
maven部署项目流程(区分环境)的更多相关文章
- 一些基本的操作,编译,构建,单元测试,安装,网站生成和基于Maven部署项目。
一些基本的操作,编译,构建,单元测试,安装,网站生成和基于Maven部署项目. 使用Maven构建项目“mvn package” 来构建项目 使用Maven清理项目“mvn clean” 来清理项目 ...
- maven部署项目遇到的问题
在构建maven hibernate时候的exception 错误原因:通过maven dependency引入了hibernate5.2.10 final 而hibernate-core中没有上述该 ...
- Maven部署项目到Tomcat
首先需要用MyEclipse建立一个Maven项目 为了不报403错误,tomcat目录下的tomcat-user.xml文件的配置如下: setting.xml配置如下,大家关注下Server的配置 ...
- Linux系统下部署项目流程
一.系统架构 linux系统 centOS 6.9 应用服务器:Tomcat /JDK 数据库服务器:MySQL 二.连接远程工具FinalShell 1.Centos 6: 启动服务:service ...
- idea远程调试tomcat部署项目(windows环境)
1.tomcat启动之前,修改apache-tomcat-8.5.34\bin\catalina.bat文件,设置调试端口 如下设置(windows环境): rem ----------------- ...
- IDEA远程快速部署SpringBoot项目到Docker环境
一:基础准备 1.首先在linux服务器安装Docker环境,具体安装步骤及Docker使用参考官网或网络资料(这里重点是快速部署项目到Docker环境) 2.配置Docker远程连接端口 1.vim ...
- jenkins+git+maven搭建自动化部署项目环境
简介 折腾了两个晚上,趁着今晚比较有空,把jenkins+git+maven搭建自动化部署项目环境搭建的过程记录一下,这里我把github作为git的远程仓库(https://github.co ...
- Java WEB开发环境搭建以及创建Maven Web项目
根据此链接博文学习配置: http://www.cnblogs.com/zyw-205520/p/4767633.html 1.JDK的安装 自行百度,(最好是jdk1.7版本的) 测试如下图,即完成 ...
- Spring+SpringMVC+Mybatis+MAVEN+Eclipse+项目完整环境搭建
1.新建一个Maven项目,创建父项目. 2.创建子项目模块 3.创建javaWeb项目 4.创建后的项目目录结构 5.Maven文件配置 parent父项目pom.xml文件配置 <?xml ...
随机推荐
- 读取 Excel 之 NPOI
HSSFWorkbook hssfworkbook; void InitializeWorkbook(string path) { //read the template via FileStream ...
- [转]C#API 实现锁屏+关屏
http://www.cnblogs.com/1971ruru/archive/2010/05/20/1740216.html public Form1( bool aLock ) { if (aLo ...
- centos7 防火墙一些相关设置 开机添加静态路由 特殊的方法
参考文献: https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/security_guide/s ...
- [UE4]代理事件(C++)
用宏定义类似格式: DECLARE_DELEGATE //普通代理 DECLARE_DYNAMIC_DELEGATE_TwoParams //动态代理 DECLARE_DYNAMIC_MULTICAS ...
- JedisCluster中应用的Apache Commons Pool对象池技术
对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分. apache common pool 官方文档可以参考:https://c ...
- jQuery的selector和context属性
从jQuery1.3开始添加了这2个属性. 现在我们来看看那这2个属性的用法. selector属性是一个字符串.存储的字符串是选择器. HTML代码: <div class="guo ...
- 微软SMB 3.0文件共享协议新特性介绍
SMB(*nix平台和Win NT4.0又称CIFS)协议是Windows平台标准文件共享协议.Linux平台通过samba来支持.SMB最新版本v3.0,在v2.0基础上针对WAN和分布式有改进.详 ...
- solr查询空值、null、不存在的字段的方法
正常情况下我们都是按有值的方式去搜索,但是有时候有一些字段为null,solr中就没有存储进去,我们怎么获取这个字段不存在为条件的搜索结果了,我们只需要在搜索字段前加上负号,如下图 摘要: Solr的 ...
- Java反射机制 —— 简单了解
一.概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...
- 如何使用change命令改变密码的属性
使用chage更改用户密码密码使用情况 -d //设置最近一次更改密码时间, 0下次登陆系统强制修改密码 -m //设置用户两次改变密码之间使用"最小天数" -M //设置用户两次 ...