1 EL表達式
1.1概念
EL(Expression Language) 是為了使JSP寫起來更加簡單。表達式語言的靈感來自于 ECMAScript 和 XPath 表達式語言,它提供了在 JSP 中簡化表達式的方法,讓Jsp的代碼更加簡化。
從4個作用域中擷取資料.
1.2從4個作用域中擷取資料
回顧4個作用域
Application > session >request >page
Application session request pageContext
通過4個對象可以使用setAttribute(String attrName,Object attrValue)方法給作用域設定屬性。通過getAttribute(String attrName) 從4個作用域中擷取資料;
将servlet中查詢的資料傳遞到頁面:在servlet中擷取資料,将資料設定到request作用域中。在JSP頁面通過request對象取出。
EL表達式可以在不使用java腳本的情況下從4個作用域中取出資料。
文法: ${expression} expression可以是表達式,也可以是作用域中的屬性的名稱。
案例:
在servlet中向4個作用域中添加屬性,在頁面通過EL取出。
添加servlet
public class ElServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //分别向4個作用域中添加屬性 //pageContext對象無法在這裡網頁面的page作用域中添加屬性。 request.setAttribute("requestAttr", "這是request的屬性值"); HttpSession session = request.getSession(); session.setAttribute("sessionAttr", "這是session的屬性值"); ServletContext application = this.getServletContext(); application.setAttribute("applicationAttr", "這是applilcation的屬性值"); //轉發進入el.jsp request.getRequestDispatcher("el.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
JSP頁面:
<div> <%pageContext.setAttribute("pageAttr", "這是page作用域中的屬性值"); %> <h2>取出4個作用域的資料</h2> <ul> <li>page:${pageScope.pageAttr }</li> <li>request:${requestScope.requestAttr }</li> <li>session:${sessionScope.sessionAttr }</li> <li>application:${applicationScope.applicationAttr }</li> </ul> </div> |
效果:
在上面的案例中,使用xxxxScope指定了擷取屬性值的作用域,其實xxxxScope是可以省略不寫的,例如:
<h3>省略scope</h3> <ul> <li>page:${pageAttr }</li> <li>request:${requestAttr }</li> <li>session:${sessionAttr }</li> <li>application:${applicationAttr }</li> </ul> |
效果:
有一些特殊的不能省略的情況:
比如4個作用域中設定了相同屬性名稱的屬性
//添加相同的屬性 request.setAttribute("igeek", "requestIgeek"); session.setAttribute("igeek", "sessionIgeek"); application.setAttribute("igeek", "applicationIgeek"); |
擷取方式:
<h3>取出相同屬性名的屬性值</h3> <ul> <li>省略score的取值方式:${igeek }</li> <li>page的取值方式:${pageScope.igeek }</li> <li>request的取值方式:${requestScope.igeek }</li> <li>session的取值方式:${sessionScope.igeek }</li> <li>application的取值方式:${applicationScope.igeek }</li> </ul> |
效果:
當指定作用域時,擷取的就是指定的作用域的屬性值。
當省略時,EL會預設從最小的作用域開始搜尋 , 找到為止。
正常的業務中不會出現不同作用域中設定相同名稱的屬性。是以一般情況下我們都是省略scope。
如果el中要擷取的資料不存在,就不顯示。
<h3>擷取一個不存在或者為null的值</h3> <% pageContext.setAttribute("key", null); %> <ul> <li>不存在的值:${ndwl }</li> <li>為null的值:${key }</li> </ul> |
效果:
1.3EL表達式的禁用
在servlet2.0之前EL表達式是預設禁止的。
可以通過page指令中的屬性:isELIgnored 設定EL表達式是否被忽略。
預設是false,如果設定為true。效果:
1.4通過EL表達式通路對象的屬性
EL表達式可以通過”.”或者[“attrName”]通路對象的屬性。
案例:
建立一個Computer類:
public class Computer { private String brand; private double price; private MainBoard board; } |
添加主機闆類:
public class MainBoard { private String brand; private int size; } |
在serlvet中建立主機闆對象放入request:
//建立主機闆對象 MainBoard board = new MainBoard("華碩", 56); request.setAttribute("board", board); |
JSP中的擷取
<h3>擷取一個對象的屬性值</h3> <ul> <li>擷取主機闆對象:${board }</li> <li>.擷取主機闆的品牌:${board.brand }</li> <li>[]擷取主機闆的品牌:${board["brand"] }</li> </ul> |
效果:
1.5EL擷取對象屬性的實質
JavaBean規範中,成員變量必須是私有的。
EL可以通過.直接擷取
看似直接擷取的,其實也是通過反射機制調用其getXxx方法擷取的。
修改brand中的getBrand的方法:
再通路:錯誤 無法通路私有屬性brand
1.6EL通路屬性可以多層導航
比如:
在servlet添加一個computer,在頁面中通路電腦的主機闆的品牌。
Servlet
//建立主機闆對象 MainBoard board = new MainBoard("華碩", 56); request.setAttribute("board", board); //建立電腦對象 Computer com = new Computer("聯想", 8000); com.setBoard(board); request.setAttribute("com", com); |
JSP
<h3>擷取一個對象的屬性的屬性</h3> <ul> <li>擷取電腦對象:${com }</li> <li>擷取電腦的主機闆:${com.board }</li> <li>擷取電腦的主機闆的主機闆的品牌:${com.board.brand }</li> </ul> |
效果:
1.7EL表達式中的運算符
回顧運算符:
算術運算符,關系運算符,邏輯運算符。
這些運算符在EL中同樣适用。
<h3>EL的運算符</h3> <ul> <li>算術運算符1:${1+1 }</li> <li>算術運算符2:${board.size+100 }</li> <li>關系運算符:${com.price > 6000 }</li> <li>邏輯運算符:${com.price>6000 && com.price < 10000 } <li>三目運算:${com==null?"沒有電腦":com.brand }</li> </ul> |
效果:
1.8在JS中使用EL表達式
由于el表達式使用$ 而在jquery中同樣使用$,此時如果在js中使用el表達式就出現沖突。
EL表達式可以使用在頁面的任何位置:比如:
效果:
但是如果導入了jquery,jquery的$就會和El的$沖突:
<script type="text/javascript"> $(document).ready(function(){ console.log("${com.price}"); }); </script> |
解決方案就是将el表達式使用””包裹
效果:浏覽器中生成的代碼
2 JSTL
2.1概述
JSTL(JavaServer Pages Standard Tag Library,JSP标準标簽庫)是一個不斷完善的開放源代碼的JSP标簽庫,是由apache的jakarta小組來維護的。JSTL隻能運作在支援JSP1.2和Servlet2.3規範的容器上,如tomcat 4.x。在JSP 2.0中也是作為标準支援的。
JSTL 1.0 釋出于 2002 年 6 月,由四個定制标記庫(core、format、xml 和 sql)和一對通用标記庫驗證器(ScriptFreeTLV 和 PermittedTaglibsTLV)組成。core 标記庫提供了定制操作,通過限制了作用域的變量管理資料,以及執行頁面内容的疊代和條件操作。它還提供了用來生成和操作 URL 的标記。顧名思義,format 标記庫定義了用來格式化資料(尤其是數字和日期)的操作。它還支援使用本地化資源束進行 JSP 頁面的國際化。xml 庫包含一些标記,這些标記用來操作通過 XML 表示的資料,而 sql 庫定義了用來查詢關系資料庫的操作。
如果要使用JSTL,則必須将jstl.jar和 standard.jar檔案放到classpath中,如果你還需要使用XML processing及Database access (SQL)标簽,還要将相關JAR檔案放到classpath中,這些JAR檔案全部存在于下載下傳回來的zip檔案中。
JSTL就是用來處理EL表達式取出的資料的。
2.2JSTL的安裝
下載下傳:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
下載下傳後解壓:
取出lib中的jar檔案添加在自己項目的classpath中,所謂classpath中就是添加到WEB-INF/lib中
在網頁中使用JSTL:
關于uri和prefix屬性
檢視JSTLjar中的标簽描述檔案:
标簽描述檔案中定義了JSTL标簽的相關的配置和使用方式。以及各種标簽的申明:
其中的short-name就是此标簽的預設字首,當然在頁面可以通過profix修改:
但不允許修改。
其中的uri屬性相當于此标簽的唯一辨別符。在頁面引用時需要在uri中申明。
2.3核心标簽庫中的c:set,c:out,c:remove
C:set 相當于 xxx.setAttribute();
<c:set var="igeek" value="igeekhome" scope="page"/> ${igeek } |
屬性 var :屬性的名稱 value :屬性值,可以使用el表達式
Score:是作用域。
C:out 相當于 <%= xx %>
<c:out value="${igeek }" /> |
屬性value:要展示的資料,可以使用el表達式
C:remove 相當于xxx.removeAttribute();
<c:remove var="igeek"/> |
屬性var就要删除的作用域中的屬性名稱
2.4核心标簽庫中的if标簽
文法: <c:if test=”” var=””></if>
<c:set var="igeek" value="80" > <c:if test="${igeek>70 }" var="result" scope="page"/> igeek屬性是大于70的 </c:if> |
當test屬性的值為true就執行if标簽内部的程式。
其中屬性var是說建立一個變量result存儲test比較的結果.
Scope屬性是配置result變量存儲的作用域。
效果:
2.5 c:choose,c:when,c:other wise
案例:
<div> <c:set var="igeek" value="60"/> <c:choose> <c:when test="${igeek>70 }"> igeek屬性是大于70的 </c:when> <c:when test="${igeek>80 }"> igeek屬性是大于80的 </c:when> <c:otherwise> igeek是其他情況 </c:otherwise> </c:choose> </div> |
效果:
此标簽類似于java中的
If .. else if .. else if ….else
2.6 c:foreach
用來循環的标簽,類似于java中的for和foreach
使用foreac做循環
案例:
<div>for 循環 <ul> <c:forEach begin="1" end="11" step="2" var="i" varStatus="status" > <li>Item ${i }--${status.index }--${status.count }</li> </c:forEach> </ul> </div> |
效果:
屬性:
Begin: 循環的起始值。
End:循環的結束之。
Step:步長。
Var:定義一個變量i,把每次循環的變量存儲在i中。
Varstatus:定義一個變量status,存儲每次循環的狀态。Status有循環的索引和循環的總數。
屬性中定義的var和varstatus都是預設存儲在page作用域中的屬性。是以可以通過el表達式直接擷取:
其中i就是循環的值,status.index就是循環的索引,status.count就是循環的總數量。
使用foreach周遊清單
<div>使用foreach周遊清單</div> <% List<String> sts = new ArrayList<String>(); sts.add("張三");sts.add("李四");sts.add("王五"); sts.add("卡卡西");sts.add("鳴人");sts.add("佐助"); pageContext.setAttribute("sts", sts); %> <c:forEach items="${sts }" var="s" varStatus="status"> <p>${status.index }.${s }--${status.count }</p> </c:forEach> |
效果:
Tips:items是設定要周遊的清單的,一般都是通過el表達式擷取作用域中的集合。切記不能忘記$ items中{}以外不能有空格。
Foreach周遊資料類型:collection. 數組。
2.7 c:fortokens
用來分割循環的
案例:
<h3>forTokens</h3> <div> <c:set var="igeek" value="igeek is a NB 的機構"/> <c:forTokens items="${igeek }" delims=" " var="s" varStatus="status"> <p>${status.index }.${s }</p> </c:forTokens> </div> |
效果:
2.8日期格式化标簽
格式化标簽在格式化标簽庫中
在頁面引用格式化标簽庫:
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> |
格式化日期:
<h3>fmt:formatDate</h3> <div> <c:set var="now" value="${date }"/> <ul> <li>不格式化:${now }</li> <li>格式化日期(type=date):<fmt:formatDate type="date" value="${now }"/></li> <li>格式化日期(type=time):<fmt:formatDate type="time" value="${now }"/></li> <li>格式化日期(type=BOTH):<fmt:formatDate type="BOTH" value="${now }"/></li> <li>格式化日期(timeStyle=short):<fmt:formatDate dateStyle="short" type="BOTH" timeStyle="short" value="${now }"/></li> <li>格式化日期(timeStyle=long):<fmt:formatDate dateStyle="long" type="BOTH" timeStyle="long" value="${now }"/></li> <li>自定義格式化(patten):<fmt:formatDate type="BOTH" pattern="yyyy年MM月dd日 HH:mm:ss" value="${now }"/></li> </ul> </div> |
效果:
2.9日期解析标簽
parseDate 用于将字元串形式的日期轉換為date
<h3>fmt:formatDate</h3> <div> <c:set var="now" value="2018-5-25 12:45:56"/> <fmt:parseDate var="n" value="${now }" pattern="yyyy-MM-dd HH:mm:ss"/> ${n } </div> |
效果:
3.JSTL和EL表達式淨化頁面
将前面的BBS項目中的list頁面進行淨化
[1]添加jar檔案
[2]在list.jsp中引用核心标簽庫和格式化标簽庫
[3]修改頁面代碼。判斷資料是否存在:
<c:if test="${board==null }"> <!-- 重定向到首頁 --> <c:redirect url="index.jsp"/> </c:if> |
[4]修改頁面。判斷使用者登入狀态
<%--判斷是否登入 --%> <c:choose> <c:when test="${loginUser ==null }"> [<a href="reg.jsp">注冊</a>] [<a href="login.jsp">登入</a>] </c:when> <c:otherwise> 歡迎您${loginUser.nickName } <a class="btn btn-default" href="inputPost?boardId=${board.boardId }">快速發帖</a> </c:otherwise> </c:choose> |
[5]修改頁面。判斷文章資料是否存在
<c:if test="${topics==null }"> <tr> <td colspan="3"> 該闆塊暫時沒有任何話題 </td> </tr> </c:if> |
[6]修改頁面。使用foreach周遊集合
<c:if test="${topics!=null }"> <c:forEach items="${topics }" var="t"> <tr> <td>${t.topicId }</td> <td> <a href="detail?topicId=${t.topicId }">${t.title }</a> </td> <td>${t.createTime }</td> </tr> </c:forEach> </c:if> |