Apache Texen 常用 CLI 命令与工具详解

围绕 Texen 1.0 的命令行使用,逐项实测 ant 主命令与 -projecthelp/-debug 选项、TexenTask 全部 11 个属性(含四个必填校验报错原文)与 jar 内默认配置。

Apache TexenApache TexenJavaApache命令行2026/10/16

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=trueAnt 类路径回显 [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.outputoutput输出目录的默认相对路径
context.objects.stringsorg.apache.velocity.util.StringUtils$strings 上下文对象的实现类(velocity 2.x 已删除其多数方法,见 4.10 注意)
context.objects.filesorg.apache.texen.util.FileUtil$files 上下文对象的实现类(mkdir 内部为 mkdirs())
context.objects.propertiesorg.apache.texen.util.PropertiesUtil$properties 上下文对象的实现类

五、注意事项

  1. 四个必填属性缺一不可:controlTemplate、outputDirectory、outputFile 在 useClasspath=false 时加上 templatePath,缺失时的报错原文全部实测捕获(见 4.6~4.8),遇错先对照文案定位是哪个属性没配。
  2. 「不设置」与「置空」行为不同:outputDirectory/outputFile 置空能通过必填校验但产生错误落点或后续失败(实测行为表见 4.8),检查配置时先确认属性被删除还是被清空。
  3. logFile 不产生文件:两种模板加载方式实测均无日志文件,排障唯一可靠通道是 ant -debug。
  4. 模板缓存与热更新:useResourceLoaderCache=true 时模板被缓存,改模板不生效时检查 resourceLoaderModificationCheckInterval(本文实测取 0 保证每次检查修改)。
  5. 编码三处设防:inputEncoding/outputEncoding 管 Template 与产物,LANG 管 JVM 默认编码,ant 控制台回显受 LANG 影响(export LANG=C.UTF-8 实测修复,详见《Apache Texen 在 Ubuntu 22.04 集成使用指南》6.1)。
  6. 换行吞噬:Velocity 1.7 会吞掉 #set/#if/#end 行尾换行,多行文本模板用「先拼变量、单独输出」模式(实测 Sql.vm 模式)。
  7. 控制模板输出即报告: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 并确认目录存在。

七、参考链接