原创地址:http://blog.csdn.net/lw_power/article/details/52495296
这一节我们介绍 Maven 的 Web 项目使用 war 插件针对不同环境打包。这是我在 BAE 部署自己的博客应用的时候整理的一种方案,供大家参考。
最最重要的思路其实就一条:打包之前替换配置文件,从手动变为自动。重点内容
需求的提出:
在开发阶段,我们的 MySQL 数据库连接配置基本上都连着本机数据库, Lucene 索引存放目录基本上是开发者本机的一个目录。但是到了生产环境部署的时候, MySQL 数据库的连接配置和 Lucene 索引存放目录就是另外一个配置了。
那么,我们在打包到生产环境之前是不是要手动将这些配置替换一下呢?
如果手动这样做的话,就显得不灵活,很笨拙了。
好在 Maven 这项工具早就帮我们想到了这个问题。下面我就介绍一下,我在自己的项目 Blog 中是如何操作的。
思路分析:
1、自己的项目里只要是有配置的地方,不要写死在源代码目录(src/main/java)中,而要将配置的信息写在资源目录中 (src/main/resources);
2、即使是写在资源目录中的代码,也尽量将特殊化的配置信息写在配置文件中,这样做的好处有以下两点:
(1)配置信息一般是比较重要的,尤其是生产环境中的配置信息,现在很多代码开源了以后,开发者如果将配置信息提交到 Git 仓库中,很有可能造成一些安全隐患(服务器的连接参数都暴露了,你说能安全吗?),所以一般情况下,这些重要的服务器配置文件应该被 Git 排除掉;
(2)分离出配置信息成为单独的配置文件也方便开发者进行单独管理。
这样开发者将代码开源以后即使不给出配置文件的代码,其他学习者拿到项目以后仍然可以根据 ${db.username}
这样的代码填写出自己本地的配置信息。
即:我们不建议这么做。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/db_blog?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
应该这样做:
<context:property-placeholder location="classpath:config/jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
在 config/jdbc.properties 文件中写:
db.url=jdbc:mysql://localhost:3306/db_blog?useUnicode=true&characterEncoding=UTF-8
db.username=root
db.password=123456
3、在资源目录下建立不同环境的文件夹,有几个环境,就应该建立几个文件夹;
4、使用 Maven 的 war 插件,使用命令指定打包参数,在打包之前替换那些重要的配置文件,就可以针对不同的环境打出适合这些环境的 war 包了。
具体配置代码分析
1、声明主资源目录
<!-- 主资源目录 -->
<resources>
<resource>
<!-- 设置主资源目录 -->
<directory>src/main/resources</directory>
<!-- maven default生命周期,process-resources阶段执行maven-resources-plugin插件的resources目标处理主资源目下的资源文件时,是否对主资源目录开启资源过滤 -->
<filtering>true</filtering>
<!-- maven default生命周期,process-resources阶段执行maven-resources-plugin插件的resources目标处理主资源目下的资源文件时,只处理如下配置中包含的资源类型 -->
<!-- 包括文件 -->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!-- maven default生命周期,process-resources阶段执行maven-resources-plugin插件的resources目标处理主资源目下的资源文件时,不处理如下配置中包含的资源类型(剔除下如下配置中包含的资源类型)-->
<!-- 排除文件,这些文件打包的时候应该被排除 -->
<excludes>
<exclude>config/local/*.properties</exclude>
<exclude>config/product/*.properties</exclude>
</excludes>
</resource>
</resources>
2、声明 profile
<profiles>
<profile>
<id>local</id>
<properties>
<package.environment>local</package.environment>
</properties>
<activation>
<!-- 默认激活这个配置 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境,这里指的是我的 百度云 BAE 环境 -->
<id>product</id>
<properties>
<package.environment>product</package.environment>
</properties>
</profile>
</profiles>
特别说明:profile 中的 id,自定义的环境变量 package.environment 的值,和“思路分析3”中建立的不同环境配置文件存放的目录名称应该是一致的,这也叫约定大于配置,这样的约定就可以少配置很多东西了。
3、声明 war 插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<!-- 部署在百度云 bae 上,一定要叫 ROOT.war -->
<!-- 虽然 IDEA 工具报提示警告,但是可以不理会,不影响使用 -->
<warName>ROOT</warName>
<webResources>
<resource>
<directory>src/main/resources/config/${package.environment}</directory>
<targetPath>WEB-INF/classes/config</targetPath>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
说明:
warName :指定了打好包的名字;
webResources 下 resource 下 directory :配置真正使用的资源文件存放的位置,通常这个位置不是一个标准 Web 项目应该存放资源文件的位置;
webResources 下 resource 下 targetPath:将上一步 directory 中配置的文件目录下的文件都拷贝到这个目录下;‘
webResources 下 resource 下 filtering:开启打包之前将 directory 下的文件拷贝(覆盖)到 targetPath 下这种配置。
4、介绍运行命令
(1)本地测试
因为我是用 Jertty 插件,本地配置都是本地开发环境的配置,所以可以直接使用
mvn jetty:run
启动 Jetty 服务器。
附:Jetty 插件配置
<!-- Jetty 插件:在本地部署测试更加方便 -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<httpConnector>
<port>8080</port>
</httpConnector>
</configuration>
</plugin>
(2)打本地环境的包
mvn package -DskipTests
因为我在 profile 的 id 为 local 的配置下写了
<activation>
<!-- 默认激活这个配置 -->
<activeByDefault>true</activeByDefault>
</activation>
所以使用 mvn package -DskipTests
不指定 profile 就默认打出的是本地开发环境的 war 包。
(3)打生产环境的包
mvn clean package -DskipTests -Pproduct
说明:通过 -P 指定 profile。