时间:2021-05-19
今天在做数据分页显示的时候遇到了一个问题,经过测试,证实是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
以上地址前可能需要加上项目名称(具体取决于你如何部署该项目)
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
表达式意义:1.字符x字符x。例如a表示字符a\\反斜线字符。在书写时要写为\\\\。(注意:因为java在第一次解析时,把\\\\解析成正则表达式\\,在第二
JavaScript中的正则表达式解析正则表达式(regularexpression)对象包含一个正则表达式模式(pattern)。它具有用正则表达式模式去匹配
下面一段代码给大家介绍了angularjs手动解析表达式($parse),具体代码如下所示:手动解析表达式($parse){{parsedValue}}angu
在spring的一个controller中要把参数传到页面,只要配置视图解析器,把参数添加到Model中,在页面用el表达式就可以取到。但是,这样使用的是for
列表解析在需要改变列表而不是需要新建某列表时,可以使用列表解析。列表解析表达式为:[exprforiter_variniterable][exprforiter