Apache Texen 常用 CLI 命令与工具详解
围绕 Texen 1.0 的命令行使用,逐项实测 ant 主命令与 -projecthelp/-debug 选项、TexenTask 全部 11 个属性(含四个必填校验报错原文)与 jar 内默认配置。
Apache Texen 常用 CLI 命令与工具详解
目标:把 Texen 1.0 在命令行下的全部操作面讲透——ant 主命令与常用选项、
<texen>任务的 11 个属性逐项实测行为(含每个必填属性缺失时的报错原文)、jar 内默认配置解读。全部命令与回显已在 Ubuntu 22.04.5 LTS(JDK 17.0.20.1 + Ant 1.10.12)实测通过。
一、环境信息
本文实测环境:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- JDK:OpenJDK 17.0.20.1(apt 包 openjdk-17-jdk)
- 构建工具:Apache Ant 1.10.12(apt 包 ant)
- 生成框架:Apache Texen 1.0(
org.apache.texen:texen:1.0,17159 字节) - 模板引擎:Velocity 1.7 + commons-collections 3.2.2 + commons-lang 2.6(全兼容推荐组合,实测)
- 示例工程:
/root/texen-demo/v17-html/(行星 HTML 生成器,文件清单见三、前置条件)
版本核验(实测):
java -version && ant -version
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
Apache Ant(TM) version 1.10.12 compiled on January 17 1970
二、工具概览
Texen 是库/框架形态的工具,没有自带可执行程序;它的"命令行"由两层组成:
| 层 | 工具 | 说明 |
|---|---|---|
| 命令层 | ant | 构建入口,执行 build.xml 中的 target;本文实测 main/clean 目标与 -projecthelp、-debug、-f 选项 |
| 任务层 | <texen>(TexenTask) | build.xml 里的生成任务,11 个属性控制模板路径、输出目录、编码等 |
| 模板层 | $generator / $strings / $files / $properties | 模板内可调用的预置上下文对象 |
TexenTask 对外暴露的全部方法(javap 实测,11 个 setter 即 11 个可配置属性):
javap -classpath lib/texen-1.0.jar org.apache.texen.ant.TexenTask
public class org.apache.texen.ant.TexenTask extends org.apache.tools.ant.Task {
public org.apache.texen.ant.TexenTask();
public void setControlTemplate(java.lang.String);
public java.lang.String getControlTemplate();
public void setTemplatePath(java.lang.String) throws java.lang.Exception;
public java.lang.String getTemplatePath();
public void setOutputDirectory(java.io.File);
public java.lang.String getOutputDirectory();
public void setOutputFile(java.lang.String);
public void setOutputEncoding(java.lang.String);
public void setInputEncoding(java.lang.String);
public java.lang.String getOutputFile();
public void setLogFile(java.lang.String);
public java.lang.String getLogFile();
public void setContextProperties(java.lang.String);
public org.apache.commons.collections.ExtendedProperties getContextProperties();
public void setUseClasspath(boolean);
public void setUseResourceLoaderCache(java.lang.String);
public void setResourceLoaderModificationCheckInterval(java.lang.String);
public org.apache.velocity.context.Context initControlContext() throws java.lang.Exception;
public void execute() throws org.apache.tools.ant.BuildException;
}
模板侧的核心入口 $generator 的公开 API(javap 实测,parse 三个重载是模板调用主入口):
javap -classpath lib/texen-1.0.jar org.apache.texen.Generator | grep -E "public|parse"
public class org.apache.texen.Generator {
public static final java.lang.String OUTPUT_PATH;
public static final java.lang.String TEMPLATE_PATH;
public static org.apache.texen.Generator getInstance();
public void setVelocityEngine(org.apache.velocity.app.VelocityEngine);
public org.apache.texen.Generator(java.lang.String);
public org.apache.texen.Generator(java.util.Properties);
public void setTemplatePath(java.lang.String);
public java.lang.String getTemplatePath();
public void setOutputPath(java.lang.String);
public java.lang.String getOutputPath();
public void setOutputEncoding(java.lang.String);
public void setInputEncoding(java.lang.String);
public java.io.Writer getWriter(java.lang.String, java.lang.String) throws java.lang.Exception;
public org.apache.velocity.Template getTemplate(java.lang.String, java.lang.String) throws java.lang.Exception;
public java.lang.String parse(java.lang.String, java.lang.String) throws java.lang.Exception;
public java.lang.String parse(java.lang.String, java.lang.String, java.lang.String, java.lang.Object) throws java.lang.Exception;
public java.lang.String parse(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Object) throws java.lang.Exception;
public java.lang.String parse(java.lang.String, org.apache.velocity.context.Context) throws java.lang.Exception;
public void shutdown();
static java.lang.Class class$(java.lang.String);
static {};
}
💡 技术拓展:模板路径解析由 useClasspath 属性切换两种资源加载器——
加载方式 触发条件 查找位置 实测回显标志 文件系统加载 默认(不设 useClasspath) templatePath 目录 回显 [texen] templates(打印模板路径)classpath 加载 useClasspath=true Ant 类路径 回显 [texen] Using classpath两种方式本文均已实测跑通,回显标志可作为定位"模板为什么找不到"的第一手线索。
三、前置条件
命令演示依赖一个可运行的 Texen 工程。以下给出最小工程(行星 HTML 生成器)的完整构成,独立可复现;依赖 jar 的下载与校验方法见《Apache Texen 在 Ubuntu 22.04 集成使用指南》。
工程结构(实测):
/root/texen-demo/v17-html/
├── build.xml
├── lib/
│ ├── commons-collections-3.2.2.jar
│ ├── commons-lang-2.6.jar
│ ├── texen-1.0.jar
│ └── velocity-1.7.jar
└── templates/
├── Control.vm
└── HtmlTemplate.vm
build.xml(完整文件):
<?xml version="1.0" encoding="UTF-8"?>
<project name="HtmlGenerator" default="main" basedir=".">
<description>Apache Texen 官方示例:行星 HTML 页面生成器(Velocity 1.7)</description>
<!-- Texen 运行所需 jar:texen-1.0.jar + velocity-1.7.jar + commons-collections-3.2.2.jar + commons-lang-2.6.jar -->
<path id="texen.classpath">
<fileset dir="lib" includes="*.jar"/>
</path>
<!-- 注册 TexenTask -->
<taskdef name="texen" classname="org.apache.texen.ant.TexenTask" classpathref="texen.classpath"/>
<target name="main" description="生成 Earth/Mars/Venus 三个 HTML 页面">
<echo message="+------------------------------------------+"/>
<echo message="| Generating HTML pages! |"/>
<echo message="+------------------------------------------+"/>
<texen
controlTemplate="Control.vm"
outputDirectory="output"
templatePath="templates"
outputFile="generation.report"/>
</target>
<target name="clean" description="清空 output 目录">
<delete dir="output"/>
</target>
</project>
templates/Control.vm 与 templates/HtmlTemplate.vm 内容(完整文件):
#*
* Control.vm —— 控制模板:驱动整个生成过程。
* 遍历行星列表,逐个调用 HtmlTemplate.vm 生成 HTML 页面。
*#
#set ($Planets = ["Earth", "Mars", "Venus"])
#foreach ($planet in $Planets)
#set ($outputFile = $strings.concat([$planet, ".html"]))
$generator.parse("HtmlTemplate.vm", $outputFile, "planet", $planet)
#end
#*
* HtmlTemplate.vm —— 工人模板:由控制模板调用,产出单个 HTML 页面。
*#
#set ($bgcolor = "#ffffff")
<html>
<head>
<title>
Everything you wanted to know about $planet!
</title>
</head>
<body bgcolor="$bgcolor">
$planet is a great place to live!
</body>
</html>
环境验证(实测,工程就绪的判定标准):
cd /root/texen-demo/v17-html && ls lib/ templates/
lib:
commons-collections-3.2.2.jar
commons-lang-2.6.jar
texen-1.0.jar
velocity-1.7.jar
templates:
Control.vm
HtmlTemplate.vm
四、各工具详解
4.1 ant 主命令:执行生成目标
ant 不带目标名时执行 project 的 default 目标(本工程为 main)。显式指定目标更清晰(实测):
cd /root/texen-demo/v17-html && ant main
Buildfile: /root/texen-demo/v17-html/build.xml
main:
[echo] +------------------------------------------+
[echo] | Generating HTML pages! |
[echo] +------------------------------------------+
[texen] templates
[texen] Generating to file /root/texen-demo/v17-html/output/generation.report
BUILD SUCCESSFUL
Total time: 0 seconds
关键回显解读:[texen] templates 是 TexenTask 打印的模板路径(文件系统加载方式);[texen] Generating to file 行指明报告文件落点(本例为 /root/texen-demo/v17-html/output/generation.report);产物落在 output/ 下(实测 3 个 HTML 与 1 个报告)。
验证产物(实测):
ls output/
Earth.html
Mars.html
Venus.html
generation.report
4.2 ant clean:清理产物
ant clean
Buildfile: /root/texen-demo/v17-html/build.xml
clean:
[delete] Deleting directory /root/texen-demo/v17-html/output
BUILD SUCCESSFUL
Total time: 0 seconds
清理后再生成(clean 与 main 可一次连跑,实测):
ant clean main
Buildfile: /root/texen-demo/v17-html/build.xml
clean:
[delete] Deleting directory /root/texen-demo/v17-html/output
main:
[echo] +------------------------------------------+
[echo] | Generating HTML pages! |
[echo] +------------------------------------------+
[texen] templates
[texen] Generating to file /root/texen-demo/v17-html/output/generation.report
BUILD SUCCESSFUL
Total time: 0 seconds
4.3 ant -projecthelp:查看目标清单
不记得工程里有哪些目标时用它(LANG=C.UTF-8 环境实测,中文 description 正常显示):
export LANG=C.UTF-8
ant -projecthelp
Buildfile: /root/texen-demo/v17-html/build.xml
Apache Texen 官方示例:行星 HTML 页面生成器(Velocity 1.7)
Main targets:
clean 清空 output 目录
main 生成 Earth/Mars/Venus 三个 HTML 页面
Default target: main
回显第一部分是 project 的 description;Main targets 列出两个目标的 description;Default target 指明不带参数时执行 main。若 LANG 为空,上述中文会显示为问号(编码问题见 4.10 与注意事项)。
4.4 ant -debug:排障定位
生成失败时,-debug 会输出完整异常栈,包括 Caused by 的根因。实测一次「模板未建输出目录」的故障(从 5.2 类工程去掉 $files.mkdir 后复现):
cd /root/texen-demo/v17-mkdir-repro && ant -debug 2>&1 | grep -B2 -A6 "Caused by"
输出节选(实测,-B2 上文两行是外层异常栈尾部):
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)
Caused by: java.io.FileNotFoundException: /root/texen-demo/v17-mkdir-repro/output/com/quzuo/demo/User.java (No such file or directory)
at java.base/java.io.FileOutputStream.open0(Native Method)
at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:123)
at org.apache.texen.Generator.getWriter(Generator.java:294)
at org.apache.texen.Generator.parse(Generator.java:401)
非 debug 模式下同一故障只给一句话提示(实测输出节选):
BUILD FAILED
/root/texen-demo/v17-mkdir-repro/build.xml:20: Exception thrown by 'generator.parse'. For more information consult the velocity log, or invoke ant with the -debug flag.
Total time: 0 seconds
💡 说明:报错文案让"consult the velocity log",但 TexenTask 的 logFile 属性实测并不产生日志文件(见 4.11),所以 -debug 是唯一可靠的排障通道。
4.5 ant -f:指定构建文件
build.xml 不在当前目录或用了别的文件名时,用 -f 指定(实测):
cd /root/texen-demo && ant -f v17-html/build.xml main
Buildfile: /root/texen-demo/v17-html/build.xml
main:
[echo] +------------------------------------------+
[echo] | Generating HTML pages! |
[echo] +------------------------------------------+
[texen] templates
[texen] Generating to file /root/texen-demo/v17-html/output/generation.report
BUILD SUCCESSFUL
Total time: 0 seconds
回显首行确认 Buildfile 定位到了 v17-html/build.xml;产物仍落在该工程自己的 output/ 下。
4.6 属性详解:controlTemplate(必填)
控制模板文件名,相对 templatePath(或 classpath)。整个生成过程以它为唯一入口。缺失时启动即失败(实测,删除该属性后执行):
BUILD FAILED
/root/texen-demo/v17-missing-ctrl/build.xml:20: The control template needs to be defined!
Total time: 0 seconds
4.7 属性详解:templatePath(条件必填)
模板所在磁盘目录。useClasspath 为默认 false 时必填,缺失时报错原文(实测):
BUILD FAILED
/root/texen-demo/v17-missing-tplpath/build.xml:20: The template path needs to be defined if you are not using the classpath for locating templates!
Total time: 0 seconds
useClasspath=true 时此属性被忽略,模板改由类路径定位(回显标志差异见 4.1 与二、工具概览的拓展块)。
4.8 属性详解:outputDirectory 与 outputFile(均必填)
outputDirectory 是产物根目录(相对执行 ant 时的目录),outputFile 是控制模板渲染结果的报告文件名。两者缺失的报错原文(实测):
BUILD FAILED
/root/texen-demo/v17-missing-outdir4/build.xml:20: The output directory needs to be defined!
Total time: 0 seconds
BUILD FAILED
/root/texen-demo/v17-missing-outfile3/build.xml:21: The output file needs to be defined!
Total time: 0 seconds
两个属性「置空」与「不设置」的语义不同,实测行为:
| 写法 | 实测行为 |
|---|---|
| 不设置 outputDirectory | 启动即失败:The output directory needs to be defined! |
| outputDirectory="" | 通过必填校验,产物直接生成到工程根目录(回显 Generating to file /root/texen-demo/v17-missing-outdir/generation.report) |
| 不设置 outputFile | 启动即失败:The output file needs to be defined! |
| outputFile="" | 通过必填校验,随后 Generation failed(报告文件无法定位) |
⚠️ 注意:Texen 只保证 outputDirectory 目录本身存在,子目录不会自动创建——模板生成嵌套路径文件前必须先调用 $files.mkdir(实测 FileNotFoundException 复现与解法见《Apache Texen 在 Ubuntu 22.04 集成使用指南》6.2 节)。
4.9 属性详解:inputEncoding / outputEncoding(建议显式设置)
模板读取与产物写出的字符集,默认随 JVM 环境。中文环境下的实测结论:不设置时模板与产物中文全部变问号;设置 UTF-8 后完整保留(前后对照回显见《Apache Texen 在 Ubuntu 22.04 集成使用指南》6.1 节)。
💡 说明:这两个属性管的是「模板文件」与「产物文件」的编码;运行环境变量 LANG 影响的是 JVM 默认编码(进而影响 contextProperties 读文件等行为),两者要同时检查。实测修复组合:模板/产物设 UTF-8,执行前 export LANG=C.UTF-8。
4.10 属性详解:contextProperties
指向一个属性文件,键值注入模板上下文,实测三类自动转换:数字串转 Integer(maxDepth=3)、true/false 转 Boolean(verbose=true)、键名以 file.contents 结尾时把整个文件内容作为字符串注入且键名去掉该后缀(license.file.contents → $license,实测 license 文本出现在每个生成文件的头部)。
任务执行时的确认回显(实测):
[texen] Using contextProperties file: /root/texen-demo/v17-model-utf8/build.properties
⚠️ 注意:该属性与 Velocity Engine 2.4.1 不兼容,设置即触发 NoSuchMethodError(实测报错原文见《Apache Texen 在 Ubuntu 22.04 集成使用指南》5.4 节)。搭配 Velocity 1.7 使用则一切正常。
4.11 属性详解:logFile(实测无效)
字面含义是引擎日志文件。实测在文件系统加载(logFile="texen.log")与 classpath 加载(logFile="texen-cp.log")两种方式下执行后,日志文件都不存在:
ls texen.log
ls: cannot access '/root/texen-demo/v17-model-utf8/texen.log': No such file or directory
ls texen-cp.log
ls: cannot access '/root/texen-demo/v17-cp/texen-cp.log': No such file or directory
结论:不要依赖 logFile 排障,用 ant -debug(见 4.4)。
4.12 属性详解:useClasspath / useResourceLoaderCache / resourceLoaderModificationCheckInterval
三个属性共同控制「模板从 classpath 加载 + 缓存」组合(实测配置与回显):
<texen
controlTemplate="Control.vm"
outputDirectory="output"
outputFile="generation.report"
useClasspath="true"
useResourceLoaderCache="true"
resourceLoaderModificationCheckInterval="0"
logFile="texen-cp.log"/>
Buildfile: /root/texen-demo/v17-cp/build.xml
main:
[texen] Using classpath
[texen] Generating to file /root/texen-demo/v17-cp/output/generation.report
BUILD SUCCESSFUL
Total time: 0 seconds
- useClasspath=true:模板由 ClasspathResourceLoader 从 Ant 类路径查找,回显标志为
[texen] Using classpath。 - useResourceLoaderCache:对应 classpath.resource.loader.cache 配置,true 时缓存已解析模板。
- resourceLoaderModificationCheckInterval:缓存刷新检查间隔(秒),0 表示每次都检查模板修改。
⚠️ 注意:useClasspath=true 时,模板所在目录必须加入 taskdef 的类路径,否则模板找不到(本文实测在
<path>中追加<pathelement location="templates"/>后跑通)。
4.13 jar 内默认配置解读
Texen 的默认值集中在 jar 内 org/apache/texen/defaults/texen.properties,提取与查看(实测):
cd /tmp && rm -rf texen-x && mkdir texen-x && cd texen-x && jar xf /root/texen-demo/lib/texen-1.0.jar org/apache/texen/defaults/texen.properties && cat org/apache/texen/defaults/texen.properties
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
path.output=output
context.objects.strings=org.apache.velocity.util.StringUtils
context.objects.files=org.apache.texen.util.FileUtil
context.objects.properties=org.apache.texen.util.PropertiesUtil
逐项说明:
| 配置键 | 默认值 | 含义 |
|---|---|---|
| path.output | output | 输出目录的默认相对路径 |
| context.objects.strings | org.apache.velocity.util.StringUtils | $strings 上下文对象的实现类(velocity 2.x 已删除其多数方法,见 4.10 注意) |
| context.objects.files | org.apache.texen.util.FileUtil | $files 上下文对象的实现类(mkdir 内部为 mkdirs()) |
| context.objects.properties | org.apache.texen.util.PropertiesUtil | $properties 上下文对象的实现类 |
五、注意事项
- 四个必填属性缺一不可:controlTemplate、outputDirectory、outputFile 在 useClasspath=false 时加上 templatePath,缺失时的报错原文全部实测捕获(见 4.6~4.8),遇错先对照文案定位是哪个属性没配。
- 「不设置」与「置空」行为不同:outputDirectory/outputFile 置空能通过必填校验但产生错误落点或后续失败(实测行为表见 4.8),检查配置时先确认属性被删除还是被清空。
- logFile 不产生文件:两种模板加载方式实测均无日志文件,排障唯一可靠通道是 ant -debug。
- 模板缓存与热更新:useResourceLoaderCache=true 时模板被缓存,改模板不生效时检查 resourceLoaderModificationCheckInterval(本文实测取 0 保证每次检查修改)。
- 编码三处设防:inputEncoding/outputEncoding 管 Template 与产物,LANG 管 JVM 默认编码,ant 控制台回显受 LANG 影响(export LANG=C.UTF-8 实测修复,详见《Apache Texen 在 Ubuntu 22.04 集成使用指南》6.1)。
- 换行吞噬:Velocity 1.7 会吞掉 #set/#if/#end 行尾换行,多行文本模板用「先拼变量、单独输出」模式(实测 Sql.vm 模式)。
- 控制模板输出即报告:outputFile 文件内容就是控制模板的渲染结果,编排型模板写报告时注意行首行尾干净,避免杂质(实测报告 4 字节空行案例与全文并入案例)。
六、常见问题
Q1:ant main 报 The control template needs to be defined! 怎么办?
build.xml 的 <texen> 元素缺少 controlTemplate 属性,或属性名拼写错误。补上 controlTemplate="Control.vm"(指向 templatePath 下实际存在的模板文件)后重跑,实测修复。
Q2:报 The template path needs to be defined if you are not using the classpath for locating templates! 怎么办?
两种选择:补 templatePath="templates"(模板在磁盘目录);或 useClasspath="true" 并把模板目录加入 taskdef 类路径(<pathelement location="templates"/>,实测可行)。报错文案本身已提示判断条件。
Q3:生成嵌套目录文件时报 FileNotFoundException 怎么办?
Texen 不自动创建子目录。在控制模板生成前调用 $files.mkdir("output/com/quzuo/demo")(注意带上 output/ 前缀,路径相对执行 ant 的目录),或改用扁平输出目录。实测复现与 -debug 栈见 4.4。
Q4:产物或控制台中文全是问号怎么办? 三步排查:build.xml 加 inputEncoding="UTF-8" outputEncoding="UTF-8";执行前 export LANG=C.UTF-8;确认模板文件本身是 UTF-8 保存。实测前后对照见《Apache Texen 在 Ubuntu 22.04 集成使用指南》6.1。
Q5:搭配 Velocity 2.4.1 报 NoSuchMethodError: StringUtils.split 怎么办? Texen 1.0 的 setContextProperties 调用了 Velocity 2.x 已删除的方法,无法通过配置规避。方案:固定搭配 Velocity 1.7(推荐、全兼容实测);或升级到 2.4.1 时同时放弃 contextProperties 属性并改写模板中所有 $strings 调用(实测仅 formatFileString 系列静态方法保留)。
Q6:为什么模板改了输出没变化? 若启用了 useResourceLoaderCache="true",模板会走缓存;把 resourceLoaderModificationCheckInterval 设为 0(每次检查修改,本文实测配置)或临时关掉缓存再试。
Q7:产物怎么跑到工程根目录了? 检查 outputDirectory 是否被置空(outputDirectory=""):置空能过必填校验,产物会落到执行 ant 的当前目录(实测见 4.8 行为表)。恢复为 output 并确认目录存在。
七、参考链接
- Texen 官方文档(1.0):https://velocity.apache.org/texen/1.0/
- Maven Central 坐标:https://repo1.maven.org/maven2/org/apache/texen/texen/1.0/
- Apache Ant 手册(命令行选项与 taskdef):https://ant.apache.org/manual/
- Apache Velocity 1.7 文档:https://velocity.apache.org/engine/1.7/
- 本文配套文档:《Apache Texen 介绍与选型指南》(选型与架构)、《Apache Texen 在 Ubuntu 22.04 集成使用指南》(0 到 1 集成与编码/目录坑)