从博客园搬家过来,这做为开篇吧。
内容属原创,转载请注明出处
写在前面的话
最近一直比较纠结,归根结底在于工程的模块化拆分。以前也干过这事,但是一直对以前的结果不满意,这会重操旧业,希望搞出个自己满意的结果。
之前有什么不满意的呢?
1. 基于maven拆分模块后,热部署的效果不好,经常出故障。
2. 对于多个子web工程,不能做到任意一个web工程都可以放到tomcat里运行,要在外面搞个壳子组合多个工程。
于是,有了这纠结的一周,也有了此文。
本文关于什么
如标题所言,本文涉及到如下几个内容:
1. maven多模块工程
2. 基于tomcat插件的热部署
且听我一一道来。
maven多模块
这次,采用了如下的结构来构建模块:
1. 工具工程
之间的依赖关系相对较多,采用了子模块的方式处理,所有工具工程都是 com.up.tool 下的模块工程。
<modules> <module>com.up.tool.a</module> <module>com.up.tool.b</module> </modules>
2. 基础工程
基础工程都放在com.up.base目录里,包含系统的基础框架的内容,但是和具体业务无关。
所有第三方的依赖以及对工具工程的依赖,都在基础工程里处理。
考虑到war类型的maven工程的依赖传递搞不定,com.up.base工程的packaging采用了jar,同时通过ant脚本另外再打war的内容以及发布。
ant插件打war且发布的脚本:
<properties> <project.build.finalName>${project.artifactId}-${project.version}</project.build.finalName> <respositories.url>http://192.168.1.254:8080/nexus/content/repositories/</respositories.url> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.7</version> <executions> <execution> <id>打包其他文件</id> <phase>package</phase> <configuration> <target> <mkdir dir="${project.build.directory}/war"/> <copy todir="${project.build.directory}/war" overwrite="true" > <fileset dir="${basedir}/src/main/webapp"> <exclude name="WEB-INF/web.xml"/> </fileset> </copy> <zip destfile="${project.build.directory}/${project.build.finalName}.war"> <fileset dir="${basedir}/target/war"> <exclude name="work/**"></exclude> </fileset> </zip> <delete dir="${project.build.directory}/war"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <id>install到本地</id> <phase>install</phase> <configuration> <target name="install-ext"> <exec executable="cmd.exe" failonerror="true"> <arg value="/c" /> <arg value="mvn" /> <arg value="install:install-file"/> <arg value="-Dfile=${project.build.directory}/${project.build.finalName}.war" /> <arg value="-DgroupId=${project.artifactId}" /> <arg value="-DartifactId=${project.artifactId}.web" /> <arg value="-Dpackaging=war" /> <arg value="-Dversion=${project.version}" /> </exec> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <id>deploy到仓库</id> <phase>deploy</phase> <configuration> <target name="deploy-ext"> <condition property="project.deploy.type" value="snapshots" else="releases"> <contains string="${project.version}" substring="SNAPSHOT" /> </condition> <exec executable="cmd.exe" failonerror="true"> <arg value="/c" /> <arg value="mvn" /> <arg value="deploy:deploy-file"/> <arg value="-Dfile=${basedir}\target\${project.build.finalName}.war" /> <arg value="-DgroupId=${project.artifactId}" /> <arg value="-DartifactId=${project.artifactId}.web" /> <arg value="-Dpackaging=war" /> <arg value="-Dversion=${project.version}" /> <arg value="-Durl=${respositories.url}${project.deploy.type}" /> <arg value="-DrepositoryId=${project.deploy.type}" /> </exec> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
为了避免版本号到处飞以及引入其他不需要的第三方依赖,对所有依赖的第三方包做了如下处理:
<properties> <spring.version>3.1.4.RELEASE</spring.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>3.1.4.RELEASE</version> <exclusions> <exclusion> <artifactId>*</artifactId> <groupId>*</groupId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement>
3. 业务工程
都以com.up.web为父工程,同时,依赖基础工程 com.up.base
<parent> <groupId>com.up</groupId> <artifactId>com.up.web</artifactId> <version>1.0.0.1-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>com.up</groupId> <artifactId>com.up.base</artifactId> <version>1.0.0.1-SNAPSHOT</version> </dependency> </dependencies> <groupId>com.up.web</groupId> <artifactId>com.up.web.a</artifactId> <version>1.0.0.1-SNAPSHOT</version> <packaging>war</packaging>
同时,为了避免业务工程打出来的war包里包含依赖的其他的jar/war的内容,在com.up.web工程里做了如下处理:
<properties> <project.build.finalName>${project.artifactId}-${project.version}</project.build.finalName> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.7</version> <executions> <execution> <id>after-package</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <taskdef resource="net/sf/antcontrib/antcontrib.properties" /> <if> <equals arg1="${project.packaging}" arg2="war" /> <then> <!-- 备份原来的war --> <move file="${project.build.directory}/${project.build.finalName}.war" tofile="${project.build.directory}/${project.build.finalName}-old.war" /> <mkdir dir="${project.build.directory}/war/WEB-INF/classes" /> <copy todir="${project.build.directory}/war/WEB-INF/classes" overwrite="true"> <fileset dir="${project.build.directory}/classes"></fileset> </copy> <copy todir="${project.build.directory}/war" overwrite="true"> <fileset dir="${basedir}/src/main/webapp"></fileset> </copy> <zip destfile="${basedir}/target/${project.build.finalName}.war"> <fileset dir="${basedir}/target/war"> </fileset> </zip> <delete dir="${basedir}/target/war" /> </then> </if> </tasks> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>ant-contrib</groupId> <artifactId>ant-contrib</artifactId> <version>1.0b3</version> <exclusions> <exclusion> <artifactId>ant</artifactId> <groupId>ant</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant-commons-net</artifactId> <version>1.8.1</version> </dependency> </dependencies> </plugin> </plugins> </build>
这样,既保留了可以直接运行的war包,也保证发布到仓库的war包只包含工程自身的内容。
基于tomcat插件的热部署
上面基本上把项目的多模块结构描述了,接下来该是热部署的事情了,怎么才能达到效果呢?
寻求方案的痛苦过程不再多说,在看到这篇博文后,把方案定下来了
参考博文:配合m2eclipse,改造tomcatPluginV321根据maven的依赖自动热部署.
既然已经有大侠基于这个插件做了支持maven的改造,咱也可以这样干。
开发环境:
1. Eclipse Java EE IDE for Web Developers. Version: Luna Release (4.4.0)
2. tomcat插件 org.uqbar.eclipse.tomcat.xt.features_2.0.0
3. maven3.2.1
实现方案:
1. 基于上面“参考博文”的方式,改造tomcat插件支持配置use Maven
2. 调整当设置use Maven的时候,设置webRoot为 target/webapp
3. 启动tomcat前,根据maven依赖的jar以及war,拷贝相应内容到target/webapp并开启监听
具体为:
对于依赖的jar,拷贝jar到target/webapp/WEB-INF/lib
对于依赖的war,解压缩后拷贝到target/webapp
对于依赖的jar或者是war,如果对应工程在工作空间而且是open状态,那么对target/classes,src/main/webapp 目录增加文件变化监听,实时把修改的内容拷贝到target/webapp下对应目录(文件变化监听基于JNotify实现)
4. 启动tomcat,docBase为target/webapp
5. 终止tomcat时,停止文件监听(需要通过插件的终止功能,否则文件监听未停止,可能导致maven clean 失败)
6. 增加切换工程的功能,点击时切换tomcat里的context为当前选中的工程(只支持一个工程)
实现效果
做了上面调整后,达到了如下效果:
1. 设置了工程为tomcat工程而且选中use Maven后,插件会在启动前拷贝所有通过maven依赖的内容到target/webap
2. 在工作空间打开而且被当前tomcat运行的工程依赖的工程,修改的内容会实时同步到target/webapp(注意设置tomcat插件里的reloadable为false,即不选中该选项)。
由于tomcat运行的docBase为target/webapp,当所有修改的内容可以实时拷贝到target/webapp时,也就实现了热部署的效果。
问题是什么
目前的方案有如下问题:
1. 启动的时候的拷贝,会导致启动tomcat延迟3到4秒。
2. 如果没通过插件关闭tomcat而是直接通过控制台关闭,会导致文件监听未停止,可能造成maven clean失败。
3. 要求所有工程的output dir都是 target/classes,要求web的root都是 src/main/webapp 也就是maven的标准配置,否则会有问题。
4. 插件只支持eclipse4.4,连eclipse4.3都不支持,未追究原因。
插件及插件源码下载
org.uqbar.eclipse.tomcat.xt_2.0.0原始插件参见其官方网站
相关推荐
这个过程涉及到了源码管理和自动化构建工具Maven,以及集成开发环境Eclipse中的服务器适配器Tomcat,它们共同助力实现项目的热部署,即代码修改后无需重启服务器即可看到更新效果。 首先,Maven是一个强大的项目...
在进行Maven工程的Tomcat热部署详解时,首先需要掌握Java后台开发中对于Tomcat热部署的基本知识。这涉及到Java环境的搭建,Tomcat的安装,以及Maven工程中对于热部署的配置方法。 Java环境的搭建是热部署的前提。在...
标题中的“配合m2eclipse,改造tomcatPluginV321根据maven的依赖自动热部署”涉及了两个主要的开发工具集成:M2Eclipse(Maven插件)和Tomcat Plugin V321,以及它们如何协同工作以实现基于Maven依赖的自动热部署。...
描述中提到的“外包tomcat的maven实时调试工具”,可能是作者对tomcat-maven插件进行了源码修改,以实现更高效的实时调试和热部署功能。这可能包括了对插件的配置调整、添加特定的监听器或者利用特定的调试协议(如...
为了实现热部署,我们需要配置Maven的Tomcat插件,例如`maven-war-plugin`和`tomcat7-maven-plugin`: ```xml <finalName>SimpleWebProject <groupId>org.apache.maven.plugins <artifactId>maven-war-...
尽管Tomcat相对轻量级且易于配置,但部署应用、热更新、多模块项目管理等方面也可能存在问题。例如,作者可能遇到了在Tomcat上部署应用后启动失败,或者在更新代码后无法自动刷新应用的问题。 文章中可能还讨论了...
- **Options**:设置热部署等功能。 #### 五、总结 通过上述步骤,我们不仅创建了一个Maven Web项目,还学习了如何利用IntelliJ IDEA进行项目配置、打包和部署。这对于开发基于Java的Web应用程序来说是非常重要的...
- **部署和热部署机制**:学习如何动态部署和更新Web应用。 总的来说,这个“Tomcat源码阅读环境”是深入学习和研究Java Web服务器架构的一个宝贵资源,无论你是希望提升自己的技术能力,还是想为Tomcat社区贡献...
Tomcat支持热部署,即在不重启服务器的情况下更新应用。 8. **国际化和本地化** Tomcat允许通过资源包(`.properties`文件)来支持多语言环境,便于构建国际化Web应用。 9. **Maven集成** Tomcat 7.0.29源码可以...
Tomcat支持热部署,这意味着开发者可以修改源代码后,无需重启服务器就能看到更改的效果。要进行源码集成,你需要配置IDE(如Eclipse或IntelliJ IDEA)与Tomcat的连接,设置正确的服务器路径,然后将项目部署到...
Spring Boot基于约定优于配置的原则,大量内置了常见的设置,如嵌入式Tomcat服务器、默认的Maven或Gradle插件、日志系统等,使得开发者可以快速地创建一个独立运行的Spring应用程序。 SpringLoaded是Spring源码中的...
- 在Jenkins中新建或编辑已有任务,添加源码管理插件,配置GitLab仓库地址以及凭据等信息。 - 配置完成后,Jenkins就能自动拉取代码并进行后续操作。 2. **构建触发器**: - 可以根据需求选择不同的构建触发方式...
- **项目类型:** 选择 Maven 项目, 因为本教程主要介绍如何在 IDEA 中管理多模块 Maven 项目。 - **项目模板:** 根据实际需求选择合适的项目模板, 如果没有特殊需求可以选择默认模板。 **1.3 工程命名与位置设定** ...
这样做的目的是允许 Jenkins 通过这个用户远程发布 WAR 包并进行热部署。 #### 五、构建与测试 完成所有配置后,即可通过 Jenkins 界面触发构建任务。构建完成后,检查 Tomcat 服务器上的应用是否已成功部署。这一...
4. **启用热部署插件**:在IDE中,如IntelliJ IDEA或Eclipse,可以安装相应的热部署插件,如Spring Boot DevTools。在`pom.xml`中添加如下依赖: ```xml <groupId>org.springframework.boot <artifactId>spring...
6. **热部署**:由于Jetty的热部署特性,当你修改了源代码后,无需重新启动服务器,只需保存更改,Jetty会自动检测并更新应用。 在实际开发过程中,你可能还需要了解如何处理依赖冲突、如何自定义Jetty配置,以及...
在Eclipse中开发b3log-solo项目时,由于其特殊的Maven目录结构,标准的Web目录结构无法直接呈现,这给热部署带来了挑战,通常需要频繁重启服务器。尽管热部署不重启服务器的开发方式可能不符合完整的单元测试流程,...
首先,SpringBoot框架是Java开发中的常用轻量级框架,它简化了传统Spring应用的初始搭建以及配置过程,内置了Tomcat服务器,支持热部署,使得开发和测试更加高效。Jpa(Java Persistence API)是Java平台上的对象...
- 开发者工具模块提供了一些方便开发的功能,如热部署、LiveReload、源码查看等。 - 当 `spring-boot-devtools` 依赖在类路径中时,SpringBoot 会开启这些特性,提高开发效率。 5. **嵌入式服务器**: - ...
Tomcat支持多种扩展,如管理工具、热部署插件等。例如,`manager`和`host-manager`应用允许管理员远程部署、更新和管理应用程序。 **5. 安全性** 源代码可以帮助开发者理解和增强Tomcat的安全性,如配置SSL/TLS以...