Tomcat8RunnerCli:可执行WAR的命令行门面

这段代码是 Tomcat8RunnerCli ------ 它是 Tomcat8Runner命令行接口(CLI)入口类,用于解析用户传入的参数,并启动内嵌 Tomcat。

你可以把它理解为:"可执行 WAR 文件的 main() 方法所在类" ,负责把命令行参数(如 -httpPort 9090)转换成 Java 对象配置,然后交给 Tomcat8Runner 去真正启动服务器。


🎯 一、核心作用

提供友好的命令行参数支持,让用户通过 java -jar app.war [options] 灵活控制内嵌 Tomcat 的行为。

例如:

bash 复制代码
java -jar myapp.war -httpPort 8081 -debug -Dmy.prop=value

🔧 二、关键组成部分解析

1. 使用 Apache Commons CLI 定义命令行选项

所有 Option 都通过 OptionBuilder 声明,比如:

java 复制代码
static Option httpPort = OptionBuilder
    .withArgName("httpPort")
    .hasArg()                  // 需要参数值
    .withDescription("http port to use")
    .create("httpPort");       // 长选项名

支持的选项包括:

选项 说明
-httpPort N HTTP 端口(默认由配置文件决定)
-httpsPort N HTTPS 端口
-ajpPort N AJP 端口
-serverXmlPath file 使用自定义 server.xml
-resetExtract 强制重新解压 WAR 内容
-Dkey=value 设置系统属性(类似 JVM 的 -D
-obfuscate password 直接混淆密码并退出 (调用 PasswordUtil.obfuscate()
-debug-X 启用调试日志
-help-h 打印帮助信息

✅ 这些选项覆盖了 Tomcat 启动所需的核心配置。


2. 优先级机制:命令行 > 配置文件

程序会先加载一个内置配置文件:

java 复制代码
// 从 JAR 内部读取 /tomcat.standalone.properties
Properties props = buildStandaloneProperties();

命令行参数优先级更高

java 复制代码
// 先读配置文件中的端口
port = props.getProperty(Tomcat8Runner.HTTP_PORT_KEY);
if (port != null) tomcat8Runner.httpPort = Integer.parseInt(port);

// 如果命令行指定了,则覆盖
if (line.hasOption(httpPort)) {
    tomcat8Runner.httpPort = Integer.parseInt(line.getOptionValue(httpPort));
}

💡 这是典型的"默认值 + 覆盖"设计模式。


3. 特殊功能:密码混淆工具

java 复制代码
if (line.hasOption(obfuscate)) {
    System.out.println(PasswordUtil.obfuscate(line.getOptionValue(obfuscate)));
    System.exit(0);
}

这意味着你可以这样使用:

bash 复制代码
java -jar myapp.war -obfuscate mypassword
# 输出:OBF:1v2j1uum1xtv1uvk1v0h1v2j

✅ 把可执行 WAR 当作一个 密码混淆工具 来用,非常方便!


4. 系统属性注入(-Dkey=value

java 复制代码
if (line.hasOption(sysProps)) {
    Properties sysProps = line.getOptionProperties('D');
    for (entry : sysProps) {
        System.setProperty(key, value); // 注入到 JVM 系统属性
    }
}

这让你可以:

bash 复制代码
java -jar app.war -Djavax.net.ssl.keyStore=keystore.jks -Dwars=app.war

→ 这些属性会被 Tomcat8Runner 读取(比如用于 HTTPS 或 WAR 列表)。


5. 帮助信息(HelpFormatter)

当参数错误或使用 -h 时,自动打印用法:

text 复制代码
usage: java -jar [path to your exec war jar]
 -ajpPort <ajpPort>               ajp port to use
 -clientAuth                      enable client authentication for https
 -debug                           debug
 -extractDirectory <extract...>   path to extract war content...
 -help                            help
 -httpPort <httpPort>             http port to use
 -httpsPort <httpsPort>           https port to use
 -obfuscate <password>            obfuscate the password and exit
 ...

🔄 三、整体工作流程(main() 方法)

  1. 解析命令行参数

    • 使用 GnuParser(支持 GNU 风格,如 -Dkey=value
    • 失败则打印帮助并退出
  2. 处理特殊命令

    • -help → 打印帮助
    • -obfuscate xxx → 混淆密码并退出
  3. 加载默认配置

    • 从 JAR 内部的 tomcat.standalone.properties 读取默认值
  4. 应用命令行覆盖

    • 将 CLI 参数赋值给 Tomcat8Runner 实例
  5. 启动 Tomcat

    java 复制代码
    tomcat8Runner.run(); // 进入真正的启动逻辑

📦 四、与 Tomcat8Runner 的关系

职责
Tomcat8RunnerCli 命令行解析 + 配置组装(面向用户)
Tomcat8Runner 实际启动 Tomcat + 部署应用(面向运行)

✅ 分离关注点:CLI 只负责"怎么启动",Runner 负责"启动什么"。

在构建可执行 WAR 时,Maven 插件会设置:

xml 复制代码
<Main-Class>Tomcat8RunnerCli</Main-Class>

所以 java -jar app.war 实际执行的是 Tomcat8RunnerCli.main()


✅ 五、典型使用场景

场景 1:快速启动 Web 应用

bash 复制代码
java -jar myapp-exec.war -httpPort 9090

场景 2:生成混淆密码

bash 复制代码
java -jar myapp-exec.war -obfuscate admin123
# 得到 OBF:xxx,用于配置文件

场景 3:调试部署问题

bash 复制代码
java -jar myapp.war -debug -resetExtract

场景 4:启用 HTTPS

bash 复制代码
java -jar myapp.war \
  -httpsPort 8443 \
  -Djavax.net.ssl.keyStore=keystore.jks \
  -Djavax.net.ssl.keyStorePassword=secret

🧠 总结:一句话理解

Tomcat8RunnerCli 是可执行 WAR 的"命令行门面",它将用户输入的参数转化为结构化配置,驱动内嵌 Tomcat 启动,同时提供密码混淆等实用工具功能。

它是 传统 WAR 应用实现"单文件交付 + 灵活配置"体验的关键一环,让 Java Web 应用像脚本一样简单运行。

如果你正在使用 Maven 的 tomcat7-maven-pluginexec-war 目标,那么你生成的可执行 WAR 就是靠这个类来启动的!

相关推荐
程序员良辰19 小时前
【TongWeb8】使用 Crontab 定时重启和检测 TongWeb 服务
java·中间件·tomcat
上海云盾商务经理杨杨21 小时前
Tomcat 弱配置漏洞渗透实战!批量 getshell 高频漏洞
java·web安全·tomcat
小张同学a.5 天前
zabbix企业级监控平台3——服务监控与API实战
linux·运维·mysql·nginx·tomcat·zabbix
xxwl58511 天前
数据库后端接口测试报告
spring boot·mysql·tomcat
次次皮13 天前
Linux 下通过 XShell 手动更新 Tomcat 应用并重启
前端·tomcat·jar
Listen·Rain14 天前
用AI开发出一个AI
java·人工智能·spring boot·tomcat·intellij-idea·mybatis·visual studio
Full Stack Developme15 天前
SpringBoot 内嵌 Tomcat 的启动流程
spring boot·后端·tomcat
Full Stack Developme15 天前
Tomcat 如何处理HTTP请求
java·http·tomcat
Full Stack Developme16 天前
Tomcat 设计原理
java·tomcat
Full Stack Developme16 天前
Tomcat NIO连接器内部如何实现零拷贝 Session管理如何实现集群同步
java·tomcat·nio