对于 Spring Boot 框架,实际上通常会使用 properties 文件进行多环境开发,相关内容见。
实际上同样可以用 Maven 来控制不同的环境加载不同的配置项。这样做更具备普遍性,意味着所有用 Maven 管理的 Java 项目都可以用这种方式来进行多环境开发。
这里使用的示例项目是,对应的测试数据 SQL文件是。
解压后将父模块 maven-parent 作为项目用 Idea 加载即可。
在上一篇文章中,我们已经将 properties 文件中的相关配置信息使用 Maven 属性来配置和管理:
<properties>
<jdbc.username>root</jdbc.username>
<jdbc.password>mysql</jdbc.password>
<jdbc.driver>com.mysql.cj.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql:///mybatis?useSSL=false</jdbc.url>
</properties>
1.1.Profile
在多环境开发的要求下,我们必须将这些属性定义到不同的“配置文件”(Profile)中:
<profiles>
<profile>
<id>env_dev</id>
<properties>
<jdbc.username>root</jdbc.username>
<jdbc.password>mysql</jdbc.password>
<jdbc.driver>com.mysql.cj.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql:///mybatis?useSSL=false</jdbc.url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>env_test</id>
<properties>
<jdbc.username>test</jdbc.username>
<jdbc.password>mysql</jdbc.password>
<jdbc.driver>com.mysql.cj.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql:///mybatis?useSSL=false</jdbc.url>
</properties>
</profile>
<profile>
<id>env_prd</id>
<properties>
<jdbc.username>prd</jdbc.username>
<jdbc.password>mysql</jdbc.password>
<jdbc.driver>com.mysql.cj.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql:///mybatis?useSSL=false</jdbc.url>
</properties>
</profile>
</profiles>
原 properties 标签中的相应属性要删除。
在这里,profile 标签代表不同环境下的“配置文件”,id 标签是配置文件的标识符,properties 标签中是具体的自定义属性。用 activation 标签可以定义默认生效的配置文件。
可以改变 activation 标签所属的配置文件来改变默认生效的配置文件:
<profile>
<id>env_test</id>
<properties>
<jdbc.username>test</jdbc.username>
<jdbc.password>mysql</jdbc.password>
<jdbc.driver>com.mysql.cj.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql:///mybatis?useSSL=false</jdbc.url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
再次编译项目就能观察到生成的 war 包中的 jdbc.properties 文件使用了 env_test 配置文件中的自定义属性。
1.2.activate-profiles
但这样做会很麻烦(每次切换环境都要修改 POM 文件)。可以在执行 Maven 命令 时加上参数来控制使用哪个配置文件:
mvn install --activate-profiles env_prd
也可以使用简写形式:
mvn install -P env_prd
这样 Maven 就会使用指定配置文件编译/安装项目。
小技巧,在 Idea 的 Maven 工具中,可以使用这个按钮来执行 Maven 命令:
2.跳过测试
在 Maven 的生命周期中,test 环节位于 package 和 install 之前:
因此执行 package 或 install 操作会自动执行 test 操作。
这里不知道为什么,我的项目并不会执行测试环节,需要手动添加 maven-surefire-plugin 插件:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin>
如果有需要,我们可以让项目编译/安装时不进行测试环节。
2.1.Maven 工具
最简单的方式是使用 Idea 的 Maven 工具:
这个小按钮按下后,Maven 生命周期中的 test 环节会变成灰色,也就不会触发。
2.2.Maven 插件
第二种方式为修改负责执行单元测试的 Maven 插件的相关配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
还可以配置成执行测试环节,但是不包括某些测试套件(Tests):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>false</skipTests>
<excludes>
<exclude>**/BookServiceTests.java</exclude>
</excludes>
</configuration>
</plugin>
假设此时 mvc-demo 模块下有两个测试套件:BookServiceTests
和UserServiceTests
。后者会执行,而前者不会。
2.3.命令行参数
最后还可以通过参数控制是否执行测试环节:
mvn install -D skipTests
但前提条件是不能在 Maven 测试插件中添加相关设置(比如 skipTests),否则这个参数不会起作用。
3.私服
是一个比较流行的 Maven 私服软件,这里介绍如何安装和使用。
3.1.安装
有多种安装方式,这里选择使用 进行安装。
下载镜像:
[icexmoon@192 ~]$ docker pull sonatype/nexus3
查看下载的镜像:
[icexmoon@192 ~]$ docker images | grep nexus
sonatype/nexus3 latest 589f7296a4a2 20 months ago 655MB
为了能够持久化数据,为 Nexus 创建数据卷:
[icexmoon@192 ~]$ docker volume create --name nexus-data
nexus-data
启动:
[icexmoon@192 ~]$ docker run -d -p 8081:8081 --name nexus -v nexus-data:/nexus-data sonatype/nexus3
Nexus 监听的端口是 8081。
Nexus 启动需要至少 5G 的磁盘空间,否则会启动失败(比如我可怜的虚拟机)。
启动 OK 后访问 8081 端口(比如 http://192.168.0.88:8081/)就可以访问管理页面:
可以通过右上角的 Sign in 登录,会提示密码位于/nexus-data/admin.password
。
因为这里我们使用数据卷,所以只需要到数据卷加载的目录下查看该文件的内容即可,具体的数据卷相关操作可以阅读。
3.2.仓库分类
私服中的仓库可以分为三种类型:
关于这些仓库分类的详细说明,可以观看这个。
3.3.配置
使用私服上传和下载前需要经过一些配置。
3.3.1.服务端
默认的 Nexus 就包含很多仓库:
其中名称为maven-centrial
类型为proxy
的这个仓库是 Maven 中央仓库的代理仓库。也就是说我们可以通过 Nexus 上的这个仓库从中央仓库获取 Jar 包,这个仓库可以缓存获取过的 Jar 包,第二次获取就会快很多。
当然,最好修改这个仓库的配置,让其从国内的中央仓库的镜像站下载而不是直接从中央仓库下载:
最好创建两个 hosted 仓库用于我们自己开发的 jar 包的发布和下载,一个用于 snapshot 版本的 jar 包,另一个用于 release 版本的 jar 包。
其它保持默认即可。
另一个仓库 icexmoon-release 的创建过程与之类似。
为了方便下载这两个仓库的 jar 包,我们需要将其加入到类型为 group 的仓库组中:
需要在其 Group 设置中将刚创建的两个仓库移动到右边的 Members 列表中。
3.3.2.本地仓库
要修改本地 Maven 仓库的配置(setting.xml),先添加两个 Maven 私服的配置:
<servers>
<server>
<id>icexmoon-release</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>icexmoon-snapshot</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
这里服务器 id 填刚创建的两个仓库的名称,用户名和密码填 Nexus 的管理员帐号和密码。
还需要添加一个镜像配置:
<mirror>
<id>maven-public</id>
<url>http://192.168.0.88:8081/repository/maven-public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
这里配置的信息是 Nexus 的仓库组的信息:
3.3.3.Maven 工程
要让创建好的 Maven 工程打包后发布到 Nexus 仓库,还需要修改 Maven 工程中的配置信息。
在这个示例中我们修改父模块 mvc-demo-parent 中的 pom.xml:
<distributionManagement>
<repository>
<id>icexmoon-release</id>
<url>http://192.168.0.88:8081/repository/icexmoon-release/</url>
</repository>
<snapshotRepository>
<id>icexmoon-snapshot</id>
<url>http://192.168.0.88:8081/repository/icexmoon-snapshot/</url>
</snapshotRepository>
</distributionManagement>
添加了两个仓库,repository
用于发布正式版 jar 包,snapshotRepository
发布开发版 jar 包。
3.4.发布
在发布我们自己开发的 jar 包前,可以先查看一下私服上相应仓库的 jar 包:
目前是空的。
执行 Maven 生命周期中的最后一个 deploy 就可以将项目打包并发布到 Nexus 仓库。
发布后的仓库页面:
如果是协同开发,其他人就可以从这个仓库拉取你开发的模块作为依赖了。
如果要发布到正式仓库(icexmoon-release),就需要将项目的版本号后缀修改为RELEASE
:
<groupId>cn.icexmoon</groupId>
<artifactId>mvc-demo-parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
注意,所有子模块的版本号同样要修改,以及引用的父模块内容:
<groupId>cn.icexmoon</groupId>
<artifactId>mvc-demo</artifactId>
<version>1.0-RELEASE</version>
<packaging>war</packaging>
<name>mvc-demo Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<parent>
<groupId>cn.icexmoon</groupId>
<artifactId>mvc-demo-parent</artifactId>
<version>1.0-RELEASE</version>
<relativePath>../mvc-demo-parent/pom.xml</relativePath>
</parent>
The End,谢谢阅读。
本文的完整示例可以从获取。
文章评论