activiti的juel与tomcat的el冲突

最近在原来的SSH框架系统里集成了Activiti,基本没有遇到大的问题,一切运行正常,但是在访问一个页面时报错,如下:

java.lang.NullPointerException
	java.util.Objects.requireNonNull(Objects.java:203)
	javax.el.CompositeELResolver.add(CompositeELResolver.java:47)
	org.apache.jasper.el.ELContextImpl.<clinit>(ELContextImpl.java:87)
	org.apache.jasper.compiler.Validator$ValidateVisitor.prepareExpression(Validator.java:1619)
	org.apache.jasper.compiler.Validator$ValidateVisitor.visit(Validator.java:752)
	org.apache.jasper.compiler.Node$ELExpression.accept(Node.java:958)
	org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2389)
	org.apache.jasper.compiler.Node$Visitor.visitBody(Node.java:2441)
	org.apache.jasper.compiler.Node$Visitor.visit(Node.java:2447)
	org.apache.jasper.compiler.Node$Root.accept(Node.java:470)
	org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2389)
	org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1855)
	org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:223)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:384)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:361)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:345)
	org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:369)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)

经过百度,大体上是说tomcat的el-api.jar与Activiti的juel-api.jar、juel-impl.jar、juel-spi.jar冲突,把tomcat的el-api.jar删掉,把Activiti的juel相关jar复制到tomcat的lib里。于是乎,我就照做了,结果可想而知——没用!这次报错:

javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax/el/StaticFieldELResolver
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:338)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMe

额,反反复复试着删除、增加、更换jar包,都是徒劳,头大...这个juel是啥?与el有啥仇?又是一番百度,搜到了一段说明,如下:

EL --- JUEL

http://juel.sourceforge.net/index.html

Who, EL started as part of JSTL.

Then, EL into the JSP2.0 standards.

Now, while still JSP2.1 part, but the EL API has been isolated from the javax.el package, the removed core JSP classes for all dependency.

In other words, the EL is ready for use in non-JSP applications!

JUEL is the Unified Expression Language (EL) of an implementation,

Expressions have been given as part of the standard JSP2.1 was introduced into the JEE5.

Moreover, JUEL 2.2 has also achieved the JSP 2.2 specification to comply JEE6 the full specification.

看完这个,对这俩货有点概念了,EL是jsp的标准之一,但是从JSP2.1开始,EL Api从javax.el包中分离了出来,删除了对JSP相关类的依赖,这样就可以在Non-JSP环境中使用了。Activiti中的变量就是使用的EL表达式,但是,冲突在哪呢??

好吧,看看tomcat的el-api.jar的源码,再看看juel的源码,通过上面第一个报错,查看

javax.el.CompositeELResolver.add(CompositeELResolver.java:47)

这个方法,发现两者都调用这个方法,且包名相同,所以会冲突;

再查看调用关系,发现对ExpressionFactory抽象类的调用不同,tomcat的EL调用的是tomcat的org.apache.el.ExpressionFactoryImpl,而juel调用的是 de.odysseus.el.ExpressionFactoryImpl,原来如此,也就是说tomcat的EL和juel都只是满足自己解析表达式的需要,且因为使用了相同的包名(javax.el),不能同时使用,要么只能解析JSP中的EL表达式,要么只能解析Activiti中的EL表达式。

我的解决方案就是修改了Tomcat与EL相关的源码,把javax.el包改成了javax.jasper.el(你也可以改成其他的),重新打包,替换原来的el-api.jar,然后就可以与Activiti的juel.jar共存了,既能解析JSP中的EL表达式,也能解析Activiti中的EL表达式,终于解决!!!!!大笑



版权声明:本文为cmengzhongren原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。