遇到不少次別人處理的項目,測試環境,本地開發和線上環境的配置不同,每一次部署都要從新修改配置文件,提交審覈代碼,才能打包,很是不方便。mysql
其實相信不少人都知道可使用maven來作配置分離,不過經過maven來作配置分離也有多種方式,一種是經過filter,一種是經過配置文件拷貝。spring
filter這種方式看不少文章感受做者理解是有誤的,而且這種在IDE中開發的時候就很差用了,因此推薦配置文件拷貝的方式。sql
下面就來介紹一下這兩種方式。apache
咱們先看一下項目目錄:mybatis
jdbc.url = jdbc:mysql://127.0.0.1:3306/mybatis?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
jdbc.url = jdbc:mysql://192.168.0.2:3308/mybatis?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
jdbc.url=${jdbc.url}
爲了簡化問題,這裏就只配置一個最簡的配置,spring-datasource.xml中的DataSource加載的就是jdbc.properties文件中的配置。maven
咱們知道在maven構建(build)過程當中有一個拷貝資源的階段,這個能夠經過resources標籤配置。若是不知道,那麼如今就把他當作一個真理。 resources是在build標籤下,咱們能夠看一下resources配置。測試
<resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>config-pro.properties</exclude> <exclude>config-dev.properties</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>jdbc.properties</include> </includes> <filtering>true</filtering> </resource> </resources>
上面的配置了2個resource標籤,第一個resource的意思就是把src/main/resources目錄下的所有文件拷貝到classpath下,通常打包後就是在和src同一級。固然要除了excludes中配置的config-pro.properties和config-dev.properties這兩個文件。優化
第二個resource配置的就是拷貝jdbc.properties這個文件,爲何前面配置了拷貝所有,後面還要單獨配置一個呢?是由於咱們要對這個文件執行filter。咱們看到filtering標籤設置爲true就是這個目的。ui
那麼問題來了,什麼事filtering呢? 咱們前面知道jdbc.properties的配置包含佔位符,以下:url
jdbc.url=${jdbc.url}
filtering就是處理配置文件中的佔位符的。
那麼配置文件中的佔位符又是在什麼地方配置的呢?
咱們能夠看到filters標籤:
<filters> <filter>src/main/resources/config-dev.properties</filter> </filters>
filters標籤中就是配置配置文件中佔位符的配置文件,能夠理解爲配置文件的配置文件。感受有點繞。不過沒有關係,咱們來看一下完整的pom配置。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.freemethod</groupId> <artifactId>maven-split</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> </dependencies> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>config-pro.properties</exclude> <exclude>config-dev.properties</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>jdbc.properties</include> </includes> <filtering>true</filtering> </resource> </resources> <finalName>split</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.8</version> <configuration> <!-- 跳過測試 --> <skipTests>true</skipTests> </configuration> </plugin> <!--<plugin>--> <!--<groupId>org.apache.maven.plugins</groupId>--> <!--<artifactId>maven-dependency-plugin</artifactId>--> <!--<version>2.8</version>--> <!--<executions>--> <!--<execution>--> <!--<id>copy-dependencies</id>--> <!--<phase>package</phase>--> <!--<goals>--> <!--<goal>copy-dependencies</goal>--> <!--</goals>--> <!--<configuration>--> <!--<outputDirectory>${project.build.directory}/lib</outputDirectory>--> <!--</configuration>--> <!--</execution>--> <!--</executions>--> <!--</plugin>--> </plugins> </build> <profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <filters> <filter>src/main/resources/config-dev.properties</filter> </filters> </build> </profile> <profile> <id>pro</id> <build> <filters> <filter>src/main/resources/config-pro.properties</filter> </filters> </build> </profile> </profiles> </project>
我把其餘的配置都刪除了,只留下了build相關的配置。
這裏說一下profile,這個能夠在構建命令中指定profile的id來肯定使用哪一個profile。 activeByDefault標籤標示默認使用的profile。
咱們能夠在使用下面的構建命令來使用id爲pro的profile:
mvn package -Ppro
下面咱們能夠在項目目錄下分別經過下面的命令來構建開發和生產環境的配置:
mvn package -Ppro mvn package
構建完能夠看到target目錄以下:
把jar包的後綴修改一下,改成zip,而後查看能夠看到jdbc.properties文件分別變爲了:
jdbc.url = jdbc:mysql://127.0.0.1:3306/mybatis?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
jdbc.url = jdbc:mysql://192.168.0.2:3308/mybatis?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
filter方式還能夠經過下面的方式配置:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.freemethod</groupId> <artifactId>maven-split</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> </dependencies> <build> <filters> <filter>src/main/resources/config-${env}.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>config-pro.properties</exclude> <exclude>config-dev.properties</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>jdbc.properties</include> </includes> <filtering>true</filtering> </resource> </resources> <finalName>split</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.8</version> <configuration> <!-- 跳過測試 --> <skipTests>true</skipTests> </configuration> </plugin> <!--<plugin>--> <!--<groupId>org.apache.maven.plugins</groupId>--> <!--<artifactId>maven-dependency-plugin</artifactId>--> <!--<version>2.8</version>--> <!--<executions>--> <!--<execution>--> <!--<id>copy-dependencies</id>--> <!--<phase>package</phase>--> <!--<goals>--> <!--<goal>copy-dependencies</goal>--> <!--</goals>--> <!--<configuration>--> <!--<outputDirectory>${project.build.directory}/lib</outputDirectory>--> <!--</configuration>--> <!--</execution>--> <!--</executions>--> <!--</plugin>--> </plugins> </build> <profiles> <profile> <id>dev</id> <properties> <env>dev</env> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>pro</id> <properties> <env>pro</env> </properties> </profile> </profiles> </project>
能夠本身感覺一下這2中配置的區別。
經過filter有一個問題就是,本地IDE中啓動配置文件中的佔位符不會處理,由於沒有執行構建過程,和maven相關的命令。
因此能夠經過拷貝文件來處理。
這個是什麼意思呢?
就是一個環境對一個配置文件,執行maven構建過程處理resource的時候,拷貝指定的文件就能夠了。
下面就是拷貝資源方式的項目結構:
在這種模式下,咱們須要新建文件夾,由於咱們須要文件名字同樣。因此咱們創建了一個dev和pro文件夾裏面存放的方即是開發環境和生成環境的,若是須要測試環境的只須要再創建一個文件夾存放測試環境的配置文件就能夠了。注意文件名字保持一致。
接下來咱們就來看一下怎樣配置pom文件了:
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>config-pro.properties</exclude> <exclude>config-dev.properties</exclude> <exclude>jdbc.properties</exclude> <exclude>dev/*</exclude> <exclude>pro/*</exclude> </excludes> </resource> <resource> <directory>src/main/resources/${env}</directory> <includes> <include>jdbc.properties</include> </includes> </resource> </resources> <finalName>split</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.8</version> <configuration> <!-- 跳過測試 --> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> <profiles> <profile> <id>dev</id> <properties> <env>dev</env> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>pro</id> <properties> <env>pro</env> </properties> </profile> </profiles>
須要注意的地方就是咱們第一個resource把 jdbc.properties配置文件排除了。
第二個resource:
<resource> <directory>src/main/resources/${env}</directory> <includes> <include>jdbc.properties</include> </includes> </resource>
咱們能夠看到使用了一個${env},這個咱們不須要像filter在其餘文件中配置,能夠直接配置在profile中:
<profiles> <profile> <id>dev</id> <properties> <env>dev</env> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>pro</id> <properties> <env>pro</env> </properties> </profile> </profiles>
看上面的profiles的配置,每個profile中都一個一個properties的標籤裏面有一個env標籤,env標籤的值就是上面${env}的引用。
因此當咱們使用:
mvn package -Pdev
打包的時候就會拷貝dev文件夾下的 jdbc.properties到指定目錄下(通常是src同級目錄,看文件結構,這裏就是src同級目錄,也就是包含在classpath中)
若是使用:
mvn package -Ppro
打包就會拷貝pro文件加下的 jdbc.properties到指定目錄下(通常是src同級目錄,看文件結構,這裏就是src同級目錄,也就是包含在classpath中)
注意咱們directory指定的目錄拷貝的目標目錄都是到src目錄下,若是要拷貝文件夾就得指定爲上級目錄 另外上面的方式還能夠優化一下,由於咱們的dev配置和本地通常是同樣的,因此咱們不須要創建dev文件夾。咱們不須要排除jdbc.properties文件了就是把
<exclude>jdbc.properties</exclude>
而後添加一個拷貝資源覆蓋模式的配置:
<properties> <maven.resources.overwrite>true</maven.resources.overwrite> </properties>
這樣就實現了默認使用jdbc.properties文件,當打包的時候就會使用指定文件覆蓋jdbc.properties文件。
另外不只僅是package階段,只有包含resources階段的就會執行,例如:
mvn install
因此經過maven分離配置,這裏有2中方式: