用户名校验写成 ^\w{2,12}$,接口对 张三 返回 400,对 zhangsan 正常。日志里 pattern 原样打印出来,看不出哪里写错了。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,Java 的 \w 默认只覆盖 [a-zA-Z_0-9],中文不在这个集合里。要匹配 Unicode 字母得打开 UNICODE_CHARACTER_CLASS,或者显式写 \p{L}。
碰到「正则匹配中文」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
jshell <<'EOF'
System.out.println("张三".matches("\\w{2,12}"));
System.out.println("张三".matches("[\\p{L}]{2,12}"));
EOF
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
具体做法是,把 \w 换成 \p{L} 或按业务限定到汉字区;编译 Pattern 时加 Pattern.UNICODE_CHARACTER_CLASS;长度按码位计算 别用 length() 数 UTF-16 单元;中文 英文 中英混合三种用户名都加进用例。
最后用这个标准收尾,张三 返回 200 英文名和带下划线的老用户名也照常通过。
