当前位置: 代码迷 >> JavaScript >> 解决JSP2.1规范对EL表达式的兼容性有关问题
  详细解决方案

解决JSP2.1规范对EL表达式的兼容性有关问题

热度:468   发布时间:2012-08-31 12:55:03.0
解决JSP2.1规范对EL表达式的兼容性问题

在使用jetty插件(6.1.9)调试过程中,发现访问一个带有#{…}表达式的页面(页面用到了模板表达式)时,抛出如下异常:?

Java代码??收藏代码
  1. org.apache.jasper.JasperException:?/WEB-INF/jsps/projectmt/formProjectLaunching.jsp(677,22)?PWC6228:?#{...}?not?allowed?in?a?template?text?body.??
  2. ????at?org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:62)??
  3. ????at?org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:357)??
  4. ????at?org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:169)??
  5. ????at?org.apache.jasper.compiler.Validator$ValidateVisitor.visit(Validator.java:731)??
  6. ????at?org.apache.jasper.compiler.Node$ELExpression.accept(Node.java:929)??
  7. ????at?org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2257)??
  8. ????at?org.apache.jasper.compiler.Node$Visitor.visitBody(Node.java:2307)??
  9. ????...??

而将项目打包并部署到tomcat(5.5)中运行时,并没有发现该异常。?

根据以上的异常信息,经过一番网络搜索,发现原来是JSP2.1规范对#{…}的兼容性问题:?
引用

Prior to JSP 2.1, the #{} syntax was not reserved. Therefore, there might exist JSP pages based on earlier versions of JSP technology that use the #{ characters where they are not allowed, according to the JSP 2.1 specification. These pages, when used in a JSP 2.1 application, will generate a translation error.?


其实,?
?? 1. 在JSP2.1以前,JSP编译器并不解析#{}表达式(不是保留的表达式),因为在之前的JSP中,EL表达式是${}来表示的;?
?? 2. 正因为#{}不是JSP保留的表达式,所以在JSF中,EL表达式采用了#{}表示的;?
?? 3. 同时,在Struts2中,OGNL(Object-Graph Navigation Language,一种功能强大的表达式语言)也是用#{}表示的;?
?? 4. 而在JSP2.1规范中,SUN为了统一JSP与JSF的EL表达式语法,将#{}作为了保留的表达式(SUN号称在纯jsp中也能够直接引用JSF的managedBean),也就是说,采用JSP2.1规范的服务器会自动编译#{}表达式;?
?? 5. jetty6和tomcat6采用的JSP2.1规范,而jetty5和tomcat5采用的是JSP2.0规范。?

OK,问题似乎明朗了,使用jetty5和tomcat5就不会出现这个jsp编译错误。那么,如果我们需要使用jetty6或者tomcat6呢??

在采用JSP2.1规范的服务器(如jetty6和tomcat6)中,我们有两种方案来解决这个EL表达式的兼容问题:?
?? 方案一:在web项目的web.xml中增加如下配置:?
Java代码??收藏代码
  1. <jsp-property-group>??
  2. ????<url-pattern>*.jsp</url-pattern>??
  3. ????<deferred-syntax-allowed-as-literal>true</deferred-syntax-allowed-as-literal>??
  4. </jsp-property-group>??

这需要使用servlet2.5规范,所以同时必须将web-app节点配置修改为:?
Java代码??收藏代码
  1. <web-app?id="KSOA3"?version="2.5"?xmlns="http://java.sun.com/xml/ns/j2ee"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
  2. ????xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee?http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">??

?? 方案二:在使用了#{}表达式的jsp文件中,在@page中增加deferredSyntaxAllowedAsLiteral="true":?
Java代码??收藏代码
  1. <%@?page?contentType="text/html;?charset=UTF-8"?deferredSyntaxAllowedAsLiteral="true"%>??

?

方案三:在使用了#{}表达式的jsp文件中,?

step1.在页面定义字符串变量;
step2.把需要#的位置用刚才定义的变量替换;

?<%?
?String?a??
=???"?#?"?;?
?
%>?

?

由于方案一只需要修改一处配置,维护成本较低,所以推荐使用方案一。?

使用了以上解决方案后,在采用JSP2.1规范的服务器中,一切运行正常。但由于采用JSP2.0规范的服务器(如tomcat5或jetty5)不能识别以上的这些配置信息,所以,如果在采用JSP2.0规范的服务器中也使用了这些配置,结果会很严重:?
?? 1. JSP页面中的${}表达式不会被编译?
?? 2. 使用了#{}表达式的jsp页面渲染不成功?

到目前为止,还没有既适合JSP2.1,又能兼容JSP2.0的配置,所以只能根据服务器采用的JSP规范版本来进行相应的配置。?

参考: http://today.java.net/pub/a/today/2006/03/07/unified-jsp-jsf-expression-language.html#backwards-compatibility