如何使用Bazel为多模块Java项目构建WAR文件?
在Bazel中构建Java WAR文件(多子项目场景)
一、使用rules_java_war规则(快速上手)
你提到的rules_java_war仓库虽然三年未更新,但WAR打包逻辑本身比较稳定,只要你的Bazel版本与仓库兼容(比如Bazel 5.x及以下版本基本无问题;若用最新Bazel 6+/7+,可能需要微调规则代码),仍可正常使用。
步骤1:在WORKSPACE中引入仓库
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") git_repository( name = "rules_java_war", remote = "https://github.com/bmuschko/rules_java_war.git", tag = "v0.1.0", # 选择仓库最新的标签版本 ) load("@rules_java_war//:defs.bzl", "java_war_repositories") java_war_repositories()
步骤2:在Web子项目的BUILD文件中定义WAR规则
假设你的Web子项目目录结构是标准的Maven/Gradle布局,在BUILD文件中添加:
load("@rules_java_war//:defs.bzl", "java_war") java_war( name = "my-web-app", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**/*"]), webapp = glob(["src/main/webapp/**/*"]), # 对应静态资源、JSP、web.xml等文件 deps = [ "//core-subproject:core-library", # 依赖你的其他子项目 "@maven//:javax_servlet_javax_servlet_api", # 示例:引入Servlet API依赖 ], )
步骤3:执行构建
运行以下命令生成WAR文件:
bazel build //path/to/web-subproject:my-web-app
生成的WAR文件位于bazel-bin/path/to/web-subproject/my-web-app.war。
二、手动构建WAR(无第三方依赖,更可控)
如果不想依赖旧仓库,可以利用Bazel的genrule或zip规则手动实现WAR打包(本质是符合Java Web规范的ZIP包),适合多子项目的复杂依赖场景。
方法1:用genrule实现完整打包
- 先确保Web子项目的代码编译为Java库:
java_library( name = "web-core", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**/*"]), deps = [ "//core-subproject:core-library", "@maven//:javax_servlet_javax_servlet_api", ], )
- 添加genrule打包WAR:
genrule( name = "my-web-war", srcs = [ ":web-core", "src/main/webapp", ], outs = ["my-web-app.war"], cmd = """ # 创建临时目录,构建WAR目录结构 TMP_DIR=$$(mktemp -d) mkdir -p $$TMP_DIR/WEB-INF/lib $$TMP_DIR/WEB-INF/classes # 复制Web静态资源到WAR根目录 cp -r $(location src/main/webapp)/* $$TMP_DIR/ # 解压编译后的class文件到WEB-INF/classes unzip -q $(location :web-core) -d $$TMP_DIR/WEB-INF/classes # 复制依赖JAR到WEB-INF/lib(若不需要打包依赖可跳过此段) for JAR in $(deps :web-core); do cp $$JAR $$TMP_DIR/WEB-INF/lib/ done # 打包为WAR文件 zip -r $(OUTS) $$TMP_DIR/* rm -rf $$TMP_DIR """, )
方法2:用zip规则配合文件组(更简洁)
# 定义Web静态资源文件组 filegroup( name = "webapp_files", srcs = glob(["src/main/webapp/**/*"]), ) # 编译Web核心代码 java_library( name = "web-core", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**/*"]), deps = [ "//core-subproject:core-library", "@maven//:javax_servlet_javax_servlet_api", ], ) # 提取class文件和资源到目录 genrule( name = "web_classes", srcs = [":web-core"], outs = ["web_classes_dir"], cmd = "unzip -q $(location :web-core) -d $(OUTS)", ) # 打包为WAR zip( name = "my-web-war", srcs = [":webapp_files", ":web_classes"], package_dirs = { "webapp_files": "", # 静态资源放到WAR根目录 "web_classes": "WEB-INF/classes", # class文件放到WEB-INF/classes # 若需添加依赖JAR,可新增filegroup并设置路径为"WEB-INF/lib" }, out = "my-web-app.war", )
关键注意事项
- 多子项目依赖:确保每个子项目的
java_library正确声明依赖,WAR规则直接依赖需要打包的子项目即可。 - 依赖打包:若WAR需要包含运行时依赖JAR,手动打包时需确保收集所有必要的依赖;使用rules_java_war时,规则会自动处理依赖JAR的打包。
- 兼容性:若使用rules_java_war遇到新版本Bazel兼容问题,可自行修改仓库中的
java_war.bzl规则,WAR打包逻辑(目录结构、ZIP打包)本身非常简单,调整成本低。
内容的提问来源于stack exchange,提问作者John Adams
相关产品推荐
相关产品推荐

