保护 Tomcat Web 应用

tomcat 会把 WAR 转换成一个自包含的 Tomcat 基础目录。它使用打包器内置的 Tomcat 组件,完全不会碰你本机安装的 Tomcat。

1. GUI 操作

  1. 在应用类型页面选择 Tomcat WAR

    选择 Tomcat WAR

  2. 选择输入 WAR、随包 Java 版本和目标平台,然后选择简单模式或高级模式。

    选择输入、Java 版本、目标平台和模式

  3. 使用高级模式时,选择 Tomcat 9 或 10.1,或者保持自动检测,并按需设置上下文路径、JVM 启动选项和排除规则;简单模式会根据兼容性扫描确定 Tomcat 版本。各选项的含义见 Protector4J 高级模式设置

    配置 Tomcat 版本、上下文路径和排除规则

  4. 选择输出目录,核对参数摘要,然后点击运行保护

    选择输出目录并执行保护

2. CLI 示例

指定上下文路径:

p4j tomcat app.war dist --context /app

兼容性扫描,以及自动应用扫描建议:

p4j tomcat app.war --compat-scan
p4j tomcat app.war dist --compat-apply --context /app

这两个选项不能同时使用,它们的区别是:

选项作用何时使用
--compat-scan只扫描输入 WAR,打印风险和配置建议后退出;不做编码,也不生成 dist,因此不需要输出目录。首次保护应用、升级 Tomcat 相关依赖、调整保护范围或 JSP 设置之后,以及排查兼容性问题时,先用它查看报告。
--compat-apply扫描后合并保守建议,然后继续编码并写出结果,因此必须指定输出目录。已经看过扫描结果并接受这些建议时,用它完成打包;规则验证过之后的重复构建和 CI 流程也适用。

tomcat 来说,--compat-apply 可以根据扫描结果追加排除规则,并调整 Tomcat 版本、扫描器 ZIP 覆盖层和归档后缀这三类选项。对这三类选项,命令行中显式指定的值优先。建议排除的类默认会与你显式写的 --exclude 合并;如果不希望自动追加,同时传入 --no-compat-excludes 即可。扫描器只做静态启发式分析,需要修改代码才能解决的问题不会被 --compat-apply 自动修复,打包完成后仍然要在目标平台上做回归测试。

其它 CLI 命令、全部选项、环境变量和自动化示例,请参阅 CLI 参数参考

--tomcat-version 默认为 auto。需要明确指定时,设为 910.1

p4j tomcat app.war dist --context /app --tomcat-version 10.1

3. 输出结构

dist/
├── bin/
│   ├── catalina.sh
│   ├── startup.sh
│   ├── shutdown.sh
│   └── *.bat
├── conf/p4jx/
│   ├── contexts.list
│   ├── protected-classes.list
│   └── allowed-prefixes.list
├── protected/
│   └── app.p4jx
├── lib/
│   ├── p4jx-tomcat-runtime.jar
│   └── tomcat-runtime-deps.jar
├── vlxjre/
├── run.sh
└── run.bat

默认不会生成物理 WAR。web.xml、静态资源、未受保护的类、元数据桩和受保护实现,全部位于 protected/<context>.p4jx 中,并通过 P4JX 的 WebResourceSet 呈现给 Tomcat。

4. 启动与停止

前台运行:

./run.sh

按 Tomcat 的方式后台启停:

./bin/startup.sh
./bin/shutdown.sh

Windows 使用对应的 .bat 文件。日志写入输出目录下的 logs/

打包 Windows 目标时,还可以额外生成一个原生启动程序,用于在前台启动内嵌的 Tomcat,详见生成 Windows EXE 启动器

JVM 启动选项

打包时可以在 GUI 的 JVM 启动选项中每行填写一个选项,也可以在命令行中指定:

p4j tomcat app.war dist \
  --context /app \
  --jvm-option -Xms1g \
  --jvm-option -Xmx2g

要在已部署的包中修改:

  • macOS 与 Linux:编辑 bin/catalina.sh,在 run_java() 内的 JVM_OPTS=(...) 之后加上 JVM_OPTS+=("-Xms1g" "-Xmx2g")。前台运行和由 startup.sh 发起的后台运行都会生效。
  • Windows 前台:编辑 bin\catalina.bat,在已有的 set "JVM_OPTS=..." 之后加上 set "JVM_OPTS=%JVM_OPTS% -Xms1g -Xmx2g"
  • Windows 后台:在 bin\startup.bat 调用 catalina.bat 之前,加上 set "APP_JAVA_OPTS=-Xms1g -Xmx2g"。如果需要一套同时覆盖前台和后台的永久选项,直接用 GUI 或 CLI 重新生成会更省事。

也可以在命令前设置 APP_JAVA_OPTS,只对本次运行生效。完整的 CMD、PowerShell 和脚本示例见 JVM 启动选项配置

5. Tomcat 版本的选择

WAR 中使用的 API 命名空间Tomcat所需 Java
javax.servlet.*Tomcat 9Java 8、11、17、21 或 25
jakarta.servlet.*Tomcat 10.1Java 11、17、21 或 25

自动检测会优先从应用类和部署描述符中识别 API 命名空间,JAR 文件名只作为辅助证据。如果 javaxjakarta 同时存在,工具会拒绝自动猜测。

6. JSP

WAR 中包含 JSP 时,默认会在编码阶段把它们预编译成 servlet 类和 URL 映射。这是因为在运行时编译 JSP 会从 Tomcat 工作目录定义新类,而这超出了受保护运行时允许的类定义边界。

也可以显式控制:

--precompile-jsp
--no-precompile-jsp

生产环境请保持默认的预编译。关闭它可能导致含 JSP 的应用打不开页面。

7. 保护范围与排除规则

默认保护 WEB-INF/classes 下的应用类,WEB-INF/lib 不在保护范围内。面向 Web 的类可以排除:

p4j tomcat app.war dist \
  --context /app \
  --exclude 'com.example.web.**,com.example.dto.**'

优先排除 servlet、filter、listener,以及 DTO、配置类、实体、JNI 桥接类和需要由容器增强的类。兼容性扫描会给出保守建议。

8. 在同一个 Tomcat 包中追加应用

p4j tomcat second.war dist \
  --append-app \
  --context /second

约束条件:

  • 上下文路径不能与已有应用冲突;
  • 新旧应用必须使用相同的 Tomcat 主版本、Java 版本和目标平台;
  • 未传 --append-app 时,工具拒绝写入已有的 Tomcat 包;
  • 在 GUI 中勾选将应用追加到现有 Tomcat 文件夹,并直接选择已有目录。

9. Java 8 注意事项

Java 8 目标会自动启用 ZIP 覆盖层,使 Tomcat 的 WebResourceSet 能够打开受保护归档。