1、背景
随着组织过程资产不断的积累,公共代码的提取是有效降低开发成本的成熟手段之一,出于版本控制、源码隔离等多方面的因素,需要设计一套合适的公共代码的复用机制,以便于项目组基于公共代码快速进行二次开发。对于打包成jar格式的工具类来说,复用很容易,但是对于包含前端代码的公共组件(打包成war文件),二次开发就比较困难,至少不像jar那样随意了,本文主要针对多个war文件整合进行介绍。
2、思路
最原始的方式:将jar集成,将前端的html、js、css等文件连同文件夹拷贝到新项目中;
在限定使用Tomcat作为Web容器时:多个war同时部署,共享session,以达到同容器的war相关资源互相引用,但是要求每个war都得有详细的资源说明文档,否则不同的war文件的开发人员互相之间缺乏沟通会有致命影响。(多个war文件同时部署,操作起来较为复杂,系统连调工作量大)
升级web容器为JBoss等支持EAR部署的应用服务器:创建EAR项目,配置打包时需要包含的module(EJB组件、War、Jar等),导出EAR包并部署(可以手动操作,也可以使用maven进行自动构建、发布。部署一个EAR文件,解压后可以看到多个WAR文件)。
单War部署:利用maven的特性,将多个依赖war依次合并,最终发布为一个war,并自动部署(因存在同名文件覆盖的问题,因此需要约束每个war的namespace或目录)。
本文主要介绍最后一种,但War文件部署相关的内容。
3、过程简述
基于maven管理依赖,利用其maven-war-plugin插件中overlays配置war覆盖顺序,以达到多个war合并的目的,最后利用distributionManagement,配置需要发布的服务器,开发调试时,需在项目名上右键>>run as >> 选择“Maven build...” ,在弹出的对话框中的goals中填写clean deploy,即可执行maven clean操作,并依据build周期中的各个环节,依次构建,最终自动部署到配置的服务器上。
4、各环节详细说明
A、准备:
安装jdk、maven、tomcat,并配置相关环境变量;
在maven生效的settings.xml文件中的servers段添加一段服务器配置的内容(即本地发布用的tomcat配置信息),如下:
<server>
<id>local_server</id>
<username>root</username>
<password>root</password>
</server>
(Tomcat 7中需要)在tomcat的配置文件tomcat-users.xml中增加manager-script的角色。
<role rolename="manager"/>
<role rolename="manager-script"/>
<user password="root" roles="manager,manager-script" username="root"/>
创建maven -webapp项目:
common,其打包类型war
<groupId>com.gs</groupId>
<artifactId>common</artifactId>
<version>1.0</version>
projectA,其打包类型war
<groupId>com.gs</groupId>
<artifactId>projectA</artifactId>
<version>1.0</version>
B、在eclipse中将common项目运行maven install,且成功将common.war发布到本地repo库中(是否发布到私服,视情况而定)。
C、在projectA的pom文件中添加common的依赖
<dependencies>
<dependency>
<groupId>com.gs</groupId>
<artifactId>common</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
</dependencies>
D、在projectA的pom文件中添加plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<overlays>
<overlay>
<groupId>com.gs</groupId>
<artifactId>common</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
E、在projectA的pom文件中添加tomcat部署插件,如下:注意,配置中的server名称为上文settings.xml中加入的server的名称。
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<url>http://localhost:8080/manager/text</url>
<server>local_server</server>
</configuration>
</plugin>
F、将项目自动发布到私服Repo*
在指定项目的pom文件的project标签下添加distributionManagement,如下:
<distributionManagement>
<repository>
<id>nexus</id>
<url>http://localhost:8080/nexus/content/repositories/thirdparty/</url>
</repository>
</distributionManagement>
如此即可在私服repositories/thirdparty/路径下根据该项目的GAV生成相应的文件夹,并自动将项目build的结果发布上去。同样,需要在上文提及的settings.xml文件中添加对应的server信息:
<server>
<id>nexus</id>
<username>admin</username>
<password>admin</password>
</server>
5、总结
按照以上步骤,项目组可以方便的基于公共代码打包的War进行二次开发,但是需要注意一下几点:
A、若以deploy作为goals时,请将部署的tomcat提前启动,以免maven无法推送;
B、以上配置基于Maven3、tomcat7,低版本的配置略有差异,请自行查找;
C、本地开发调试也需使用maven构建的方式将war部署到本地server,若直接使用eclipse插件将projectA部署到server时,会发现发布的文件夹内未合并common中内容;
D、再次强调使用overlay配置会对指定的war中的文件进行同名覆盖,因此需要合理规划多个war包中目录结构,以及java源码的目录结构。
2015.5.12 追加更新
经过几天的摸索~又深入的了解了一番~现阶段提出2种较快捷的方式来进行开发调试~
1、因开发是基于war进行二次开发,因此此次提出的2种方式均是基于war展开的;
2、因使用embed tomcat来启动部署项目的配置未调试通过,因此这次提出的2个方案均是基于独立的tomcat实例进行启动部署的。
PS:这里给出embed tomcat调试的思路,及未继续展开研究的原因:
1、直接按照嵌入式tomcat的配置方案,项目可以启动,依赖jar后台也可以正常运行,但默认只将src/main/webapp作为webroot,因此,依赖的war中的相关资源无法使用。
2、contextFile这个配置可以配置一个指定目录作为webpath,网上很多例子是用contextFile配置数据源的,这里,我们应该是将target下自动生成的合并后的项目目录配置到docBase属性。但是不知道能否配置到WebROOT下,暂时还未尝试成功。
3、一直没太明白systemProperties下appserver.base和appserver.home的区别和用途~~但是将target/RealWarWebRoot作为其参数,也未成功,前端访问时一直重复出现http 302 重定向的问题,同时被依赖的war中的资源也无法正常使用。
4、尝试在plugin中配置executions.execution属性,将goals设定为exec-war-only,可以打出一个runnerable webapp,输出一个jar,里面包含合并后的war包,但是 这个jar未运行成功。
略过上述失败的尝试,回到正题:“基于tomcat实例快速调试多war合并工程”
一、基于更新前内容的简化版本
maven的settings.xml中的部分配置和pom中的一致,因此我们可以将部分配置内容移到pom中,以减少工程对环境的依赖。
该方法中只要配置2个文件:tomcat-user.xml和pom.xml
<rolerolename="manager"/>
<userusername="admin" password="admin"roles="manager"/>
pom文件中:
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<!-- or if you want to use tomcat 6.x
<artifactId>tomcat6-maven-plugin</artifactId>
-->
<version>2.2</version>
<configuration>
<url>http://localhost:8019/manager/text</url>
<server>tomcat</server>
<username>root</username>
<password>root</password>
</configuration>
</plugin>
二、通过配置eclipse 中的参数,改变实际发布的路径
公共项目叫common.war,二次开发项目名称是projectA
假设在projectA的pom中设定了 build.finalName 是 projectA
按照更新前内容配置完pom依赖后,对项目执行maven build... 将goals设定为 package,
以上是背景~~
项目右键 properties中再Deployment Assembly中 将/src/main/webapp 这一项移除,
因为我们的目标是将合并(基于overlays配置合并)后的文件夹“target/projectA”发布到“/”下,
因此添加一个文件夹/target/projectA,确定(如下图)。
此时,可以按照以往web项目调试一样,在eclipse配置的外部server中添加项目(如下),并启动tomcat进行调试。