遇到不少次别人处理的项目,测试环境,本地开发和线上环境的配置不同,每一次部署都要从新修改配置文件,提交审核代码,才能打包,很是不方便。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中方式: