Apache Commons Validator 1.11.0 配置参数详解
系统梳理 Apache Commons Validator 1.11.0 在环境、校验器实例开关与 XML 规则三个层面的全部配置项并附实测矩阵
Apache Commons Validator 1.11.0 配置参数详解
目标:完整梳理 Commons Validator 1.11.0 的三类配置入口(JVM 环境、校验器实例开关、XML 规则文件),并对每个开关给出实测验证矩阵,已在 Ubuntu 22.04(x86_64)+ Temurin JDK 17.0.20.1 + Maven 3.9.16 环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- 架构:x86_64
- JDK:Temurin OpenJDK 17.0.20.1
- 构建工具:Apache Maven 3.9.16
- 组件版本:Apache Commons Validator 1.11.0
- Maven 坐标:
commons-validator:commons-validator:1.11.0 - 工作目录:
/work/demo(示例工程根目录,全部探针类位于src/main/java)
二、配置体系总览
Commons Validator 是「无配置文件、纯代码开关」的库,这一点与数据库连接池类组件完全不同。它的配置入口分三层:
| 层级 | 配置手段 | 典型示例 | 生效范围 |
|---|---|---|---|
| 环境层 | JVM 参数、Locale、依赖编排 | -Dfile.encoding=UTF-8、Locale.US | 整个进程 |
| 实例层 | 构造参数与 getInstance 重载 | UrlValidator.ALLOW_ALL_SCHEMES | 单个校验器实例 |
| 规则层 | validation.xml + 回调类 | <field depends="required,email"> | 一次表单校验 |
💡 技术拓展:同为 Apache Commons 组件,「配置详解」的写法因组件而异——像 Commons IO 的 IOUtils 只有方法参数可谈;而 Validator 的「配置」主要体现为校验器构造开关与 XML 规则要素。本文按上述三层展开,所有结论均来自 1.11.0 实测。
三、环境层配置
3.1 JDK 版本兼容
官方 RELEASE-NOTES 原文:This is a feature and maintenance release. Java 8 or later is required.。因此:
- 编译期:组件本身按 Java 8 字节码发布,工程 POM 可将
maven.compiler.source/target设为 8~17 之间任意版本; - 运行期:JDK 8/11/17/21 均可,本文全部探针在 JDK 17 下编译运行通过;
- 唯一注意点:旧式 XML 方式依赖的 commons-digester 2.1 与 commons-beanutils 1.11.0 在 JDK 17 下实测无兼容问题(见第十章实测回显)。
3.2 字符编码与 Locale
- 编码:实测 Ubuntu 环境
mvn -version显示platform encoding: ANSI_X3.4-1968,处理中文 pattern(如yyyy年MM月dd日)或中文数据时统一加-Dfile.encoding=UTF-8,本文所有java命令均带该参数; - Locale:数值与日期校验器(
DateValidator、CurrencyValidator等)是 Locale 敏感的,调用时显式传Locale.US、Locale.GERMANY等,不要依赖系统默认值,具体实测见 8.2 节。
3.3 Maven 依赖编排
commons-validator:1.11.0 自动带入四个传递依赖。若确认只用 routines 包代码校验,可排除以减小体积:
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.11.0</version>
<exclusions>
<exclusion>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
实测依赖树(未排除时):
[INFO] com.example.validator:commons-validator-demo:jar:1.0.0
[INFO] \- commons-validator:commons-validator:jar:1.11.0:compile
[INFO] +- commons-beanutils:commons-beanutils:jar:1.11.0:compile
[INFO] +- commons-digester:commons-digester:jar:2.1:compile
[INFO] +- commons-logging:commons-logging:jar:1.4.0:compile
[INFO] \- commons-collections:commons-collections:jar:3.2.2:compile
要点提示:XML 规则方式(第十章)依赖 digester 解析与 beanutils 取值,排除后这两者将不可用,需按需取舍。
四、UrlValidator:scheme 与结构开关
4.1 开关常量一览
| 常量 | 含义 | 默认行为 |
|---|---|---|
ALLOW_ALL_SCHEMES | 放行任意 scheme(默认仅 http/https/ftp) | 不开启 |
ALLOW_LOCAL_URLS | 放行单标签主机名等本地 URL | 不开启 |
ALLOW_2_SLASHES | 放行路径中连续双斜杠 // | 不开启 |
NO_FRAGMENTS | 禁止锚点片段(# 及其后内容) | 锚点默认允许 |
开关通过位或组合传入构造器:new UrlValidator(UrlValidator.ALLOW_ALL_SCHEMES | UrlValidator.ALLOW_LOCAL_URLS)。
4.2 实测矩阵
探针对默认实例与四个开关实例逐一验证(-> 后为实测返回值):
default http://www.apache.org -> true
default https://commons.apache.org/proper/commons-validator/ -> true
default ftp://ftp.example.com/pub/file.txt -> true
default http://www.apache.org:8080/index.html?q=validator#top -> true
default https://example.com/a/b?x=1&y=2 -> true
default gopher://example.com -> false
default ldap://example.com/dc=example,dc=com -> false
default www.apache.org -> false
default http://local.server/path -> false
default http://www.apache.org//double -> false
default http://bad url.com -> false
ALL_SCHEMES gopher://example.com -> true
ALL_SCHEMES ldap://example.com/dc=example,dc=com -> true
ALL_SCHEMES custom+app://host/path -> false
LOCAL_URLS http://local.server/path -> false
LOCAL_URLS http://myserver:8080/app -> true
LOCAL_URLS http://www.apache.org -> true
2_SLASHES http://www.apache.org//double -> true
2_SLASHES http://www.apache.org/single -> true
NO_FRAGMENTS http://www.apache.org/index.html#top -> false
NO_FRAGMENTS http://www.apache.org/index.html -> true
COMBO myapp://internal.host:8080//a/b#frag -> true
实测发现两个反直觉点:
ALLOW_ALL_SCHEMES下custom+app://host/path仍为 false:scheme 正则不允许+字符,含加号的自定义协议需业务层先行放行;ALLOW_LOCAL_URLS下http://local.server/path仍为 false:local.server不是单标签主机,其 TLDserver不在 1.11.0 内置 TLD 表中(实测DomainValidator.isValidTld("server") = false,而app为 true,内置 generic TLD 共 1127 个),既非合法 TLD 又非本地主机,两个分支都不放行。
4.3 分解校验方法
isValidScheme/isValidAuthority/isValidPath/isValidQuery/isValidFragment 五个方法在 1.11.0 中是 protected,需要通过子类暴露才能单独调用:
static class ExposedUrlValidator extends UrlValidator {
boolean checkScheme(String s) { return isValidScheme(s); }
boolean checkAuthority(String s) { return isValidAuthority(s); }
boolean checkPath(String s) { return isValidPath(s); }
boolean checkQuery(String s) { return isValidQuery(s); }
boolean checkFragment(String s) { return isValidFragment(s); }
}
默认实例实测:
isValidScheme(http) = true
isValidScheme(gopher) = false
isValidAuthority(www.apache.org:8080) = true
isValidAuthority(bad_host) = false
isValidPath(/proper/commons-validator/) = true
isValidPath(//double) = false
isValidQuery(?q=validator) = true
isValidFragment(#top) = true
要点提示:分解方法适合定位「一个 URL 为什么被拒」,例如 //double 路径默认拒绝正好解释了 4.2 节 ALLOW_2_SLASHES 的存在意义。
五、EmailValidator:allowLocal 与 allowTld
5.1 开关语义
| 构造方式 | allowLocal | allowTld | 效果 |
|---|---|---|---|
getInstance() | false | false | 最严格:域名必须是「合法 TLD 结尾的普通域名」 |
getInstance(true) | true | false | 额外放行内置本地 TLD(localdomain、localhost) |
getInstance(true, true) | true | true | 额外放行「纯 TLD 域名」如 user@com、user@cn |
5.2 实测
默认实例 19 个样本:
"user@example.com" -> true
"first.last@sub.example.com" -> true
"user+tag@example.com" -> true
"user_123@example.co.uk" -> true
"user@[192.168.1.2]" -> true
"user@[::1]" -> false
"user@192.168.1.2" -> false
""john doe"@example.com" -> true
"user@localhost" -> false
"user.name@" -> false
"@example.com" -> false
"user@example..com" -> false
"user@@example.com" -> false
"user name@example.com" -> false
"user@.example.com" -> false
"user@example.com." -> false
"user@example.c" -> false
"user@-example.com" -> false
"user@com" -> false
开关实例:
---- getInstance(true)(allowLocal) ----
user@localhost -> true
user@myhost.local -> false
user@com -> true
---- getInstance(true, true)(allowLocal + allowTld) ----
user@com -> true
user@cn -> true
user@localhost -> true
实测要点:
- IPv4 域字面量
user@[192.168.1.2]无需任何开关即为 true;但 IPv6 字面量user@[::1]为 false——1.11.0 的 IPv6 域字面量判断分支实测不可达,这是组件现状,需要时应在业务层先解析; - 引号本地部分
""john doe"@example.com"是 true,1.11.0 允许 RFC 风格 quoted-string 本地部分; user@myhost.local为 false:.local不在内置本地 TLD 数组中(内置仅localdomain,localhost,见 7.1 节),需用 7.3 节的LOCAL_PLUS扩展才能放行。
六、InetAddressValidator:行为即配置
该类没有构造开关,配置体现在「校验语义」上。全部实测:
IPv4 192.168.1.1 -> true
IPv4 255.255.255.0 -> true
IPv4 0.0.0.0 -> true
IPv4 127.0.0.1 -> true
IPv4 256.1.1.1 -> false
IPv4 1.2.3 -> false
IPv4 1.2.3.4.5 -> false
IPv4 1.2.3.4a -> false
IPv4 01.02.03.04 -> false
IPv4 1.2.3.256 -> false
IPv6 ::1 -> true
IPv6 fe80::1 -> true
IPv6 2001:db8::8a2e:370:7334 -> true
IPv6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 -> true
IPv6 ::ffff:192.168.1.1 -> true
IPv6 2001:db8::8a2e:370::7334 -> false
IPv6 1:2:3:4:5:6:7:8:9 -> false
IPv6 12345:: -> false
IPv6 ::ffff:999.1.1.1 -> false
合并 ::1 -> true
合并 192.168.1.1 -> true
合并 example.com -> false
要点提示:01.02.03.04 被拒绝(前导零安全语义,避免八进制歧义);::ffff:192.168.1.1 这类 IPv4 映射地址按 IPv6 校验通过;合并方法 isValid 对任一地址族通过即返回 true。
七、DomainValidator:TLD 表与扩展开关
7.1 内置 TLD 数组规模
1.11.0 把 TLD 列表内置为四个只读数组,可通过 DomainValidator.getTLDEntries(ArrayType) 读取,实测规模:
GENERIC_RO 条目数 = 1127
COUNTRY_CODE_RO 条目数 = 309
INFRASTRUCTURE_RO = arpa
LOCAL_RO = localdomain,localhost
GENERIC 最后 5 个 = zara,zero,zip,zone,zuerich
💡 技术拓展:四类 TLD 数组的分工
| 数组 | 实测规模 | 含义 | 示例 |
|---|---|---|---|
| GENERIC_RO | 1127 | 通用顶级域 | com、info、xxx、app |
| COUNTRY_CODE_RO | 309 | 国家和地区顶级域 | cn、uk、de |
| INFRASTRUCTURE_RO | 1(arpa) | 基础设施域 | arpa |
| LOCAL_RO | 2 | 本地保留域 | localdomain、localhost |
.xxx 属于 GENERIC_RO 内置成员(实测 isValidTld("xxx") = true 且 generic 分类命中),这是它与 localdomain 等的本质区别:前者是真实 gTLD,后者只在 allowLocal 开启时生效。
7.2 getInstance(allowLocal) 实测
isValidTld(xxx ) = true generic=true cc=false local=false
isValidTld(cn ) = true generic=false cc=true local=false
isValidTld(localhost ) = false generic=false cc=false local=true
isValidTld(example ) = false generic=false cc=false local=false
isValidTld(COM ) = true generic=true cc=false local=false
isValidTld(CN ) = true generic=false cc=true local=false
---- getInstance(true) 后 ----
isValidTld(localhost) = true
isValidTld(example) = false
isValidLocalTld(localhost) = true
实测要点:分类判断大小写不敏感(COM/CN 均通过);example、invalid、test 虽是 RFC 2606 保留域,但 1.11.0 的 LOCAL_RO 并不包含它们,任何开关下都返回 false。
7.3 updateTLDOverride:四个扩展开关
DomainValidator.updateTLDOverride(ArrayType, String[]) 允许在运行时扩充或收缩 TLD 表,ArrayType 共四个值:GENERIC_PLUS(追加 gTLD)、GENERIC_MINUS(移除 gTLD)、LOCAL_PLUS(追加本地 TLD)、LOCAL_MINUS(移除本地 TLD)。
实测一:追加自定义 gTLD 与本地 TLD:
DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"mybrand"});
DomainValidator.updateTLDOverride(ArrayType.LOCAL_PLUS, new String[]{"mycorp.internal"});
isValidTld(mybrand) = true
isValidGenericTld(mybrand) = true
isValidTld(mycorp.internal)= false
isValidLocalTld(mycorp.internal) = true
isValidTld(com) = true
(mycorp.internal 的 isValidTld 为 false 是因为默认实例 allowLocal=false,getInstance(true) 下为 true。)
实测二:用 GENERIC_MINUS 关闭 .xxx:
DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, new String[]{"xxx"});
移除后 isValidTld(xxx) = false
对照 isValidTld(com) = true
要点提示:updateTLDOverride 必须在第一次 getInstance() 之前调用(单例缓存 TLD 表后才注册会失效),且这是进程级全局修改,多业务共存的进程要谨慎使用——对内容平台而言,GENERIC_MINUS 关闭 .xxx 域是 1.11.0 提供的现成开关。
八、数值、日期与货币校验器配置
8.1 DateValidator / CalendarValidator
可配置点为构造参数与调用参数两层:构造器 new DateValidator(boolean strict, int dateStyle),getInstance() 返回 strict=true 的共享实例;调用层可传 pattern 与 Locale。实测:
---- DateValidator(getInstance 默认 strict=true) ----
validate(15/10/2026, dd/MM/yyyy, US) = 2026-10-15
validate(2026-10-15, yyyy-MM-dd) = 2026/10/15
validate(15-10-2026, yyyy-MM-dd) = null
validate(2026-02-30, yyyy-MM-dd) = null
validate(10/15/2026, dd/MM/yyyy, US) = null
validate(15.10.2026, dd.MM.yyyy, DE) = 2026-10-15
lenient 2026-02-30 (回写格式化) = null
两条重要实测结论:
- pattern 与 Locale 决定解析成败:
15-10-2026对yyyy-MM-dd返回 null;德国区域dd.MM.yyyy正常解析; new DateValidator(false, DateFormat.SHORT)(strict=false)下2026-02-30仍为 null。源码核实:AbstractCalendarValidator第 365/390 行对底层 formatter 硬编码setLenient(false),strict 参数只影响「解析结果回写比对」,因此溢出日期(2 月 30 日)在任何配置下都会被拒绝,不会滚到 3 月。
CalendarValidator 返回 java.util.GregorianCalendar,pattern 中文字面量在 UTF-8 下工作正常:
---- CalendarValidator ----
parse 类型 = java.util.GregorianCalendar
format 回写 = 2026年10月15日 13:45
format 反转 = 13:45 2026-10-15
8.2 CurrencyValidator
按 Locale 解析与格式化,实测发现一个隐蔽的配置陷阱:
---- CurrencyValidator ----
validate($1,234.56, US) = 1234.56 (java.math.BigDecimal)
format(1234.56, US) = $1,234.56
format(1234.56, DE) = 1.234,56 €
validate(ASCII 空格写法, DE) = null
往返 validate(format 产物, DE) = 1234.56
德语区格式化结果 1.234,56 € 中的空格实际是不换行空格(U+00A0),手写 ASCII 空格的输入串解析直接失败返回 null;用 format() 产出的字符串做往返校验才通过。跨区域货币解析务必以组件自身 format 产物为准。
8.3 PercentValidator
默认实例的行为由底层 NumberFormat 的百分数格式决定,实测存在小数截断:
---- PercentValidator ----
validate(50%, US) = 0.50 (java.math.BigDecimal)
validate(12.5%, US) = 0.12
format(0.125, US) = 12%
实测解析链路:先按 DecimalFormat(小数位 0)解析,BigDecimalValidator.processParsedValue 以 ROUND_DOWN 把小数截断到 0 位,再乘 0.01——所以 12.5% 得到 0.12 而不是 0.125,format(0.125) 也只显示 12%。需要保留小数百分比时,应自定义 NumberFormat 后按对应构造器创建 PercentValidator 实例配套使用,而不是改默认单例。
8.4 LongValidator / IntegerValidator
---- LongValidator / IntegerValidator ----
validate(123456789012, US) = 123456789012 (java.lang.Long)
isInRange(5, 1, 10) = true
isInRange(11, 1, 10) = false
validate(abc, US) = null
validate(42, US) = 42 (java.lang.Integer)
数值校验器的配置就是 Locale 与取值范围,非法输入统一返回 null(配合 GenericValidator.isInRange 做区间判断)。
九、检查位(CheckDigit)配置
9.1 接口与 1.11.0 现状
所有检查位算法实现统一接口 CheckDigit:boolean isValid(String) 与 String calculate(String)(抛 CheckDigitException)。注意 1.11.0 的 AbstractCheckDigit 已相当精简,老资料中的 generate() 辅助方法已不存在,生成校验位请直接用 calculate 后自行拼接。
9.2 ModulusTenCheckDigit:通用模 10 构造器
构造器三参数为 ModulusTenCheckDigit(int[] positionWeight, boolean useRightPos, boolean sumWeightedDigits):权重数组、权重从右往左还是从左往右、以及是否对乘积做数位求和(Luhn/CUSIP 需要)。EAN-13 等价写法实测:
---- ModulusTenCheckDigit(通用模 10,权重可配;EAN-13 等价写法) ----
isValid(4006381333931) = true
isValid(4006381333932) = false
calculate(400638133393) = 1
9.3 经典 Mod11 的 1.11.0 写法
1.11.0 不内置 Mod11 算法类,需继承 ModulusCheckDigit 自实现。关键是权重函数的 rightPos 语义:校验位自身位置为 1,数据位自右向左从 2 开始:
static final class Mod11CheckDigit extends ModulusCheckDigit {
Mod11CheckDigit() { super(11); }
@Override
protected int weightedValue(int charValue, int leftPos, int rightPos) {
// rightPos=1 是校验位自身位置(权重 1);数据位自右向左权重 2 到 10 循环
int weight = rightPos;
if (weight > 10) {
weight = (weight - 2) % 9 + 2;
}
return charValue * weight;
}
}
实测(036532 的经典 Mod11 校验位为 7):
---- Mod11(ModulusCheckDigit 子类自实现,权重 2..10 自右向左) ----
calculate(036532) = 7
isValid(0365327) = true
isValid(0365328) = false
要点提示:若算法可能出现校验位 10(经典记法写作 X),还需覆写 toCheckDigit/toInt 处理 X 字符(ISBN10CheckDigit 即采用此做法),否则框架会抛 CheckDigitException: Invalid Check Digit Value =10——这是实测走过的弯路。
9.4 CreditCardValidator:卡种开关
new CreditCardValidator(int options) 用卡种常量位或组合(VISA、AMEX、MASTERCARD、DISCOVER),校验时先按前缀卡种匹配再跑 Luhn:
---- CreditCardValidator(卡种开关 + Luhn) ----
VISA+AMEX 6011111111111117 = false
全卡种 6011111111111117 = true
全卡种 4111111111111111 = true
全卡种 378282246310005 = true
全卡种 4111111111111112 = false
6011111111111117 是 Discover 测试卡号,Luhn 本身合法,仅因 VISA+AMEX 实例不含 DISCOVER 被拒——卡种开关与校验位是两层独立配置。
十、XML 规则配置详解
10.1 文档结构
validation.xml 根元素为 <form-validation>,下设 <global>(全局动作与常量)与 <formset>(表单集合),DOCTYPE 固定为 1.4.0 DTD(组件 jar 内置该 DTD,离线可解析)。DTD 对元素顺序有硬性要求:<global> 内必须先全部 <validator> 再 <constant>。
10.2 <global> 动作注册
每个校验动作由 <validator> 注册,四个属性:
| 属性 | 含义 | 本文取值 |
|---|---|---|
| name | 动作名,供 depends 引用 | required、minLength、email、intRange、mask |
| classname | 回调类全限定名 | MyChecks(默认包) |
| method | 回调静态方法名 | validateRequired 等 |
| methodParams | 方法签名(逗号分隔类名) | java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,java.util.List |
实测注意事项:<constant> 必须用子元素写法,写成属性会被 DTD 拒绝,实测报错(输出节选):
SEVERE: Parse Error at line 32 column 70: Attribute "constant-name" must be declared for element type "constant".
org.xml.sax.SAXParseException; lineNumber: 32; columnNumber: 70; Attribute "constant-name" must be declared for element type "constant".
10.3 <formset>/<form>/<field> 要素
| 要素/属性 | 作用 | 本文取值 |
|---|---|---|
<form name> | 表单名,new Validator(resources, formName) 按此查找 | orderForm |
<field property> | 绑定 bean 属性名,框架经 getter 取值 | customerName、email、age、postCode |
depends | 逗号分隔的动作链,按序执行,首个失败后本字段短路 | required,minLength 等 |
<arg key position> | 错误消息参数占位 | label.customerName 等 |
<var>/<var-name>/<var-value> | 传给回调的参数,field.getVarValue(name) 读取 | minlength=3、min=18、max=65、mask=${postCodeMask} |
${常量名} 会在加载期替换为 <global> 中定义的 <constant> 值,实测 mask 动作收到的已是替换后的 ^\d{6}$(第二轮 100081 通过即为证据)。
10.4 回调约定
回调方法返回 Boolean:TRUE 记 PASS、FALSE 或抛异常记 FAIL。抛异常时框架打印 SEVERE 日志并继续其余字段(输出节选,实测把未替换的 ${postCodeMask} 当正则时触发):
SEVERE: Unhandled exception thrown during validation: Illegal repetition near index 2
${postCodeMask}
^
java.util.regex.PatternSyntaxException: Illegal repetition near index 2
10.5 端到端实测
驱动代码与完整回显(两轮共 16 个断言):
---- 第一轮:全部非法 ----
postCode required=PASS mask=FAIL
customerName required=FAIL
email required=PASS email=FAIL
age intRange=FAIL required=PASS
---- 第二轮:全部合法 ----
postCode required=PASS mask=PASS
customerName minLength=PASS required=PASS
email required=PASS email=PASS
age intRange=PASS required=PASS
验证结果:required 失败后同字段后续动作短路;空值对非 required 动作放行(回调内自行返回 TRUE);常量替换、多动作依赖、范围校验全部按配置生效。完整的 validation.xml、回调类与驱动代码见本专栏快速入门篇第五节。
十一、常见问题(FAQ)
1. 为什么我的 URL 开了 ALLOW_ALL_SCHEMES 还是被拒?
检查 scheme 是否含 + 等非常规字符(实测 custom+app 被拒),以及主机名 TLD 是否在 1.11.0 内置表内(实测 server 不在、app 在)。
2. user@[::1] 为什么不合法?
1.11.0 的 IPv6 域字面量分支实测不可达,EmailValidator 只支持 IPv4 域字面量。需要 IPv6 时在业务层自行解析。
3. updateTLDOverride 调用后没生效?
必须在进程第一次 DomainValidator.getInstance() 之前调用;单例初始化后 TLD 表已固化。
4. 12.5% 解析成了 0.12?
PercentValidator 默认实例按小数位 0 的 DecimalFormat 解析并 ROUND_DOWN 截断,属预期行为;需要小数百分比请自建 NumberFormat 与校验器实例。
5. 2026-02-30 想放行怎么办?
组件在任何配置下都拒绝溢出日期(formatter 硬编码非宽松模式)。业务上确需宽松语义时,用 java.time 自行解析后再交给其他校验。
6. XML 方式如何定位失败原因?
三个抓手:ValidatorResult.isValid(action) 逐动作判断;ValidatorAction 的 SEVERE 异常日志;DTD 报错行号。三者叠加足以定位绝大多数规则文件问题。
7. 排除 digester 后 XML 方式报 NoClassDefFoundError?
XML 方式强依赖 digester/logging/beanutils/collections 四个包,要么不排除,要么彻底不用 XML 方式。
十二、参考链接
- UrlValidator API 文档:https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/UrlValidator.html
- DomainValidator API 文档:https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/DomainValidator.html
- EmailValidator API 文档:https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/EmailValidator.html
- 用户指南(XML 配置章节):https://commons.apache.org/proper/commons-validator/userguide/index.html
- 本专栏配套文档:《Apache Commons Validator 1.11.0 快速入门与集成示例》《Apache Commons Validator 1.11.0 常用 API 与校验器详解》