前几天上线的一个内容,其中一个环节对json格式的字符串进行了参数校验,为了避免写重复的校验代码,使用了hibernate-validator的注解校验功能
添加的依赖如下:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
在开发、测试环境,都可以正常使用,在生产环境竟然报错了。。使用校验时直接报错了。完整的错误信息如下:
javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:206)
at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:94)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.getDefaultMessageInterpolator(AbstractConfigurationImpl.java:570)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.getDefaultMessageInterpolatorConfiguredWithClassLoader(AbstractConfigurationImpl.java:790)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.getMessageInterpolator(AbstractConfigurationImpl.java:480)
at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.<init>(ValidatorFactoryImpl.java:151)
at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:38)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.buildValidatorFactory(AbstractConfigurationImpl.java:430)
查询网上大部分说的都是缺少依赖,添加hibernate-validator的依赖。
但是我的依赖包hibernate-validator-6.1.5.Final.jar、javax.el-3.0.0.jar都有的,而且版本也没有问题。
最后经过一位同事提醒,是不是有相同的类冲突了。
最后经过查找发现,第三方的依赖包,还存在一个el-api.jar,这个包中也有一个“javax.el.ExpressionFactory”类,全路径一模一样
el-api.jar中的“javax.el.ExpressionFactory”如下图:
javax.el-3.0.0.jar中的“javax.el.ExpressionFactory”如下图:
所以说,根本原因还是两个类重名导致类冲突。由于JVM类的加载顺序不一定,在开发环境与测试环境先加载的javax.el-3.0.0.jar,因此使用注解进行参数校验可以正常使用。但是生产环境先加载了el-api.jar,一使用注解进行校验就出现“Unable to initialize ‘javax.el.ExpressionFactory’”错误
另外,如果你找不到是与哪个包中的类冲突了,在linux主机上,第三方包的文件夹下,执行如下命令即可
参考链接: link.
find / -name "*.jar" -exec grep -Hsli 类名 {} \;
find . -name "*.jar" -exec grep -Hsli 'javax.el.ExpressionFactory' {} \;
如下是我的搜索结果
既然找到问题,那么就容易解决了。
方式一:如果有把握,直接删除el-api.jar包或依赖即可;
方式二:如果没把握,可以改动启动i脚本,在进程启动时优先加载 javax.el-3.0.0.jar
我使用的第二种方式,重新启动,完美解决
LIB=".:${FPATH}/lib/javax.el-3.0.0.jar:${FPATH}/lib/*:${FPATH}/core/*:${FPATH}/blib/*.jar"