scene used
I often encounter the problem of switching between multiple environments in some projects. For example, the development environment is used in the development process, the test environment is used in the test, and the production environment is used in production. The spring.profile.active method is provided in springboot to realize multi-environment switching by setting environment variables and startup parameters. But this cannot be done once and for all, either you need to modify the yml file, or you need to remember to bring parameters when starting. Using maven profiles can reduce a lot of work. Let us step by step through a few examples to master the use of maven's profiles property.
Get started quickly
pom.xml file settings
<profiles>
<profile>
<!--不同环境Profile的唯一id-->
<id>dev</id>
<properties>
<!--profiles.active是自定义的字段(名字随便起),自定义字段可以有多个-->
<profiles.active>dev</profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
</properties>
</profile>
</profiles>
Directory Structure.
application.yml
spring:
profiles:
active: @profiles.active@
The code in application-dev.yml is as follows
server:
port: 7091
I just modified the port numbers for the other files, so that they can be packaged to see different effects.
Maven packaging and activation profiles
you can execute the command
mvn clean package -Ptest
Then start the jar package, you can see that the jar package starts the configuration of the test, if it is changed to -Pdev, it starts the port of the dev package.
default startup method
If -Ptest is not included, the port of prod is started. Because in profiles we see that there are options for configuring defaults.
<activation>
<activeByDefault>true</activeByDefault>
</activation>
Use activeProfiles in settings.xml to specify
<activeProfiles>
<activeProfile>profileTest1</activeProfile>
</activeProfiles>
Visible way of IDEA
Of course, if you use IDEA tools for development, you can also use visual packaging for packaging.
more advanced gameplay
Set dynamic parameters by combining with pom
If we want to use the docker-maven-plugin plug-in, the compiled jar is packaged into docker and passed to the corresponding development, testing, and production servers. At this time, we need to pass in different servers according to different conditions.
In profiles we can do the following definitions
<profiles>
<profile>
<id>dev</id>
<properties>
<profile.id>dev</profile.id>
<docker.host>http://dev.demo.com:2375</docker.host>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profile.id>test</profile.id>
<docker.host>http://test.demo.com375</docker.host>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profile.id>prod</profile.id>
<docker.host>http://prod.demo.com:2375</docker.host>
</properties>
</profile>
</profiles>
And in the build control we can use the following configuration
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>demo/${project.artifactId}</imageName>
<imageTags>
<imageTag>${project.version}-${current.time}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
<forceTags>true</forceTags>
<dockerHost>${docker.host}</dockerHost>
<forceTags>true</forceTags>
<baseImage>java:8</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
Where ${project.artifactId} and ${project.version} are references to and below the node. ${current.time} is defined in build-helper-maven-plugin, let's study it later.
${docker.host} is defined in the profiles. We can build jar packages into different docker images as we choose different profiles, and pass them to the specified server.
Set dynamic parameters by combining with yml
In addition to setting dynamic parameters in pom, it can select different parameters according to different profiles. You can also let yml choose different parameters by setting different profiles. This is somewhat similar to the example of getting started quickly. details as follows:
set profiles
<profiles>
<profile>
<id>dev</id>
<properties>
<profile.id>dev</profile.id>
<eureka.url>http://127.0.0.1:8001/eureka</eureka.url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profile.id>test</profile.id>
<eureka.url>http://base-registry:8001/eureka</eureka.url>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profile.id>prod</profile.id>
<eureka.url>http://base-registry:8001/eureka</eureka.url>
</properties>
</profile>
<profile>
<id>new</id>
<properties>
<profile.id>new</profile.id>
<eureka.url>http://base-registry:8001/eureka</eureka.url>
</properties>
</profile>
</profiles>
We set a eureka.url property in the profile, which can be called directly in yml.
eureka:
client:
service-url:
defaultZone: @eureka.url@
registry-fetch-interval-seconds: 10
instance:
prefer-ip-address: true
When IDEA is debugging and starting, the error is generally reported as follows:
org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token
found character ‘@’ that cannot start any token.
The solution is to introduce the jar package of yaml.sankeyaml
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
Package different resources
When the profile packs the yml file, if we unzip the jar package, we will find that all the application-profile.yml files are still packaged. This can be done by setting the packaging parameters to only package the required application files.
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prd</id>
<properties>
<env>prd</env>
</properties>
</profile>
</profiles>
<build>
<finalName>springmvc</finalName>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>dev/*</exclude>
<exclude>prd/*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/${env}</directory>
</resource>
</resources>
</build>
The directory structure is as follows: