JSTL標簽介紹
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一共包含四大標簽庫:
- core:核心標簽庫,我們學習的重點;
- fmt:格式化標簽庫,只需要學習兩個標簽即可;
- sql:數據庫標簽庫,不需要學習了,它過時了;
- xml:xml標簽庫,不需要學習了,它過時了。
3、使用taglib指令導入標簽庫:
除了JSP動作標簽外,使用其他第三方的標簽庫都需要:
- 導包;
- 在使用標簽的JSP頁面中使用taglib指令導入標簽庫;
下面是導入JSTL的core標簽庫:
[html] view plain copy
- <%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>
- prefix="c":指定標簽庫的前綴,這個前綴可以隨便給值,但大家都會在使用
- uri="http://java.sun.com/jstl/core":指定標簽庫的uri,它不一定是真實存在的網址,但它可以讓JSP找到標簽庫的描述文件;
4、core標簽庫常用標簽:
(1)out和set標簽
<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攻擊。 |
<c:set var=”a” value=”hello”/> |
在pageContext中添加name為a,value為hello的數據。 |
<c:set var=”a” value=”hello” scope=”session”/> |
在session中添加name為a,value為hello的數據。 |
(2)remove標簽
<% pageContext.setAttribute("a","pageContext"); request.setAttribute("a","session"); session.setAttribute("a","session"); application.setAttribute("a","application"); %> <c: remove var="a"/> <c: out value="${a}" default="none"/> |
刪除所有域中name為a的數據! |
<c:remove var="a" scope=”page”/> |
刪除pageContext中name為a的數據 |
(3)url標簽:該標簽會在需要重寫URL時添加。
<c:url value="/"/> |
輸出上下文路徑:/項目名/ |
<c:url value="/" var="a" scope="request"/> |
把本該輸出的結果賦給變量a。範圍為request |
<c:url value="/AServlet"/> |
輸出:/項目名/AServlet |
<c:url value="/AServlet"> <c:param name="username" value="abc"/> <c:param name="password" value="123"/> |
輸出:/項目名/AServlet?username=abc&password=123 如果參數中包含中文,那麽會自動使用URL編碼! |
(4)if標簽:
if標簽的test屬性必須是一個boolean類型的值,如果test的值為true,那麽執行if標簽的內容,否則不執行。
[html] view plain copy
- <c:set var="a" value="hello"/>
- <c:if test="${not empty a }">
- <c:out value="${a }"/>
- </c:if>
(5)choose標簽:
choose標簽對應Java中的if/else if/else結構。when標簽的test為true時,會執行這個when的內容。當所有when標簽的test都為false時,才會執行otherwise標簽的內容。
[html] view plain copy
- <c:set var="score" value="${param.score }"/>
- <c:choose>
- <c:when test="${score > 100 || score < 0}">錯誤的分數:${score }</c:when>
- <c:when test="${score >= 90 }">A級</c:when>
- <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>
- </c:choose>
(6)forEach標簽:
forEach當前就是循環標簽了,forEach標簽有多種兩種使用方式:
- 使用循環變量,指定開始和結束值,類似for(int i = 1; i <= 10; i++) {};
- 循環遍歷集合,類似for(Object o : 集合);
循環變量:
[html] view plain copy
- <c:set var="sum" value="0" />
- <c:forEach var="i" begin="1" end="10">
- <c:set var="sum" value="${sum + i}" />
- </c:forEach>
- <c:out value="sum = ${sum }"/>
- <c:set var="sum" value="0" />
- <c:forEach var="i" begin="1" end="10" step ="2">
- <c:set var="sum" value="${sum + i}" />
- </c:forEach>
- <c:out value="sum = ${sum }"/>
遍歷集合或數組方式:
[html] view plain copy
- <%
- String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"};
- pageContext.setAttribute("ns", names);
- %>
- <c:forEach var="item" items="${ns }">
- <c:out value="name: ${item }"/><br/>
- </c:forEach>
遍歷List:
[html] view plain copy
- <%
- 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 }">
- <c:out value="name: ${item }"/><br/>
- </c:forEach>
遍歷Map:
[html] view plain copy
- <%
- 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" items="${stu }">
- <c:out value="${item.key }: ${item.value }"/><br/>
- </c:forEach>
forEach標簽還有一個屬性:varStatus,這個屬性用來指定接收“循環狀態”的變量名,例如:<forEach varStatus=”vs” …/>,這時就可以使用vs這個變量來獲取循環的狀態了。
- count:int類型,當前以遍歷元素的個數;
- index:int類型,當前元素的下標;
- first:boolean類型,是否為第一個元素;
- last:boolean類型,是否為最後一個元素;
- current:Object類型,表示當前項目。
[html] view plain copy
- <c:forEach var="item" items="${ns }" varStatus="vs">
- <c:if test="${vs.first }">第一行:</c:if>
- <c:if test="${vs.last }">最後一行:</c:if>
- <c:out value="第${vs.count }行: "/>
- <c:out value="[${vs.index }]: "/>
- <c:out value="name: ${vs.current }"/><br/>
- </c:forEach>
5、fmt標簽庫常用標簽:
fmt標簽庫是用來格式化輸出的,通常需要格式化的有時間和數字。
格式化時間:
[html] view plain copy
- <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
- ......
- <%
- Date date = new Date();
- pageContext.setAttribute("d", date);
- %>
- <fmt:formatDate value="${d }" pattern="yyyy-MM-dd HH:mm:ss"/>
格式化數字:
[html] view plain copy
- <%
- double d1 = 3.5;
- double d2 = 4.4;
- pageContext.setAttribute("d1", d1);
- pageContext.setAttribute("d2", d2);
- %>
- <fmt:formatNumber value="${d1 }" pattern="0.00"/><br/>
- <fmt:formatNumber value="${d2 }" pattern="#.##"/>
介紹了JSTL中的常用標簽,那可以定義自己的標簽嗎?
答案是:可以。
二、自定義標簽
1、自定義標簽
1.1步驟:
其實我們在JSP頁面中使用標簽就等於調用某個對象的某個方法一樣,例如:<c:if test=””>,這就是在調用對象的方法一樣。自定義標簽其實就是自定義類一樣!
- 定義標簽處理類:必須是Tag或SimpleTag的實現類;
- 編寫標簽庫描述符文件(TLD);
SimpleTag接口是JSP2.0中新給出的接口,用來簡化自定義標簽,所以現在我們基本上都是使用SimpleTag。
Tag是老的,傳統的自定義標簽時使用的接口,現在不建議使用它了。
1.2 SimpleTag接口介紹:
SimpleTag接口內容如下:
- void doTag():標簽執行方法;
- JspTag getParent():獲取父標簽;
- void setParent(JspTag parent):設置父標簽
- void setJspContext(JspContext context):設置PageContext
- void setJspBody(JspFragment jspBody):設置標簽體對象;
請記住,萬物皆對象!在JSP頁面中的標簽也是對象!你可以通過查看JSP的源碼,清楚的知道,所有標簽都會變成對象的方法調用。標簽對應的類我們稱之為“標簽處理類”!
標簽的生命周期:
1、當容器(Tomcat)第一次執行到某個標簽時,會創建標簽處理類的實例;
2、然後調用setJspContext(JspContext)方法,把當前JSP頁面的pageContext對象傳遞給這個方法;
3、如果當前標簽有父標簽,那麽使用父標簽的標簽處理類對象調用setParent(JspTag)方法;
4、如果標簽有標簽體,那麽把標簽體轉換成JspFragment對象,然後調用setJspBody()方法;
5、每次執行標簽時,都調用doTag()方法,它是標簽處理方法。
HelloTag.java
[java] view plain copy
- public class HelloTag implements SimpleTag {
- private JspTag parent;
- private PageContext pageContext;
- private JspFragment jspBody;
- public void doTag() throws JspException, IOException {
- pageContext.getOut().print("Hello Tag!!!");
- }
- public void setParent(JspTag parent) {
- this.parent = parent;
- }
- public JspTag getParent() {
- return this.parent;
- }
- public void setJspContext(JspContext pc) {
- this.pageContext = (PageContext) pc;
- }
- public void setJspBody(JspFragment jspBody) {
- this.jspBody = jspBody;
- }
- }
1.3 標簽庫描述文件(TLD)
標簽庫描述文件是用來描述當前標簽庫中的標簽的!標簽庫描述文件的擴展名為tld,你可以把它放到WEB-INF下,這樣就不會被客戶端直接訪問到了。
hello.tld
[html] view plain copy
- <?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"
- 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 ">
- <tlib-version>1.0</tlib-version>
- <short-name>ywq</short-name>
- <uri>http://www.ywq.cn/tags</uri>
- <tag>
- <name>hello</name>
- <tag-class>cn.ywq.tag.HelloTag</tag-class>
- <body-content>empty</body-content>
- </tag>
- </taglib>
1.4 使用標簽
在頁面中使用標簽分為兩步:
- 使用taglib導入標簽庫;
- 使用標簽;
[html] view plain copy
- <%@ taglib prefix="it" uri="/WEB-INF/hello.tld" %>
- ......
- <it:hello/>
2、自定義標簽進階
2.1 繼承SimpleTagSupport
繼承SimpleTagSuppport要比實現SimpleTag接口方便太多了,現在你只需要重寫doTag()方法,其他方法都已經被SimpleTagSuppport完成了。
[java] view plain copy
- public class HelloTag extends SimpleTagSupport {
- public void doTag() throws JspException, IOException {
- this.getJspContext().getOut().write("<p>Hello SimpleTag!</p>");
- }
- }
2.2 有標簽體的標簽
我們先來看看標簽體內容的可選值:
<body-content>元素的可選值有:
- empty:無標簽體。
- JSP:傳統標簽支持它,SimpleTag已經不再支持使用<body-content>JSP</body-content>。標簽體內容可以是任何東西:EL、JSTL、<%=%>、<%%>,以及html;
- scriptless:標簽體內容不能是Java腳本,但可以是EL、JSTL等。在SimpleTag中,如果需要有標簽體,那麽就使用該選項;
- tagdependent:標簽體內容不做運算,由標簽處理類自行處理,無論標簽體內容是EL、JSP、JSTL,都不會做運算。這個選項幾乎沒有人會使用!
自定義有標簽體的標簽需要:
- 獲取標簽體對象:JspFragment jspBody = getJspBody();;
- 把標簽體內容輸出到頁面:jspBody.invoke(null);
- tld中指定標簽內容類型:scriptless。
[java] view plain copy
- public class HelloTag extends SimpleTagSupport {
- public void doTag() throws JspException, IOException {
- PageContext pc = (PageContext) this.getJspContext();
- HttpServletRequest req = (HttpServletRequest) pc.getRequest();
- String s = req.getParameter("exec");
- if(s != null && s.endsWith("true")) {
- JspFragment body = this.getJspBody();
- body.invoke(null);
- }
- }
- }
[html] view plain copy
- <tag>
- <name>hello</name>
- <tag-class>cn.ywq.tags.HelloTag</tag-class>
- <body-content>scriptless</body-content>
- </tag>
[html] view plain copy
- <itcast:hello>
- <h1>哈哈哈~</h1>
- </itcast:hello>
2.3 不執行標簽下面的頁面內容
如果希望在執行了自定義標簽後,不再執行JSP頁面下面的東西,那麽就需要在doTag()方法中使用SkipPageException。
[java] view plain copy
- public class SkipTag extends SimpleTagSupport {
- public void doTag() throws JspException, IOException {
- this.getJspContext().getOut().print("<h1>只能看到我!</h1>");
- throw new SkipPageException();
- }
- }
[html] view plain copy
- <tag>
- <name>skip</name>
- <tag-class>cn.ywq.tags.SkipTag</tag-class>
- <body-content>empty</body-content>
- </tag>
[html] view plain copy
- <itcast:skip/>
- <h1>看不見我!</h1>
2.4 帶有屬性的標簽
一般標簽都會帶有屬性,例如<c:iftest=””>,其中test就是一個boolean類型的屬性。完成帶有屬性的標簽需要:
- 在處理類中給出JavaBean屬性(提供get/set方法);
- 在TLD中部屬相關屬性。
[java] view plain copy
- public class IfTag extends SimpleTagSupport {
- private boolean test;
- public boolean isTest() {
- return test;
- }
- public void setTest(boolean test) {
- this.test = test;
- }
- @Override
- public void doTag() throws JspException, IOException {
- if(test) {
- this.getJspBody().invoke(null);
- }
- }
- }
[html] view plain copy
- <tag>
- <name>if</name>
- <tag-class>cn.ywq.IfTag</tag-class>
- <body-content>scriptless</body-content>
- <attribute>
- <name>test</name>
- <required>true</required>
- <rtexprvalue>true</rtexprvalue>
- </attribute>
- </tag>
[html] view plain copy
- <%
- pageContext.setAttribute("one", true);
- pageContext.setAttribute("two", false);
- %>
- <it:if test="${one }">xixi</it:if>
- <it:if test="${two }">haha</it:if>
- <it:if test="true">hehe</it:if>
JSTL標簽介紹