Maven插件实现热部署,支持Tomcat和Jetty插件

时间:2022-11-22 00:49:56
Maven是一个非常优秀的工具,在Maven出现之前,一个项目如果业务很多,很复杂,整个项目就非常庞大。这会造成如下几个问题: 1、项目后期维护成本大,新加一个需求需要全盘考虑会不会影响其他的业务逻辑;
2、开发效率低下,改动一个Java文件需要重启Tomcat (Jetty等)服务器 ,重新编译整个项目,编译会花去一定的时间,程序员开发的时间会大大减少;
3、所有的业务代码和非业务代码紧密耦合在一起,无法拆分;
4、jar文件冲突,不同的业务代码依赖jar的版本无法做到统一。

Maven出现后,很好的解决了上述问题。使用Maven后,一个大的项目被拆分成小的模块,这样程序员可以专注于某个模块,开发效率大大提高。同时程序员改了某个模块后,只需编译这个模块,这样减少了编译时间。Maven也很好的管理jar,所有的jar可以通过自己构建私服统一管理,冲突问题得以解决。
写到这里也许你会问,Maven似乎已经实现分模块编译和打包的功能,实现了热部署,还要在Maven上做什么文章?确实,Maven解决了“热部署”。一般情况下不需要再做什么文章了,分模块已经大大的提高了开发效率。如果一个项目拆分成几个模块后,模块不能继续再分了(模块分的越多也不是很好,不便于管理),但是模块还是很大,这时候有点问题了!!
于是就有人提出,JVM每次编译Java文件只编译.class文件改动的文件,这样会提高JVM编译效率。JRebel插件是其中一种,可以监控哪些Java文件被修改过,原理就不叙述了,可以百度相关文章阅读。

本文只讨论Maven插件(Tomcat + JRebel)实现Web项目热部署(增量部署)功能。其他插件如Jetty也可以实现热部署,Maven的配置类似,本人也成功使用Jetty插件实现热部署,鉴于篇幅原因,这里就不在赘述。开发中选择Tomcat还是Jetty依项目而定,不过一般推荐使用Jetty插件,Jetty比Tomcat 更轻量级,大多数情况下Jetty完全可以满足需求。需要注意的是,JBoss插件的支持不是很好,目前本人未能成功用JBoss插件实现分模块打包,如果你实现了用JBoss插件分模块打包,并可以正常的运行项目,欢迎分享给大家。

好了,开始进入正题,Tomcat + JRebel 插件实现热部署。

1、配置编译插件:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>

2、配置打源码插件(可选项):

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

3、配置Tomcat 插件,关闭Tomcat 本身的热部署功能:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8888</port>
<path>/uums-web</path>
<uriEncoding>UTF-8</uriEncoding>
<!-- 监控web.xml文件 -->
<contextFile>${basedir}/src/main/webapp/WEB-INF/web.xml</contextFile>
<useTestClasspath>false</useTestClasspath>

<webAppConfig>
<contextPath>/${project.artifactId}</contextPath>
<extraClasspath>
../uums-common/target/classes;
</extraClasspath>
</webAppConfig>

<scanTargets>
<scanTarget>../uums-common/target/classes</scanTarget>
</scanTargets>

<scanTargetPatterns>
<scanTargetPattern>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</scanTargetPattern>
<scanTargetPattern>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
<excludes>
<exclude>**/*.xml</exclude>
</excludes>
</scanTargetPattern>
</scanTargetPatterns>
<!-- 关闭tomcat自身的热部署 -->
<scanIntervalSeconds>0</scanIntervalSeconds>
<webAppSourceDirectory>${basedir}/src/main/webapp</webAppSourceDirectory>
</configuration>
</plugin>
  
4、JRebel插件Maven配置:
<plugin>  
<groupId>org.zeroturnaround</groupId>
<artifactId>jrebel-maven-plugin</artifactId>
<version>1.1.5</version>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<rebelXmlDirectory>${basedir}/src/main/webapp/WEB-INF/classes</rebelXmlDirectory>
</configuration>
</plugin>

5、指定编译后文件的存放路径。因 为Tomcat 默认src/main/webapp为 web应用的根目录,而maven compile目标后的默认classpath在target文件夹下,就造成jrebel.xml无法兼顾Tomcat 默认的是webapp中的 classes为web应用的根目录,而Maven默认是target目录,所以需要修改该Maven的默认classes目录。
<outputDirectory>${basedir}/src/main/webapp/WEB-INF/classes</outputDirectory>

6、在Eclipse 里下载JRebel插件: 点击Help->Eclipse Marketplace,下载JRebel for Eclipse插件。 Maven插件实现热部署,支持Tomcat和Jetty插件


7、配置jrebel.jar的路径
点击Windows->Prefrences->JRebel->Advanced,在JRebel agent里指定下载好的jrebel.jar的路径。
Maven插件实现热部署,支持Tomcat和Jetty插件

8、配置VM参数:
Maven插件实现热部署,支持Tomcat和Jetty插件


使用maven命令:tomcat7:run,启动Tomcat ,出现如下信息,则说明JRebel配置成功。
Maven插件实现热部署,支持Tomcat和Jetty插件


在uums-web的/WEB-INF/classes目录下生成了一个rebel.xml文件,该文件会监控如下两个目录:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.zeroturnaround.com"
xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">

<classpath>
<dir name="F:/workspace/uums/uums-web/src/main/webapp/WEB-INF/classes"></dir>
</classpath>

<web>
<link target="/">
<dir name="F:/workspace/uums/uums-web/src/main/webapp"></dir>
</link>
</web>

</application>



启动Tomcat ,在浏览器地址栏输入http://localhost:8888/uums-web/,显 示默认页面,这时修改LoginAction.java和LoginDaoImpl.java文件,发现只加载LoginAction.java和 LoginDaoImpl.java文件,不需要重启Tomcat 重新编译整个模块。实现了只编译修改的.class文件,大功告成!
Maven插件实现热部署,支持Tomcat和Jetty插件

上 面似乎没有任何问题,但是,问题还是出现了,比如修改了uums-common模块(uums-common是uums-web依赖的模块)里的Java 文件,发现并没有reload修改的那个文件。上述配置只实现了reload uums-web模块修改的Java文件,其依赖的模块被修改并不能被reload,需要重新编译uums-common模块。这个问题一直困扰了我很 久,经过查阅资料和不断地测试,终于实现了不用重新编译uums-common模块也可以实现reload修改的Java文件,只需在uums-web模 块的pom.xml文件添加如下的配置即可。注意,如果uums-web依赖多个模块,则需要在每个依赖的模块的后面加上“;”。
<webAppConfig>
<contextPath>/${project.artifactId}</contextPath>
<extraClasspath>
../uums-common/target/classes;
</extraClasspath>
</webAppConfig>

<scanTargets>
<scanTarget>../uums-common/target/classes</scanTarget>
</scanTargets>


重启Tomcat,这次修改uums-common模块的Java文件,发现可以被reload,至此热部署得以实现。
由于本人能力有限,问题在所难免,恳请各位批评指正!

==================================全文完==================================