项目构建
Resource | 资源管理
它对应的配置方式为:
<project>
...
<build>
...
<resources>
<resource>
<directory>[your folder here]</directory>
</resource>
</resources>
...
</build>
...
</project>
对于如下的结构:
Project
|-- pom.xml
`-- src
`-- my-resources
我们需要在 pom 文件中进行如下配置:
...
<resources>
<resource>
<directory>src/my-resources</directory>
</resource>
</resources>
...
譬如如果我们要用 Maven 构建一个 Web 项目,会在 src/main 目录下构建一个
选择包含或者忽视文件或者目录
<project>
...
<name>My Resources Plugin Practice Project</name>
...
<build>
...
<resources>
<resource>
<directory>src/my-resources</directory>
<excludes>
<exclude>**/*.bmp</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.gif</exclude>
</excludes>
</resource>
<resource>
<directory>src/my-resources2</directory>
<includes>
<include>**/*.txt</include>
</includes>
<excludes>
<exclude>**/*test*.*</exclude>
</excludes>
</resource>
...
</resources>
...
</build>
...
</project>
Filter | 过滤与内容替换
Profile | 构建不同环境的部署包
项目开发好以后,通常要在多个环境部署,象我们公司多达 5 种环境:本机环境(local)、(开发小组内自测的)开发环境(dev)、(提供给测试团队的)测试环境(test)、预发布环境(pre)、正式生产环境(prod),每种环境都有各自的配置参数,比如:数据库连接、远程调用的 ws 地址等等。如果每个环境 build 前手动修改这些参数,显然会非常的麻烦。而 Maven 本身就可以允许我们通过定义 Profile 的方式来在编译是动态注入配置:
<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 节点,参考下面的示例:
<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 目录下:
以上图为例,其中 spring-database.xml 的内容为:
<?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 的环境自动替换这些占位符为实际属性值。
默认情况下: maven package
将采用默认激活的 profile 环境来打包,也可以手动指定环境,比如:maven package -P dev
,将自动打包成 dev 环境的部署包(注:参数 P 为大写)。
动态数据源
本机开发时为了方便,很多开发人员喜欢直接用 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>
灵活 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 里。