在Maven和Spring中,都有profile这个概念。profile是用于区分各类环境的,例如开发环境、测试环境、正式环境等。Maven的profile用于在打包时根据指定环境替换不一样环境的配置文件配置,如数据库配置。Spring的Profile能够用于在不一样的环境下加载不一样的bean,例如@Profile
注解。二者一个是Maven编译和打包时生效,另外一个是运行时生效,默认是没有关联的,本文会分别介绍非Spring Boot项目和Spring Boot项目整合Maven profile。html
在pom.xml
中,能够配置test
和product
两个profile,分别对应测试环境和正式环境。这里也能够根据具体状况自定义。web
<profiles> <profile> <id>test</id> ... </profile> <profile> <id>product</id> ... </profile> </profiles>
此时,运行mvn package -Ptest
就会使用id为test的profile内的配置打包,mvn package -Pproduct
就是用来打正式环境包的命令。spring
Spring启用某个profile有多种方式(摘自官方文档:https://docs.spring.io/spring... ):数据库
Activating a profile can be done in several ways, but the most straightforward is to do it programmatically against the Environment API which is available through an ApplicationContext.
In addition, you can also declaratively activate profiles through the spring.profiles.active property, which may be specified through system environment variables, JVM system properties, servlet context parameters in web.xml, or even as an entry in JNDI.
总结一下有如下几种方式:app
ApplicationContext.getEnvironment().setActiveProfiles("yourProfile")
spring.profiles.active
值来设置spring.profiles.active
值来设置web.xml
中的context-param
来设置为了便于跟Maven整合,咱们使用web.xml
来设置Spring profile,以下:框架
<context-param> <param-name>spring.profiles.active</param-name> <param-value>product</param-value> </context-param>
以上配置会启用Spring的product
profile,即正式环境。eclipse
若是想要整合Maven profile和Spring Framework profile,须要在Maven打包时对web.xml
中的spring.profiles.active
值进行替换,能够在web.xml
中配置一个占位符${activeProfile}
:jsp
<context-param> <param-name>spring.profiles.active</param-name> <param-value>${activeProfile}</param-value> </context-param>
在pom.xml
配置maven-war-plugin
:maven
<!-- 打war包时替换占位符 --> <build> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> <configuration> <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> </configuration> </plugin> </build> <!-- 默认的maven profile --> <properties> <activeProfile>dev</activeProfile> </properties> <profiles> <profile> <id>test</id> <properties> <activeProfile>test</activeProfile> </properties> </profile> <profile> <id>product</id> <properties> <activeProfile>product</activeProfile> </properties> </profile> </profiles>
<filteringDeploymentDescriptors>
为true
表示过滤Deployment Descriptor
并将文件中的占位符替换为pom.xml
中对应的<properties>
值,Deployment Descriptor
即部署描述符,指的就是web.xml (参考维基百科:https://zh.wikipedia.org/wiki... )。ide
以上配置完成后,再经过mvn package -Ptest
或mvn package -Pproduct
打包后,再解压war包,能够看到web.xml
中原有的
<context-param> <param-name>spring.profiles.active</param-name> <param-value>${activeProfile}</param-value> </context-param>
被替换为了Maven中对应的profile,例如mvn package -Pproduct
打包后web.xml
内容:
<context-param> <param-name>spring.profiles.active</param-name> <param-value>product</param-value> </context-param>
以上就完成了Maven profile和Spring profile的整合。
若是刚好在项目中使用到jetty-maven-plugin
用于开发环境调试,那么在web.xml
配置占位符${activeProfile}
后,经过mvn jetty:run
启动应用时会Spring框架会报错:
Could not resolve placeholder 'activeProfile' in string value "${activeProfile}"
这是由于运行mvn jetty:run
命令时插件并无打war包,而是直接使用源码中的web.xml
,此时占位符${activeProfile}
未被maven-war-plugin
替换,因此Spring框架会报错。
参考文档:https://www.eclipse.org/jetty...
使用mvn jetty:run-war
或mvn jetty:run-exploded
命令替代mvn jetty:run
,这两个命令会先用maven-war-plugin
打好war包后再运行,此时占位符${activeProfile}
已被替换为Maven的profile。
可是这种方案会带来一个问题:因为这种方式须要先打war包再运行,开发时项目中资源(例如html、jsp)修改后就不会实时生效,而是须要从新打包启动,不便于调试。
这种方案仍是使用mvn jetty:run
命令,只须要给jetty-maven-plugin
插件添加一个名为activeProfile
的系统属性,让Spring框架来解析web.xml
中的${activeProfile}
:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.10.v20150310</version> <configuration> <webApp> <contextPath>/</contextPath> </webApp> <systemProperties> <systemProperty> <name>activeProfile</name> <value>${activeProfile}</value> </systemProperty> </systemProperties> </configuration> </plugin>
参考文档:https://www.eclipse.org/jetty...
若是项目采用的框架是Spring Boot而不是直接使用Spring Framework,那么Spring Boot的profile能够在resources目录下的application.properties
或application.yml
文件中指定,以application.properties
为例:
spring.profiles.active=product
要想整合Maven profile只须要改成@activeProfile@
占位符便可:
spring.profiles.active=@activeProfile@
仅须要这一行配置就完成了Spring Boot profile整合Maven profile,很是方便。此时能够尝试mvn package -Ptest
或mvn package -Pproduct
命令打包,安装包内的文件中@activeProfile@
占位符已被替换。
Spring Boot项目中通常都会加上spring-boot-starter-parent
:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>${spring.boot.version}</version> </parent>
能够查看spring-boot-starter-parent
的pom.xml文件,里面包含maven-resources-plugin
:
<plugin> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimiter>${resource.delimiter}</delimiter> </delimiters> <useDefaultDelimiters>false</useDefaultDelimiters> </configuration> </plugin>
${resource.delimiter}
定义的值是@
:
<resource.delimiter>@</resource.delimiter>
这样maven-resources-plugin
插件会将application.properties
或application.yml
文件中的@activeProfile@
替换为pom.xml
中对应profile的值。
至于为何Spring Boot要使用@..@
而不是Maven默认的${..}
做为占位符的符号,官方文档也给出了解释,如下摘自:https://docs.spring.io/spring...
Note that, since the application.properties and application.yml files accept Spring style placeholders (${…}), the Maven filtering is changed to use @..@ placeholders. (You can override that by setting a Maven property called resource.delimiter.)
由于Spring Boot框架自己也用${..}
做为占位符,Maven插件maven-resources-plugin
若是还使用相同的占位符,那么可能会致使一些冲突,因此spring-boot-starter-parent
将maven-resources-plugin
的占位符改成@..@
。