如何在Tomcat 8中部署多个Grails 3.x应用并共享公共JAR包?
刚好之前帮团队处理过类似的场景,给你整理一套Grails 3.x + Tomcat 8+的可行方案,亲测稳定:
一、调整Grails项目构建配置,剥离公共依赖
Grails 3.x基于Gradle构建,我们需要把多个应用共享的JAR依赖从项目打包范围中移除,让Tomcat的共享类加载器来加载它们:
- 打开项目的
build.gradle文件,将所有需要共享的公共依赖(比如数据库驱动、Spring核心包、通用工具类等)的作用域从implementation/compile改为provided,示例:// 原来的依赖声明 // implementation 'org.springframework:spring-core:5.3.20' // 修改为provided provided 'org.springframework:spring-core:5.3.20' provided 'mysql:mysql-connector-java:8.0.33' provided 'commons-lang:commons-lang:2.6' - 注意:Grails自身的核心依赖(比如
grails-core)建议保留在项目中,避免不同应用的Grails版本冲突;只抽离那些所有应用都用相同版本的第三方依赖。
二、配置Tomcat启用共享类加载器
Tomcat 8+默认没有开启shared/lib的类加载支持,需要手动配置:
- 打开Tomcat安装目录下的
conf/catalina.properties文件,找到shared.loader配置项,取消注释并修改为:shared.loader=${catalina.base}/shared/lib/*.jar,${catalina.base}/shared/lib - 如果Tomcat目录下没有
shared/lib文件夹,手动创建一个,然后把所有共享的JAR包复制到这个目录里。 - 关键提醒:共享JAR的版本必须和所有Grails项目中
provided声明的版本完全一致,否则会出现类版本冲突或找不到类的错误。
三、为每个Grails应用配置独立数据源
每个Grails应用的数据源配置完全独立,不会互相干扰,直接在各自项目中配置即可:
- 打开项目的
grails-app/conf/application.yml(或application.groovy),配置专属数据源,示例:dataSource: pooled: true jmxExport: true driverClassName: com.mysql.cj.jdbc.Driver username: app1_db_user password: app1_db_pass dbCreate: update url: jdbc:mysql://localhost:3306/app1_db?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC - 如果需要多数据源,可以通过
dataSources节点配置,具体参考Grails 3的多数据源官方配置规则即可。
四、打包部署Grails应用
- 每个Grails项目执行
./gradlew war命令生成WAR包,此时WAR包中不会包含那些标记为provided的公共依赖,体积会小很多。 - 将生成的WAR包复制到Tomcat的
webapps目录下,启动Tomcat即可。 - 启动后可以查看Tomcat的
logs/catalina.out日志,确认数据源连接正常,没有类找不到或版本冲突的报错。
五、避坑注意事项
- 版本一致性优先:所有共享JAR的版本必须和项目中
provided依赖的版本严格匹配,否则会出现ClassCastException或NoClassDefFoundError。 - 依赖树排查:可以用
./gradlew dependencies命令查看项目的依赖树,确认哪些依赖是公共的,避免漏抽离或误抽离。 - 类加载优先级:Tomcat的共享类加载器优先级低于Web应用自身的类加载器,如果某个应用需要特殊版本的依赖,可以在项目中保留
implementation作用域,覆盖共享的JAR。 - 数据源隔离:每个应用的数据源连接池是独立维护的,Tomcat不会共享连接池资源,不用担心数据串库问题。
内容的提问来源于stack exchange,提问作者Anshul
相关产品推荐
相关产品推荐

