解析Tomcat 6、7在EL表达式解析时存在的一个Bug_java

今天在做数据分页显示的时候遇到了一个问题,经过测试,证实是Tomcat 6的一个bug,我所用的版本为:apache-tomcat-6.0.36,和7.0.30均能复现。下面详细描述一下这个bug:

该bug是在JSTL<c:forEach>标签中发现的,后来分析是EL表达式实现时产生的问题。jsp页面中有一个list需要遍历,这个list的类型为ArrayList<String>,我在其中放置的数据为(为方便我写成数组的形式):["1","...","4","5","6","7","8","...","10"],这是一个很常见的带页码缩略的分页导航。在展示这些数据的时候我使用了下面的代码:

复制代码 代码如下:

<c:forEach var="looper" items="${pageHelper.pageList}">
 <c:choose>
  <c:when test="${looper eq pageHelper.pageDot}">
  <p>分页游标的 点点点</p>
  </c:when>
  <c:when test="${looper eq pageHelper.pageNo}">
  <p>当前页为第${looper}页面</p>
  </c:when>
  <c:otherwise>
  <p>分页游标:${looper}</p>
  </c:otherwise>
 </c:choose>
</c:forEach>

这里pageHelper就是分页组件,其中预设了pageDot为"...",pageNo为当前的页码(假设为6),其他情况直接显示分页游标。在循环遍历中只不过使用了最基本的条件判断语句,由于pageList在定义中已经明确指出是List<String>,按逻辑应该eq是按照字符串判断的,但是居然出异常了:

复制代码 代码如下:

javax.el.ELException: Cannot convert ... of type class java.lang.String to class java.lang.Long

为什么会出现“类型转换错误”呢?通过分析代码走向,当进入循环后,list中的第一条数据是“1”,而pageHelper.pageNo为long型,此时tomcat的EL表达式解析器会把looper类型转换为Long型而不是把pageHelper.pageNo类型转换为String进行比较,当遍历到下一元素时,looper="...",这时looper的类型已经确定,比较的时候tomcat还要试图将looper转换为Long类型,于是就出错了。

为此我专门写了一个实例代码:

复制代码 代码如下:

<c:forEach var="looper" items="${pageHelper.pageList}">
 <c:choose>
  <c:when test="${looper eq fn:trim(pageHelper.pageDot)}">
  <p>分页游标的 点点点</p>
  </c:when>
  <c:when test="${looper eq fn:trim(pageHelper.pageNo)}">
  <p>当前页为第${looper}页面</p>
  </c:when>
  <c:otherwise>
  <p>分页游标:${looper}</p>
  </c:otherwise>
 </c:choose>
</c:forEach>

很简单,每次比较的时候都把后者用fn:trim方法进行去除左右非可见字符。相当于强制转换为String类型,此时tomcat又可以正常解析代码,并未报错。

同样的一套代码,我将其部署到resin中发现无论是修改前还是修改后都能正常运行,可见,应该是tomcat的bug。

示例代码:点击下载

让tomcat报错的演示地址:/bug/show.do

避免此bug的方法演示地址:/bug/avoid.do

以上地址前可能需要加上项目名称(具体取决于你如何部署该项目)

时间: 2024-09-20 21:26:18

解析Tomcat 6、7在EL表达式解析时存在的一个Bug_java的相关文章

el表达式-EL表达式解析错误,页面无法展示

问题描述 EL表达式解析错误,页面无法展示 以下的jsp代码中,在Linux服务器上部署工程出现: <c:if test="${switch == 0 || switch == 1}">解析错误!页面无法正常展示,是语法错误吗? <center> <c:set var="switch" scope="session" value="${scoreCleanIp }"/> <c:if t

Tomcat5发布项目问题(2):默认不解析EL表达式

Tomcat 5.5使EL表达式不被解析.  现象 代码${userSession.user_name}是JSP中的一个代码片段: 如果部署到tomcat5.5中,不会显示出session中的变量user用户名,而只会把 ${userSession.user_name}打印出来,猜测很可能是tomcat5.5的bug,不解析(或屏蔽了)EL表达式.  原因 如果web.xml中声明部分的schema版本为2.5或者以上,而tomcat使用的是5.5.x以下的版本的时候就会出现在页面直接显示而不解

Taglib原理和实现之支持El表达式

1.先看这么一个例子 <%@ page contentType="text/html; charset=gb2312" language="java"%><%@ taglib uri="/WEB-INF/tlds/c.tld" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" &

JSP EL表达式详细介绍

一.JSP EL语言定义 E L(Expression Language) 目的:为了使JSP写起来更加简单. 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法.它是一种简单的语言,基于可用的命名空间(PageContext 属性).嵌套属性和对集合.操作符(算术型.关系型和逻辑型)的访问符.映射到 Java 类中静态方法的可扩展函数以及一组隐式对象. EL 提供了在 JSP 脚本编制元素范围外使用运行时表达式的功能.脚本编制元素是

el表达式里面fn的用法

头部加入标签库  <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>  使用:  截取字符串长多  ${fn:substring(wjcd.lrsj, 0, 16)}  使用 functions函数来获取list 的长度  ${fn:length(list)}  函数名 函数说明 使用举例 fn:contains 判断字符串是否包含另外一个字符串 <c:if

EL表达式概述

E L(Expression Language) 目的:为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法. 禁用EL表达式的3种方式 1.语法结构 ${expression} 2.[ ]与.运算符 EL 提供"."和"[ ]"两种运算符来存取数据. 当要存取的属性名称中包含一些特殊字符,如 . 或 - 等并非字母或数字的符号,就一定要使用"[ ]".例如:

EL表达式入门必看篇(推荐)_JSP编程

为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法. JSP EL语言定义 E L(Expression Language)目的:为了使JSP写起来更加简单. 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法.它是一种简单的语言,基于可用的命名空间(PageContext 属性).嵌套属性和对集合.操作符(算术型.关系型和逻辑型)的访问符.映射

JSP EL表达式详细介绍_JSP编程

一.JSP EL语言定义         E L(Expression Language)  目的:为了使JSP写起来更加简单.        表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法.它是一种简单的语言,基于可用的命名空间(PageContext 属性).嵌套属性和对集合.操作符(算术型.关系型和逻辑型)的访问符.映射到 Java 类中静态方法的可扩展函数以及一组隐式对象.        EL 提供了在 JSP 脚本编制元

运用El表达式截取字符串/获取list的长度

${fn:substring(wjcd.lrsj, 0, 16)} 使用functions函数来获取list的长度 ${fn:length(list)}     <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>   函数名 函数说明 使用举例 fn:contains 判断字符串是否包含另外一个字符串 <c:if test="${fn:contain