解析Tomcat 6、7在EL表達式解析時存在的一個Bug
今天在做數據分頁顯示的時候遇到了一個問題,經過測試,證實是Tomcat 6的一個bug,我所用的版本為:apache-tomcat-6.0.36,和7.0.30均能復現。下面詳細描述一下這個bug:
該bug是在JSTL<c:forEach>標簽中發(fā)現的,后來分析是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),其他情況直接顯示分頁游標。在循環(huán)遍歷中只不過使用了最基本的條件判斷語句,由于pageList在定義中已經明確指出是List<String>,按邏輯應該eq是按照字符串判斷的,但是居然出異常了:
javax.el.ELException: Cannot convert ... of type class java.lang.String to class java.lang.Long
為什么會出現“類型轉換錯誤”呢?通過分析代碼走向,當進入循環(huán)后,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中發(fā)現無論是修改前還是修改后都能正常運行,可見,應該是tomcat的bug。
示例代碼:點擊下載
讓tomcat報錯的演示地址:/bug/show.do
避免此bug的方法演示地址:/bug/avoid.do
以上地址前可能需要加上項目名稱(具體取決于你如何部署該項目)
相關文章
探究springboot中的TomcatMetricsBinder
springboot的TomcatMetricsBinder主要是接收ApplicationStartedEvent然后創(chuàng)建TomcatMetrics執(zhí)行bindTo進行注冊,TomcatMetrics主要注冊了globalRequest、servlet、cache、threadPool、session相關的指標,本文給大家介紹的非常詳細,需要的朋友參考下吧2023-11-11
SpringBoot + FFmpeg實現一個簡單的M3U8切片轉碼系統(tǒng)
使用大名鼎鼎的ffmpeg,把視頻文件切片成m3u8,并且通過springboot,可以實現在線的點播。2021-05-05
Java 中POI 導入EXCEL2003 和EXCEL2007的實現方法
這篇文章主要介紹了Java 中POI 導入EXCEL2003 和EXCEL2007的實現方法的相關資料,希望通過本文大家能掌握理解這種方法,需要的朋友可以參考下2017-09-09
Windows安裝Maven并配置環(huán)境的詳細步驟
Maven是一個非常流行的構建和項目管理工具,用于Java開發(fā),它提供了一個強大的依賴管理系統(tǒng)和一系列標準化的構建生命周期,本文將指導您如何在Windows操作系統(tǒng)上安裝和配置Maven,需要的朋友可以參考下2023-05-05

