天天看點

EL&JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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&JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

在上面的案例中,使用xxxxScope指定了擷取屬性值的作用域,其實xxxxScope是可以省略不寫的,例如:

    <h3>省略scope</h3>

    <ul>

       <li>page:${pageAttr }</li>

       <li>request:${requestAttr }</li>

       <li>session:${sessionAttr }</li>

       <li>application:${applicationAttr }</li>

    </ul>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

有一些特殊的不能省略的情況:

比如4個作用域中設定了相同屬性名稱的屬性

       //添加相同的屬性

       request.setAttribute("igeek", "requestIgeek");

       session.setAttribute("igeek", "sessionIgeek");

       application.setAttribute("igeek", "applicationIgeek");

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

擷取方式:

    <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&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

當指定作用域時,擷取的就是指定的作用域的屬性值。

當省略時,EL會預設從最小的作用域開始搜尋 , 找到為止。

正常的業務中不會出現不同作用域中設定相同名稱的屬性。是以一般情況下我們都是省略scope。

如果el中要擷取的資料不存在,就不顯示。

    <h3>擷取一個不存在或者為null的值</h3>

    <% pageContext.setAttribute("key", null); %>

    <ul>

       <li>不存在的值:${ndwl }</li>

       <li>為null的值:${key }</li>

    </ul>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

1.3EL表達式的禁用

在servlet2.0之前EL表達式是預設禁止的。

可以通過page指令中的屬性:isELIgnored  設定EL表達式是否被忽略。

預設是false,如果設定為true。效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面
EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

1.5EL擷取對象屬性的實質

         JavaBean規範中,成員變量必須是私有的。

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

         EL可以通過.直接擷取

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

看似直接擷取的,其實也是通過反射機制調用其getXxx方法擷取的。

修改brand中的getBrand的方法:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

再通路:錯誤  無法通路私有屬性brand

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

1.8在JS中使用EL表達式

由于el表達式使用$ 而在jquery中同樣使用$,此時如果在js中使用el表達式就出現沖突。

EL表達式可以使用在頁面的任何位置:比如:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面
EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

但是如果導入了jquery,jquery的$就會和El的$沖突:

<script type="text/javascript">

    $(document).ready(function(){

       console.log("${com.price}");

    });

</script>

解決方案就是将el表達式使用””包裹

效果:浏覽器中生成的代碼

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和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/

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

下載下傳後解壓:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

取出lib中的jar檔案添加在自己項目的classpath中,所謂classpath中就是添加到WEB-INF/lib中

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

在網頁中使用JSTL:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

關于uri和prefix屬性

檢視JSTLjar中的标簽描述檔案:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面
EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

标簽描述檔案中定義了JSTL标簽的相關的配置和使用方式。以及各種标簽的申明:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

其中的short-name就是此标簽的預設字首,當然在頁面可以通過profix修改:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

但不允許修改。

其中的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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

此标簽類似于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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

屬性:

Begin: 循環的起始值。

End:循環的結束之。

Step:步長。

Var:定義一個變量i,把每次循環的變量存儲在i中。

Varstatus:定義一個變量status,存儲每次循環的狀态。Status有循環的索引和循環的總數。

屬性中定義的var和varstatus都是預設存儲在page作用域中的屬性。是以可以通過el表達式直接擷取:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>

效果:

EL&amp;JSTL1 EL表達式2 JSTL 3.JSTL和EL表達式淨化頁面

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>