javax.validation@Pattern非ASCII兼容问题及Gradle域名验证异常求助
这个问题我之前也碰到过,核心原因是Hibernate Validator 6.x中@Pattern注解的正则默认没有启用Unicode字符类匹配模式,导致你写的\p{L}无法正确识别西里尔这类非ASCII Unicode字母。
为什么IDEA测试有效但Gradle运行不行?
IDEA自带的正则测试工具默认开启了Unicode字符类匹配(相当于隐含(?U)标志),所以你的正则能正确匹配西里尔域名。但Hibernate Validator在默认配置下,会使用Java正则的传统模式——这种模式下\p{L}只会匹配ASCII范围内的字母,对非ASCII的Unicode字符(比如西里尔字母)不生效,这就是Gradle测试失败的原因。
两种解决方法
方法1:在正则开头添加(?U)嵌入式标志
直接在你的正则表达式开头加上(?U),强制开启Unicode字符类匹配模式:
@Pattern( regexp = "(?U)((([\\p{L}0-9])+(-?[\\p{L}0-9])*)\\.)*[\\p{L}0-9](-?[\\p{L}0-9])+\\.\\p{L}{2,}" )
(?U)是Java正则的嵌入式标志,作用和Pattern.UNICODE_CHARACTER_CLASS一致,开启后\p{L}会正确匹配所有Unicode字母(包括西里尔、希腊等非ASCII字母)。
方法2:使用@Pattern.Flag指定UNICODE_CHARACTER_CLASS
如果你不想修改正则表达式,可以通过注解的flags参数显式启用Unicode字符类匹配:
@Pattern( regexp = "((([\\p{L}0-9])+(-?[\\p{L}0-9])*)\\.)*[\\p{L}0-9](-?[\\p{L}0-9])+\\.\\p{L}{2,}", flags = { Pattern.Flag.UNICODE_CHARACTER_CLASS } )
这种方式更清晰,不用在正则里嵌入标志,适合团队协作时让其他开发者一眼看到配置的匹配模式。
验证建议
修改后重新运行Gradle测试,应该就能正确验证西里尔域名了。如果还是有问题,可以检查下Hibernate Validator的版本是否确实是6.0.9.Final(这个版本完全支持UNICODE_CHARACTER_CLASS标志),或者有没有其他自定义的Validator配置覆盖了默认行为。
内容的提问来源于stack exchange,提问作者Donz

