接上回繼續,項目開發好之後,一般要在多個環境部署,象咱們公司多達5種環境:本機環境(local)、(開發小組內自測的)開發環境(dev)、(提供給測試團隊的)測試環境(test)、預發佈環境(pre)、正式生產環境(prod),每種環境都有各自的配置參數,好比:數據庫鏈接、遠程調用的ws地址等等。若是每一個環境build前手動修改這些參數,顯然太不fashion.html
maven早就考慮到了這些問題,看下面的pom片斷:web
<profiles> <profile> <!-- 本地環境 --> <id>local</id> <properties> <db-url>jdbc:oracle:thin:@localhost:1521:XE</db-url> <db-username>***</db-username> <db-password>***</db-password> </properties> </profile> <profile> <!-- 開發環境 --> <id>dev</id> <properties> <db-url>jdbc:oracle:thin:@172.21.129.51:1521:orcl</db-url> <db-username>***</db-username> <db-password>***</db-password> </properties> <!-- 默認激活本環境 --> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> ... </profiles>
profiles節點中,定義了二種環境:local、dev(默認激活dev環境),能夠在各自的環境中添加須要的property值,接下來修改build節點,參考下面的示例:spring
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.6</source> <target>1.6</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build>
resource節點是關鍵,它代表了哪一個目錄下的配置文件(無論是xml配置文件,仍是properties屬性文件),須要根據profile環境來替換屬性值。數據庫
一般配置文件放在resources目錄下,build時該目錄下的文件都自動會copy到class目錄下apache
以上圖爲例,其中spring-database.xml的內容爲:tomcat
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="${db-url}" /> <property name="username" value="${db-username}" /> <property name="password" value="${db-password}" /> </bean> </beans>
各屬性節點的值,用佔位符"${屬性名}"佔位,maven在package時,會根據profile的環境自動替換這些佔位符爲實際屬性值。服務器
默認狀況下: oracle
maven packageapp
將採用默認激活的profile環境來打包,也能夠手動指定環境,好比:dom
maven package -P dev
將自動打包成dev環境的部署包(注:參數P爲大寫)
最後再給2個實例的運用例子:
一、開發環境與生產環境數據源採用不一樣方式的問題
本機開發時爲了方便,不少開發人員喜歡直接用JDBC直接鏈接數據庫,這樣修改起來方便;
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="${db-url}" /> <property name="username" value="${db-username}" /> <property name="password" value="${db-password}" /> <property name="defaultAutoCommit" value="false" /> <property name="initialSize" value="2" /> <property name="maxActive" value="10" /> <property name="maxWait" value="60000" /> </bean>
而生產環境,一般是在webserver(好比weblogic上)配置一個JNDI數據源,
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="appDS" /> </bean>
若是每次發佈生產前,都要手動修改,未免太原始,能夠經過maven的profile來解決
先把配置文件改爲
<bean id="${db-source-jdbc}" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="${db-url}" /> <property name="username" value="${db-username}" /> <property name="password" value="${db-password}" /> <property name="defaultAutoCommit" value="false" /> <property name="initialSize" value="2" /> <property name="maxActive" value="10" /> <property name="maxWait" value="60000" /> </bean> <bean id="${db-source-jndi}" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="appDS" /> </bean>
即用佔位符來代替bean的id,而後在pom.xml裏相似下面設置
<profile> <!-- 本機環境 --> <id>local</id> <properties> ... <db-source-jdbc>dataSource</db-source-jdbc> <db-source-jndi>NONE</db-source-jndi> <db-url>jdbc:oracle:thin:@172.21.129.51:1521:orcl</db-url> <db-username>mu_fsu</db-username> <db-password>mu_fsu</db-password> ... </properties> <!-- 默認激活本環境 --> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <!-- 生產環境 --> <id>pro</id> <properties> ... <db-source-jdbc>NONE</db-source-jdbc> <db-source-jndi>dataSource</db-source-jndi> ... </properties> </profile> </profiles>
這樣,mvn clean package -P local打包本地開發環境時,將生成
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@172.21.129.***:1521:orcl" /> <property name="username" value="***" /> <property name="password" value="***" /> <property name="defaultAutoCommit" value="false" /> <property name="initialSize" value="2" /> <property name="maxActive" value="10" /> <property name="maxWait" value="60000" /> </bean> <bean id="NONE" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="appDS" /> </bean>
而打包生產環境 mvn clean package -P pro時,生成
<bean id="NONE" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="${db-url}" /> <property name="username" value="${db-username}" /> <property name="password" value="${db-password}" /> <property name="defaultAutoCommit" value="false" /> <property name="initialSize" value="2" /> <property name="maxActive" value="10" /> <property name="maxWait" value="60000" /> </bean> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="appDS" /> </bean>
spring配置的其它跟數據庫相關的bean,約定引用dataSource這個名稱的bean便可
二、不一樣webserver環境,依賴jar包,是否打包的問題
weblogic上,容許多個app,把共用的jar包按約定打包成一個war文件,以library的方式部署,而後各應用在WEB-INF/weblogic.xml中,用相似下面的形式
<?xml version="1.0" encoding="utf-8"?> <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"> ... <library-ref> <library-name>my-share-lib</library-name> </library-ref> </weblogic-web-app>
指定共享library 的名稱便可。這樣的好處是,即節省了服務器開銷,並且各app打包時,就沒必要再重複打包這些jar文件,打包後的體積大大減小,上傳起來會快不少。
而其它webserver上卻未必有這個機制,通常爲了方便,咱們開發時,每每採用一些輕量級的webserver,好比:tomcat,jetty,jboss 之類,正式部署時才發佈到weblogic下,這樣帶來的問題就是,本機打包時,要求這些依賴jar包,全打包到app的WEB-INF/lib下;而生產環境下,各應用的WEB-INF/lib下並不須要這些jar文件,一樣仍是用profile來搞定,先處理pom.xml,把依賴項改爲相似下面的形式:
<dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> <scope>${jar.scope}</scope> </dependency>
即scope這裏,用一個佔位符來代替,而後profile這樣配置
<profile> <!-- 本機環境 --> <id>local</id> <properties> <jar.scope>compile</jar.scope> ... </properties> <!-- 默認激活本環境 --> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <!-- 生產環境 --> <id>pro</id> <properties> <jar.scope>provided</jar.scope> ... </properties> </profile>
在maven裏,若是一個依賴項的scope是provided,表示由容器提供,打包時將不會打包進最終的package裏,因此這樣配置後,生產環境打包時,依賴項的scope全變成了provided,即不打包進war文件,而本機環境下,由於scope是compile,因此會打包到war裏