前端模块化后,一个模块可以在多个页面或者一个页面的多处被复用,提升了我们的开发效率,避免重复造轮子。而后,我们对复用性有了更高的要求,能不能让一个模块在多个工程(网站)间复用呢?我们的几个网站大多情况下使用的是同一套UI,我们希望尽量避免把相同的代码从这个网站拷贝到另一个网站,而是使其成为更加公共的模块,能够在不同的网站间复用。

maven的overlay模式能够将一个外部的war包部署到当前war包中,包括静态文件和class,最后的效果就是将两个war包合并起来了。例如我们的主模块使用了一个公共模块fe_common,按照如下方式配置overlay模式:

  1. 在主模块的pom文件里加上依赖项 将依赖的模块加入dependency节点,并指明type值为war
<dependency>
   <groupId>com.company</groupId>
   <artifactId>fe_common</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <type>war</type>
 </dependency>

2. 添加一个plugin——maven-war-plugin,并在overlay中设置依赖的模块,以及包含的文件

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-war-plugin</artifactId>
   <version>2.1.1</version>
   <configuration>
     <dependentWarIncludes>WEB-INF/**/*,static/**/*</dependentWarIncludes>
     <overlays>
       <overlay>
         <groupId>com.company</groupId>
         <artifactId>fe_common</artifactId>
       </overlay>
     </overlays>
   </configuration>
 </plugin>

经过这两步就设置好了,在编译的时候,主模块会自动下载fe_common模块的war包,在打包阶段将两个war包合并一块儿打包。

注意和说明

1. 由于overlay模式是将依赖包的文件合并到当前包中,所以要避免文件冲突,最好把依赖包的文件放在一个特定的目录中,如主模块的目录结构是/static/css , /static/js , /WEB-INF/views ,而fe_common的目录结构是/static/css/fe_common ,  /static/js/fe_common , /WEB-INF/views/fe_common。由于在本地开发的时候,IDE或者maven会在源代码处添加一些临时目录,而且不会删掉,所以应在.gitignore文件中添加上排除的目录

overlays
src/main/webapp/**/fe_common

2. overlay形式的依赖能够正确的编译打包和部署,如上所述,最后两个模块会合并到一个包里。如果是在本地调试阶段,不少IDE能够正确识别overlay的模块并引入依赖。但如果是用普通编辑器+命令行编译,则更改了fe_common后应该mvn install一下,这样对主模块执行mvn compile时才能正确取到包

3. 以nested方式运行jetty(mvn jetty:run)也可以识别出overlay模块,不过需要比较新的jetty plugin(最好升级到最新),但这种方式仍然不支持include ftl文件,猜测这和freemarker编译器的处理行为有关。解决方法是在maven的test-compile阶段把依赖的模块的ftl文件拷到本地,以使其正常运行。当然,这些拷过来的文件也不会被删掉,只要按照第1点所说的,在.gitignore文件中添加排除项就不会被加入到版本库中。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.10</version>
  <executions>
    <execution>
      <id>unpack</id>
      <phase>test-compile</phase>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>com.company</groupId>
            <artifactId>fe_common</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <type>war</type>
            <overWrite>true</overWrite>
            <outputDirectory>${basedir}/src/main/webapp</outputDirectory>
            <includes>WEB-INF/views/**/*</includes>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>
  </executions>
</plugin>

参考资料

http://maven.apache.org/plugins/maven-war-plugin/overlays.html http://eclipse.org/jetty/documentation/current/jetty-maven-plugin.html#using-overlaid-wars