在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
的佔位符改成@..@
。