Java Web複習(12)EL表示式jstl標籤庫
1 EL概述
1.1 EL的作用
JSP2.0要把html和css分離、要把html和javascript分離、要把Java指令碼替換成標籤。標籤的好處是非Java人員都可以使用。
JSP2.0 – 純標籤頁面,即:不包含<% … %>、<%! … %>,以及<%= … %>
EL(Expression Language)是一門表示式語言,它對應<%=…%>。我們知道在JSP中,表示式會被輸出,所以EL表示式也會被輸出。
1.2 EL的格式
格式:${…}
例如:${1 + 2}
1.3 關閉EL
如果希望整個JSP忽略EL表示式,需要在page指令中指定isELIgnored=”true”。
如果希望忽略某個EL表示式,可以在EL表示式之前新增“\”,例如:\${1 + 2}。
1.4 EL運算子
運算子 | 說明 | 範例 | 結果 |
+ | 加 | ${17+5} | 22 |
- | 減 | ${17-5} | 12 |
* | 乘 | ${17*5} | 85 |
/或div | 除 | ${17/5}或${17 div 5} | 3 |
%或mod | 取餘 | ${17%5}或${17 mod 5} | 2 |
==或eq | 等於 | ${5==5}或${5 eq 5} | true |
!=或ne | 不等於 | ${5!=5}或${5 ne 5} | false |
<或lt | 小於 | ${3<5}或${3 lt 5} | true |
>或gt | 大於 | ${3>5}或${3 gt 5} | false |
<=或le | 小於等於 | ${3<=5}或${3 le 5} | true |
>=或ge | 大於等於 | ${3>=5}或${3 ge 5} | false |
&&或and | 並且 | ${true&&false}或${true and false} | false |
!或not | 非 | ${!true}或${not true} | false |
||或or | 或者 | ${true||false}或${true or false} | true |
empty | 是否為空 | ${empty “”},可以判斷字串、資料、集合的長度是否為0,為0返回true。empty還可以與not或!一起使用。${not empty “”} | true |
1.5 EL不顯示null
當EL表示式的值為null時,會在頁面上顯示空白,即什麼都不顯示。
2 EL表示式格式
先來了解一下EL表示式的格式!現在還不能演示它,因為需要學習了EL11個內建物件後才方便顯示它。
l 操作List和陣列:${list[0]}、${arr[0]};
l 操作bean的屬性:${person.name}、${person[‘name’]},對應person.getName()方法;
l 操作Map的值:${map.key}、${map[‘key’]},對應map.get(key)。
3 EL內建物件
EL一共11個內建物件,無需建立即可以使用。這11個內建物件中有10個是Map型別的,最後一個是pageContext物件。
l pageScope
l requestScope
l sessionScope
l applicationScope
l param;
l paramValues;
l header;
l headerValues;
l initParam;
l cookie;
l pageContext;
3.1 域相關內建物件(重點)
域內建物件一共有四個:
l pageScope:${pageScope.name}等同與pageContext.getAttribute(“name”);
l requestScope:${requestScope.name}等同與request.getAttribute(“name”);
l sessionScoep: ${sessionScope.name}等同與session.getAttribute(“name”);
l applicationScope:${applicationScope.name}等同與application.getAttribute(“name”);
如果在域中儲存的是JavaBean物件,那麼可以使用EL來訪問JavaBean屬性。因為EL只做讀取操作,所以JavaBean一定要提供get方法,而set方法沒有要求。
Person.java
publicclass Person { private String name; privateintage; private String sex; public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } publicint getAge() { returnage; } publicvoid setAge(int age) { this.age = age; } public String getSex() { returnsex; } publicvoid setSex(String sex) { this.sex = sex; } } |
全域查詢:${person}表示依次在pageScope、requesScopet、sessionScope、appliationScope四個域中查詢名字為person的屬性。
3.2 請求引數相關內建物件
param和paramValues這兩個內建物件是用來獲取請求引數的。
l param:Map<String,String>型別,param物件可以用來獲取引數,與request.getParameter()方法相同。
注意,在使用EL獲取引數時,如果引數不存在,返回的是空字串,而不是null。這一點與使用request.getParameter()方法是不同的。
l paramValues:paramValues是Map<String, String[]>型別,當一個引數名,對應多個引數值時可以使用它。
3.3 請求頭相關內建物件
header和headerValues是與請求頭相關的內建物件:
l header:Map<String,String>型別,用來獲取請求頭。
l headerValues:headerValues是Map<String,String[]>型別。當一個請求頭名稱,對應多個值時,使用該物件,這裡就不在贅述。
3.4 應用初始化引數相關內建物件
l initParam:initParam是Map<String,String>型別。它對應web.xml檔案中的<context-param>引數。
3.5 Cookie相關內建物件
l cookie:cookie是Map<String,Cookie>型別,其中key是Cookie的名字,而值是Cookie物件本身。
3.6 pageContext物件
pageContext:pageContext是PageContext型別!可以使用pageContext物件呼叫getXXX()方法,例如pageContext.getRequest(),可以${pageContext.request}。也就是讀取JavaBean屬性!!!
EL表示式 | 說明 |
${pageContext.request.queryString} | pageContext.getRequest().getQueryString(); |
${pageContext.request.requestURL} | pageContext.getRequest().getRequestURL(); |
${pageContext.request.contextPath} | pageContext.getRequest().getContextPath(); |
${pageContext.request.method} | pageContext.getRequest().getMethod(); |
${pageContext.request.protocol} | pageContext.getRequest().getProtocol(); |
${pageContext.request.remoteUser} | pageContext.getRequest().getRemoteUser(); |
${pageContext.request.remoteAddr} | pageContext.getRequest().getRemoteAddr(); |
${pageContext.session.new} | pageContext.getSession().isNew(); |
${pageContext.session.id} | pageContext.getSession().getId(); |
${pageContext.servletContext.serverInfo} | pageContext.getServletContext().getServerInfo(); |
EL函式庫
1 什麼EL函式庫
EL函式庫是由第三方對EL的擴充套件,我們現在學習的EL函式庫是由JSTL新增的。JSTL明天再學!
EL函式庫就是定義一些有返回值的靜態方法。然後通過EL語言來呼叫它們!當然,不只是JSTL可以定義EL函式庫,我們也可以自定義EL函式庫。
EL函式庫中包含了很多對字串的操作方法,以及對集合物件的操作。例如:${fn:length(“abc”)}會輸出3,即字串的長度。
2 匯入函式庫
因為是第三方的東西,所以需要匯入。匯入需要使用taglib指令!
<%@ taglib prefix="fn"uri="http://java.sun.com/jsp/jstl/functions" %>
3 EL函式庫介紹
l String toUpperCase(String input):
l String toLowerCase(String input):
l int indexOf(String input, String substring):
l boolean contains(String input, String substring):
l boolean containsIgnoreCase(String input, String substring):
l boolean startsWith(String input, String substring):
l boolean endsWith(String input, String substring):
l String substring(String input, int beginIndex, int endIndex):
l String substringAfter(String input, String substring):hello-world, “-“
l substringBefore(String input, String substring):hello-world, “-“
l String escapeXml(String input):把字串的“>”、“<”。。。轉義了!
l String trim(String input):
l String replace(String input, String substringBefore, StringsubstringAfter):
l String[] split(String input, String delimiters):
l int length(Object obj):可以獲取字串、陣列、各種集合的長度!
l String join(String array[], String separator):
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> … String[] strs = {"a", "b","c"}; List list = new ArrayList(); list.add("a"); pageContext.setAttribute("arr", strs); pageContext.setAttribute("list", list); %> ${fn:length(arr) }<br/><!--3--> ${fn:length(list) }<br/><!--1--> ${fn:toLowerCase("Hello") }<br/><!-- hello --> ${fn:toUpperCase("Hello") }<br/><!-- HELLO --> ${fn:contains("abc", "a")}<br/><!-- true --> ${fn:containsIgnoreCase("abc", "Ab")}<br/><!-- true --> ${fn:contains(arr, "a")}<br/><!-- true --> ${fn:containsIgnoreCase(list, "A")}<br/><!-- true --> ${fn:endsWith("Hello.java", ".java")}<br/><!-- true --> ${fn:startsWith("Hello.java", "Hell")}<br/><!-- true --> ${fn:indexOf("Hello-World", "-")}<br/><!-- 5 --> ${fn:join(arr, ";")}<br/><!-- a;b;c --> ${fn:replace("Hello-World", "-", "+")}<br/><!-- Hello+World --> ${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c --> ${fn:substring("0123456789", 6, 9)}<br/><!-- 678 --> ${fn:substring("0123456789", 5, -1)}<br/><!-- 56789 --> ${fn:substringAfter("Hello-World", "-")}<br/><!-- World --> ${fn:substringBefore("Hello-World", "-")}<br/><!-- Hello --> ${fn:trim(" a b c ")}<br/><!-- a b c --> ${fn:escapeXml("<html></html>")}<br/><!-- <html></html> --> |
4 自定義EL函式庫
l 寫一個類,寫一個有返回值的靜態方法;
l 編寫itcast.tld檔案,可以引數fn.tld檔案來寫,把itcast.tld檔案放到/WEB-INF目錄下;
l 在頁面中新增taglib指令,匯入自定義標籤庫。
ItcastFuncations.java
package cn.itcast.el.funcations; publicclass ItcastFuncations { publicstatic String test() { return"傳智播客自定義EL函式庫測試"; } } |
itcast.tld(放到classes下)
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <short-name>itcast</short-name> <uri>http://www.itcast.cn/jsp/functions</uri> <function> <name>test</name> <function-class>cn.itcast.el.funcations.ItcastFuncations</function-class> <function-signature>String test()</function-signature> </function> </taglib> |
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="itcast" uri="/WEB-INF/itcast.tld" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> <h1>${itcast:test() }</h1> </body> </html> |
JSTL標籤庫
1 什麼是JSTL
JSTL是apache對EL表示式的擴充套件(也就是說JSTL依賴EL),JSTL是標籤語言!JSTL標籤使用以來非常方便,它與JSP動作標籤一定,只不過它不是JSP內建的標籤,需要我們自己導包,以及指定標籤庫而已!
如果你使用MyEclipse開發JavaWeb,那麼在把專案釋出到Tomcat時,你會發現,MyEclipse會在lib目錄下存放jstl的Jar包!如果你沒有使用MyEclipse開發那麼需要自己來匯入這個JSTL的Jar包:jstl-1.2.jar。
2 JSTL標籤庫
JSTL一共包含四大標籤庫:
l core:核心標籤庫,我們學習的重點;
l fmt:格式化標籤庫,只需要學習兩個標籤即可;
l sql:資料庫標籤庫,不需要學習了,它過時了;
l xml:xml標籤庫,不需要學習了,它過時了。
3 使用taglib指令匯入標籤庫
除了JSP動作標籤外,使用其他第三方的標籤庫都需要:
l 導包;
l 在使用標籤的JSP頁面中使用taglib指令匯入標籤庫;
下面是匯入JSTL的core標籤庫:
<%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>
l prefix="c":指定標籤庫的字首,這個字首可以隨便給值,但大家都會在使用core標籤庫時指定字首為c;
l uri="http://java.sun.com/jstl/core":指定標籤庫的uri,它不一定是真實存在的網址,但它可以讓JSP找到標籤庫的描述檔案;
4 core標籤庫常用標籤
4.1 out和set
out
<c:out value=”aaa”/> | 輸出aaa字串常量 |
<c:out value=”${aaa}”/> | 與${aaa}相同 |
<c:out value=”${aaa}” default=”xxx”/> | 當${aaa}不存在時,輸出xxx字串 |
<% request.setAttribute("a","<script>alert('hello');</script>"); %> <c:out value="${a }" default="xxx" escapeXml="false" /> | 當escapeXml為false,不會轉換“<”、“>”。這可能會受到JavaScript攻擊。 |
set
<c:set var=”a” value=”hello”/> | 在pageContext中新增name為a,value為hello的資料。 |
<c:set var=”a” value=”hello” scope=”session”/> | 在session中新增name為a,value為hello的資料。 |
4.2 remove
<% pageContext.setAttribute("a", "pageContext"); request.setAttribute("a", "session"); session.setAttribute("a", "session"); application.setAttribute("a", "application"); %> <c:out value="${a }" default="none"/> | 刪除所有域中name為a的資料! |
<c:remove var="a" scope=”page”/> | 刪除pageContext中name為a的資料! |
4.3 url
url標籤會在需要URL重寫時新增sessionId。
<c:url value="/"/> | 輸出上下文路徑:/day08_01/ |
<c:url value="/" var="a" scope="request"/> | 把本該輸出的結果賦給變數a。範圍為request |
<c:url value="/AServlet"/> | 輸出:/day08_01/AServlet |
<c:url value="/AServlet"> <c:param name="username" value="abc"/> <c:param name="password" value="123"/> </c:url> | 輸出:/day08_01/AServlet?username=abc&password=123 如果引數中包含中文,那麼會自動使用URL編碼! |
4.4 if
if標籤的test屬性必須是一個boolean型別的值,如果test的值為true,那麼執行if標籤的內容,否則不執行。
<c:set var="a" value="hello"/>[c1] <c:if test="${not empty a[c2] }"> <c:out value="${a }"/> </c:if> |
4.5 choose
choose標籤對應Java中的if/else if/else結構。when標籤的test為true時,會執行這個when的內容。當所有when標籤的test都為false時,才會執行otherwise標籤的內容。
<c:set var="score" value="${param.score }"/> <c:choose> <c:when test="${score > 100 || score < 0}">錯誤的分數:${score }</c:when>[c3] <c:when test="${score >= 90 }">A級</c:when>[c4] <c:when test="${score >= 80 }">B級</c:when> <c:when test="${score >= 70 }">C級</c:when> <c:when test="${score >= 60 }">D級</c:when> <c:otherwise>E級</c:otherwise>[c5] </c:choose> |
4.6 forEach
forEach當前就是迴圈標籤了,forEach標籤有多種兩種使用方式:
l 使用迴圈變數,指定開始和結束值,類似for(int i = 1; i <= 10; i++) {};
l 迴圈遍歷集合,類似for(Object o : 集合);
迴圈變數方式:
<c:set var="sum" value="0" />[崔6] <c:forEach var="i" begin="1" end="10">[崔7] <c:set var="sum" value="${sum + i}" />[崔8] </c:forEach> <c:outvalue="sum = ${sum }"/> |
<c:set var="sum" value="0" /> <c:forEach var="i" begin="1" end="10" step[崔9] ="2"> <c:set var="sum" value="${sum + i}" /> </c:forEach> <c:out value="sum = ${sum }"/> |
遍歷集合或陣列方式:
<% String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"}; pageContext.setAttribute("ns", names); %> <c:forEach var="item[崔10] " items="${ns }[崔11] "> <c:out value="name: ${item }[崔12] "/><br/> </c:forEach> |
遍歷List
List<String> names = new ArrayList<String>(); names.add("zhangSan"); names.add("liSi"); names.add("wangWu"); names.add("zhaoLiu"); pageContext.setAttribute("ns", names); %> <c:forEach var="item" items="${ns }">[崔13] <c:out value="name: ${item }"/><br/> </c:forEach> |
遍歷Map
<% Map<String,String> stu = new LinkedHashMap<String,String>(); stu.put("number", "N_1001"); stu.put("name", "zhangSan"); stu.put("age", "23"); stu.put("sex", "male"); pageContext.setAttribute("stu", stu); %> <c:forEach var="item[崔14] " items="${stu }"> </c:forEach> |
forEach標籤還有一個屬性:varStatus,這個屬性用來指定接收“迴圈狀態”的變數名,例如:<forEach varStatus=”vs” …/>,這時就可以使用vs這個變數來獲取迴圈的狀態了。
l count:int型別,當前以遍歷元素的個數;
l index:int型別,當前元素的下標;
l first:boolean型別,是否為第一個元素;
l last:boolean型別,是否為最後一個元素;
l current:Object型別,表示當前專案。
<c:forEach var="item" items="${ns }" varStatus="vs"[崔16] > <c:if test="${vs.first }[崔17] ">第一行:</c:if> <c:if test="${vs.last }[崔18] ">最後一行:</c:if> <c:out value="第${vs.count }[崔19] 行: "/> <c:out value="[${vs.index }[崔20] ]: "/> <c:out value="name: ${vs.current }[崔21] "/><br/> </c:forEach> |
5 fmt標籤庫常用標籤
fmt標籤庫是用來格式化輸出的,通常需要格式化的有時間和數字。
格式化時間:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> ...... <% Date date = new Date(); pageContext.setAttribute("d", date); %> <fmt:formatDate value="${d }" pattern=[崔22] "/> |
格式化數字:
<% double d1 = 3.5; double d2 = 4.4; pageContext.setAttribute("d1", d1); pageContext.setAttribute("d2", d2); %> <fmt:formatNumber value="${d1 }" pattern="0.00[崔23] "/><br/> |
[c1]在page域中建立名為a的變數
[c2]判斷a變數不為null,沒有指定域,表示全域
[c3]if
[c4]else if
[c5]else
[崔6]建立page域屬性sum為0
[崔7]設定迴圈變數i,初始值為1,遍歷到10。
[崔8]設定sum的值為sum + i
[崔9]步長為2,預設步長為1。相當於i+=2的意思!而預設為i++。
[崔10]把ns是中每一項賦給item。
[崔11]ns是被遍歷的陣列。
[崔12]列印每一項
[崔13]與遍歷陣列沒有區別!
for(String s : ns) {
…
}
[崔14]因為遍歷的是Map,所以每一項是Entry型別
[崔15]獲取Entry的key和value
[崔16]把迴圈狀態賦給vs
[崔17]如果是第一行,那麼${vs.first}為true
[崔18]如果是最後一行,那麼${vs.last}為true
[崔19]返回行數,從1開始
[崔20]返回行數,從0開始
[崔21]當前項,與${item}相同
[崔22]按指定格式輸出日期和時間。
[崔23]必須且僅能保留兩位小數,如果大於兩位,那麼只保留兩位,並四捨五入,如果小於兩位,那麼使用0補足兩位。
[崔24]最多顯示兩位,如果小於兩位,那麼有幾位保留幾位,不會用0補足。大於兩位,只保留兩位,並四捨五入!
自定義標籤
1 自定義標籤概述
1.1 自定義標籤的步驟
其實我們在JSP頁面中使用標籤就等於呼叫某個物件的某個方法一樣,例如:<c:if test=””>,這就是在呼叫物件的方法一樣。自定義標籤其實就是自定義類一樣!
l 定義標籤處理類:必須是Tag或SimpleTag的實現類;
l 編寫標籤庫描述符檔案(TLD);
SimpleTag介面是JSP2.0中新給出的介面,用來簡化自定義標籤,所以現在我們基本上都是使用SimpleTag。
Tag是老的,傳統的自定義標籤時使用的介面,現在不建議使用它了。
1.2 SimpleTag介面介紹
SimpleTag介面內容如下:
l void doTag():標籤執行方法;
l JspTag getParent():獲取父標籤;
l void setParent(JspTag parent):設定父標籤
l void setJspContext(JspContext context):設定PageContext
l void setJspBody(JspFragment jspBody):設定標籤體物件;
請記住,萬物皆物件!在JSP頁面中的標籤也是物件!你可以通過檢視JSP的“真身”清楚的知道,所有標籤都會變成物件的方法呼叫。標籤對應的類我們稱之為“標籤處理類”!
標籤的生命週期:
1. 當容器(Tomcat)第一次執行到某個標籤時,會建立標籤處理類的例項;
2. 然後呼叫setJspContext(JspContext)方法,把當前JSP頁面的pageContext物件傳遞給這個方法;
3. 如果當前標籤有父標籤,那麼使用父標籤的標籤處理類物件呼叫setParent(JspTag)方法;
4. 如果標籤有標籤體,那麼把標籤體轉換成JspFragment物件,然後呼叫setJspBody()方法;
5. 每次執行標籤時,都呼叫doTag()方法,它是標籤處理方法。
HelloTag.java
publicclass HelloTag implements SimpleTag { private JspTag parent; private PageContext pageContext; private JspFragment jspBody; publicvoid doTag() throws JspException, IOException { pageContext.getOut().print("Hello Tag!!!");[崔1] } publicvoid setParent(JspTag parent) { this.parent = parent; } public JspTag getParent() { returnthis.parent; } publicvoid setJspContext(JspContext pc) { this.pageContext = (PageContext) pc; } publicvoid setJspBody(JspFragment jspBody) { this.jspBody = jspBody; } } |
1.3 標籤庫描述檔案(TLD)
標籤庫描述檔案是用來描述當前標籤庫中的標籤的!標籤庫描述檔案的副檔名為tld,你可以把它放到WEB-INF下,這樣就不會被客戶端直接訪問到了。
hello.tld
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xml="http://www.w3.org/XML/1998/namespace" |