上一篇博文我們講解了 MVC 小案例,案例中包含了基本的增、刪、改、查,對這個案例的有興趣的伙伴可以自己動手實踐一下,去復習一下或者說是學點新的知識!如果有已經看過且實踐過的伙伴相信對 JSP 頁面中的 Java 代碼很是煩躁。在 JSP 頁面上寫 Java 代碼不僅影響美觀而且對很容易寫錯我們想寫的邏輯代碼,我們今天所講的 JSTL 就可以完美解決在 JSP 頁面上寫 Java 代碼的缺點。在開始講解 JSTL 之前我們先講解一下 EL、自定義 JSTL等知識點。
EL(Expression Language) 是為了使JSP寫起來更加簡單。表達式語言的靈感來自於 ECMAScript 和 XPath 表達式語言,它提供了在 JSP 中簡化表達式的方法,讓Jsp的代碼更加簡化。
1. 所有的 EL 表達式都是以 ${ 開頭,以 } 結尾,我們先來舉一個例子體會一下 EL 表達式相比於 Java 代碼的優勢,如: ${sessionScope.user.sex} ,表示的是在隱藏域 session 范圍里找 user 屬性,然后在 user 對象中找 sex 屬性,它等同於 JSP 頁面中的 Java 代碼,如下:
1 User user = (User)session.getAttribute(“user”); 2 String sex = user.getSex();
2. EL 運算符 [ ] 和 .
1). [ ] 等同於 . 運算符,如上面的 EL 表達式等同於 ${sessionScope.user[“sex”]} ;
2). [ ] 運算符可以結合下標打印數組或者集合的值,如: ${sessionScope.shoppingCart[0].price 表示在 session 屬性范圍內找到屬性 shoppingCart 的集合對象,然后打印其第一行的 price 屬性;
3). 如果屬性名為 com.javaweb.el 那我們就應該使用 [ ] 運算符去操作屬性;
4). EL 表達式不可以進行遍歷數組集合的遍歷。
3. EL 表達式的查找順序
- 對於 EL 表達式 ${userName} 由於我們沒有指定其屬性范圍,那么 EL 會從 page、request、session、application 四個隱藏屬性中依次查找屬性名為 userName 的屬性,如果在哪一個隱藏域中找到就返回不再繼續查找,如果找完了還沒有找到就返回 NULL
4. EL 隱含對象
1). param 獲取請求參數
2). paramValues 獲取一組請求參數,返回類型為數組,可以使用 [] 和小標的形式打印其中某一個數據
5. EL 表達式會自動進行強制轉換
- EL 表達式可以進行自動的強制類型轉換,如: ${param.count + 20} 就是將獲取請求參數 count 后加上 20,假如請求參數 count 的值是 10,那么打印結果將會是 30,而不是 1020,因為 EL 表達式會進行自動的類型轉換。
6. . 運算符
- EL 表達式獲取到結果是對象,並且該對象有無參的 get 方法,那么就可以使用 . 運算符調用該方法,並且可以一直調用下去,如: ${sessionScope.time.time} 等同於
Session.setAttribute(“time”, new Date() );
new Date.getTime()
7. 其他隱含對象
1). initParam 獲取當前 WEB 應用的初始化參數
2). pageContext 可以用來獲取當前 WEB 應用的根路徑 ${pageContext.request.contextPath}
3). Cookie ${cookie.JSESSIONID.name} ${cookie.JSESSIONID.value}
4). empty 運算符,如: ${empty param.name} 是判斷輸入框 name 屬性是否為空,為空返回 true, 否則返回 false
自定義 JSTL 標簽
1. 自定義標簽分為空標簽、帶內容的標簽、帶屬性的標簽、帶屬性和帶內容的標簽、帶有父標簽的標簽
2. 開發自定義標簽的核心就是編寫標簽處理器
3. 步驟
1). 編寫完成標簽功能的 Java 類(標簽處理器)
a. 編寫標簽處理器,新建 Java 類,實現 SimpleTag 接口
b. 接口方法介紹:
-1. SetJspContext JSP 引擎將代表頁面的 pageContext 對象傳遞給標簽處理器對象 ,JSPContext 是 pageContext 的父類由其可獲得其他八個隱含對象
-2. setParent JSP 引擎將父標簽處理器對象傳給當前標簽處理器對象,只有存在父標簽時 JSP 引擎才回調用該方法
-3. SetXxx 設置標簽屬性,只有定義了屬性才回調用該方法
-4. setJSPBody 若存在標簽體,JSP 引擎把標簽體封裝為一個 JSPFragment 對象,調用 SetJspBody 方法將 JSPFragment 對象傳遞給標簽處理器,若標簽體為空 JSP 引擎則不會調用該方法
-5. doTag 此方法是標簽執行邏輯代碼的主要方法
2). 編寫標簽庫的描述文件(.tld),在 tld 文件對自定義標簽進行描述
3). 在 JSP 頁面導入和使用自定義標簽
4. 編寫帶屬性的自定義標簽(我們自定義一個帶有 count 屬性和 attr 屬性的標簽,該標簽的功能是將 attr 屬性值打印在頁面上,並打印 count 次)
1). 步驟如上所說,代碼如下:
a. 標簽處理器類
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspContext; 4 import javax.servlet.jsp.JspException; 5 import javax.servlet.jsp.PageContext; 6 import javax.servlet.jsp.tagext.JspFragment; 7 import javax.servlet.jsp.tagext.JspTag; 8 import javax.servlet.jsp.tagext.SimpleTag; 9 import java.io.IOException; 10 11 public class SimpleTagHelloWorld implements SimpleTag { 12 13 // 當設置屬性時調用屬性名對應的 setXxx 方法;需要首先在 tld 文件中描述其標簽屬性 14 // 建議將所有的屬性都聲明為 String 類型 15 private String attr; 16 private String count; 17 private PageContext pageContext; 18 19 public void setAttr(String attr) { 20 this.attr = attr; 21 } 22 public void setCount(String count) { 23 this.count = count; 24 } 25 26 // 標簽執行的邏輯代碼,每次都會執行的方法 27 @Override 28 public void doTag() throws JspException, IOException { 29 System.out.println(attr); 30 System.out.println(count); 31 32 // 從 url 中獲取請求參數 name 的值,並將其打印 count 次 33 int c; 34 c = Integer.parseInt(count); 35 for (int i = 0; i < c; i++) { 36 pageContext.getOut().print(attr + "<br>"); 37 } 38 } 39 40 @Override 41 public void setParent(JspTag jspTag) { 42 System.out.println("setParent"); 43 } 44 45 @Override 46 public JspTag getParent() { 47 return null; 48 } 49 // 是 pageContext 的父類,可以獲取到其他八個隱含對象,所以凡是 JSP 頁面可以做的那么標簽處理器都可以做 50 // 由 JSP 引擎直接調用 51 @Override 52 public void setJspContext(JspContext jspContext) { 53 this.pageContext = (PageContext) jspContext; 54 } 55 56 @Override 57 public void setJspBody(JspFragment jspFragment) { 58 System.out.println("setJspBody"); 59 } 60 }
b. .tld 文件(后面的 tld 文件將指貼出 tag 節點,因為其他部分為固定的)
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <taglib xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" 6 version="2.1"> 7 8 <tlib-version>1.0</tlib-version> 9 <!--在頁面所推薦使用的標簽開頭--> 10 <short-name>hello</short-name> 11 <!--在頁面所要引用的 uri--> 12 <uri>http://hello.world.com</uri> 13 14 <tag> 15 <!--標簽名--> 16 <name>world</name> 17 <!--標簽處理器全類名--> 18 <tag-class>simple.myself.tag.helloworld.SimpleTagHelloWorld</tag-class> 19 <!--標簽體--> 20 <body-content>empty</body-content> 21 <!--設置屬性--> 22 <attribute> 23 <!--屬性名--> 24 <name>attr</name> 25 <!--設置是否為必須的屬性--> 26 <required>true</required> 27 <!--runtime expression value, 設置是否可以接受表達式的值,如 EL--> 28 <rtexprvalue>true</rtexprvalue> 29 </attribute> 30 <attribute> 31 <name>count</name> 32 <required>false</required> 33 <rtexprvalue>false</rtexprvalue> 34 </attribute> 35 </tag> 36 </taglib>
c. JSP 頁面上的使用(其中 attr 屬性的值為獲取請求參數的 name 屬性值,我們可以直接在地址欄加上 name 屬性,如 http://.....xxx.jsp?name=java)
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%--導入標簽庫--%> 3 <%@taglib prefix="hello" uri="http://hello.world.com" %> 4 <html> 5 <head> 6 <title>myselfTag</title> 7 </head> 8 <body> 9 <h3> 10 <hello:world attr="${param.name}" count="10"></hello:world> 11 </h3> 12 </body> 13 </html>
5. 帶屬性標簽小練習(可以先思考,其代碼在最后公布)
1). 自定義一個標簽,帶有兩個屬性 max,min,執行標簽將會打印兩個屬性中的最大值
2). 自定義一個標簽,帶有一個屬性 src,執行標簽將會將文件的內容打印到桌面上
6. 帶標簽體和帶屬性的標簽
1). 類似於上面,我們這次將標簽體的內容打印 times 次,並將標簽體的內容轉換為大寫
a. 標簽處理器類(這次我們直接繼承 SimpleTagSupport 類,只需要實現 doTag 方法,方便了代碼書寫)
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.PageContext; 5 import javax.servlet.jsp.tagext.JspFragment; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7 import javax.sql.rowset.JdbcRowSet; 8 import java.io.IOException; 9 import java.io.StringWriter; 10 11 /** 12 * Created by shkstart on 2017/11/21. 13 */ 14 public class Times extends SimpleTagSupport { 15 16 private String times; 17 18 public void setTimes(String times) { 19 this.times = times; 20 } 21 22 @Override 23 public void doTag() throws JspException, IOException { 24 PageContext pageContext = (PageContext) getJspContext(); 25 // 獲取標簽體,封裝為 JSPFragment 對象 26 JspFragment jspFragment = getJspBody(); 27 StringWriter stringWriter = new StringWriter(); 28 // 將標簽體輸出到 StringWriter,若 invoke 方法參數為 null 則直接輸出到頁面 29 jspFragment.invoke(stringWriter); 30 String content = stringWriter.toString().toUpperCase(); 31 32 int c = Integer.parseInt(times); 33 for (int i = 0; i < c; i++) { 34 pageContext.getOut().print(content + "<br>"); 35 } 36 } 37 }
b. tld 文件
1 <tag> 2 <name>toUpTimes</name> 3 <tag-class>simple.myself.tag.helloworld.Times</tag-class> 4 <body-content>scriptless</body-content> 5 <attribute> 6 <name>times</name> 7 <required>true</required> 8 </attribute> 9 </tag>
c. 標簽的使用
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@taglib prefix="hello" uri="http://hello.world.com" %> 3 <html> 4 <head> 5 <title>BodyAttr</title> 6 </head> 7 <body> 8 <h3></h3> 9 <hello:toUpTimes times="10">HelloWorldAgain</hello:toUpTimes> 10 11 </body> 12 </html>
7. 帶父標簽的標簽
1. 我們利用父標簽實現一個類似於 if ... else if ... else if ... else ... 的標簽
2. 標簽包含了 choose(父標簽)、when(子標簽)、otherwise(子標簽),類似於 if ... else if ... else ...
3. 父標簽和子標簽只是在標簽處理器上有聯系(通過 getParent),而在 tld 描述文件上沒有聯系
4. 新建三個標簽處理器類,如下
a. 標簽處理器類 (順序為 choose --> when --> otherwise)
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.SimpleTagSupport; 5 import java.io.IOException; 6 7 /** 8 * Created by shkstart on 2017/11/21. 9 */ 10 public class Choose extends SimpleTagSupport { 11 12 // 在父標簽中創建一個變量,用於在子標簽中的判斷 13 private boolean flag = true; 14 15 public void setFlag(boolean flag) { 16 this.flag = flag; 17 } 18 19 public boolean isFlag() { 20 return flag; 21 } 22 23 @Override 24 public void doTag() throws JspException, IOException { 25 // 對於父標簽來說,其標簽體為子標簽,所以直接打印標簽體就是執行子標簽 26 getJspBody().invoke(null); 27 } 28 }
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.JspTag; 5 import javax.servlet.jsp.tagext.SimpleTagSupport; 6 import java.io.IOException; 7 8 /** 9 * Created by shkstart on 2017/11/21. 10 */ 11 public class When extends SimpleTagSupport { 12 13 private boolean item; 14 15 public void setItem(boolean item) { 16 this.item = item; 17 } 18 19 @Override 20 public void doTag() throws JspException, IOException { 21 Choose jspTag = (Choose) getParent(); 22 boolean flag = jspTag.isFlag(); 23 24 if (item) { 25 if (flag) { 26 // 若父標簽的標志為真,且子標簽本身也為真,那么就執行子標簽的標簽的標簽體,且將父標簽的標志置為 false 27 getJspBody().invoke(null); 28 jspTag.setFlag(false); 29 } 30 } 31 } 32 }
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.SimpleTagSupport; 5 import java.io.IOException; 6 7 /** 8 * Created by shkstart on 2017/11/21. 9 */ 10 public class OtherWise extends SimpleTagSupport { 11 12 @Override 13 public void doTag() throws JspException, IOException { 14 Choose choose = (Choose) getParent(); 15 boolean flag = choose.isFlag(); 16 // 只需判斷父標簽是否為真,若執行了 when 那么就不會執行此操作,因為父標簽的標志已經被置為 false 17 if (flag) { 18 getJspBody().invoke(null); 19 } 20 } 21 }
b. tld 文件
1 <tag> 2 <name>choose</name> 3 <tag-class>simple.myself.tag.helloworld.Choose</tag-class> 4 <body-content>scriptless</body-content> 5 </tag> 6 <tag> 7 <name>when</name> 8 <tag-class>simple.myself.tag.helloworld.When</tag-class> 9 <body-content>scriptless</body-content> 10 <attribute> 11 <name>item</name> 12 <required>true</required> 13 <rtexprvalue>true</rtexprvalue> 14 </attribute> 15 </tag> 16 <tag> 17 <name>otherwise</name> 18 <tag-class>simple.myself.tag.helloworld.OtherWise</tag-class> 19 <body-content>scriptless</body-content> 20 </tag>
c. 使用(獲取請求參數 age 的值,判斷其值若是大於 25 則打印 DX,否則打印 XX),表面上看父標簽和子標簽沒有直接上的聯系,但是需要在父標簽中新建標識控制子標簽的執行與否
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@ taglib prefix="hello" uri="http://hello.world.com" %> 3 <html> 4 <head> 5 <title>Choose</title> 6 </head> 7 <body> 8 <h3> 9 <hello:choose> 10 <hello:when item="${param.age > 25}">DX</hello:when> 11 <hello:otherwise>XX</hello:otherwise> 12 </hello:choose> 13 </h3> 14 </body> 15 </html>
8. 實現一個自定義的 forEach 標簽,實現了對集合的遍歷(JSTL 中的 forEach 可以對集合和 Map等進行遍歷,這里我們實現對集合的遍歷就好)
1. 其必須包含屬性 ietms 獲取集合信息
2. 其必須包含屬性 var 存儲當期所遍歷的信息
3. 將當前所遍歷的集合數據存入域對象 pageContext 中,屬性名為 var,值為當前遍歷的對象
4. 在頁面上使用的時候不需要去指明其域對象范圍,因為默認的便是從 pageContext 中查找
a. 標簽處理器類
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.PageContext; 5 import javax.servlet.jsp.tagext.JspFragment; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7 import java.io.IOException; 8 import java.util.List; 9 10 /** 11 * Created by shkstart on 2017/11/21. 12 */ 13 public class ForEach extends SimpleTagSupport { 14 15 private List<Object> items; 16 private String var; 17 18 public void setItems(List<Object> items) { 19 this.items = items; 20 } 21 22 public void setVar(String var) { 23 this.var = var; 24 } 25 26 // 自定義實現 forEach 27 // 遍歷 items 集合,並將該當前遍歷的對象加入到 pageContext 中,鍵為 var, 值為正在遍歷的對象 28 // 在頁面上若不加范圍 默認的便是從 pageContext 開始查找,所以可以省略 29 @Override 30 public void doTag() throws JspException, IOException { 31 PageContext pageContext = (PageContext) getJspContext(); 32 33 for (Object obj : items) { 34 pageContext.setAttribute(var, obj); 35 JspFragment jspFragment = getJspBody(); 36 jspFragment.invoke(null ); 37 } 38 } 39 }
b. tld 描述文件
1 <tag> 2 <name>forEach</name> 3 <tag-class>simple.myself.tag.helloworld.ForEach</tag-class> 4 <body-content>scriptless</body-content> 5 6 <attribute> 7 <name>items</name> 8 <required>true</required> 9 <rtexprvalue>true</rtexprvalue> 10 </attribute> 11 12 <attribute> 13 <name>var</name> 14 <required>true</required> 15 <rtexprvalue>false</rtexprvalue> 16 </attribute> 17 </tag>
c. 頁面上的使用(包含了在頁面上模仿 Servlet 給集合中添加數據在請求轉發到獲取頁面對其進行遍歷)
1 <%@ page import="com.java.jstl.domain.Customer" %> 2 <%@ page import="java.util.List" %> 3 <%@ page import="java.util.ArrayList" %> 4 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 5 <html> 6 <head> 7 <title>Customer</title> 8 </head> 9 <body> 10 <h3><% 11 List<Customer> list = new ArrayList<Customer>(); 12 list.add(new Customer(1, "z", "x")); 13 list.add(new Customer(2, "v", "q")); 14 list.add(new Customer(3, "c", "w")); 15 list.add(new Customer(4, "x", "e")); 16 17 request.setAttribute("customer", list); 18 %> 19 <jsp:forward page="forEach.jsp"></jsp:forward> 20 </body> 21 </html>
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@taglib prefix="hello" uri="http://hello.world.com" %> 3 <html> 4 <head> 5 <title>ForEachOfMy</title> 6 </head> 7 <body> 8 <h3> 9 <hello:forEach items="${requestScope.customer}" var="customer"> 10 ${customer.id}, ${customer.name}, ${customer.address}<br> 11 </hello:forEach> 12 </h3> 13 </body> 14 </html>
9. 我們上面要求大家自己去實現思考的自定義標簽的代碼
1. 是求兩個屬性的最大值
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspContext; 4 import javax.servlet.jsp.JspException; 5 import javax.servlet.jsp.PageContext; 6 import javax.servlet.jsp.tagext.JspFragment; 7 import javax.servlet.jsp.tagext.JspTag; 8 import javax.servlet.jsp.tagext.SimpleTag; 9 import java.io.IOException; 10 11 /** 12 * 此標簽的功能是比較兩個參數值,並輸出比較大的值到頁面 13 */ 14 public class MaxMin implements SimpleTag { 15 16 private String max; 17 private String min; 18 private PageContext pageContext; 19 20 public void setMax(String max) { 21 this.max = max; 22 } 23 24 public void setMin(String min) { 25 this.min = min; 26 } 27 28 @Override 29 public void doTag() throws JspException, IOException { 30 int num1, num2; 31 num1 = Integer.parseInt(max); 32 num2 = Integer.parseInt(min); 33 34 if (num1 > num2) { 35 pageContext.getOut().print(num1 + "<br>"); 36 return; 37 } 38 pageContext.getOut().print(num2 + "<br>"); 39 } 40 41 @Override 42 public void setParent(JspTag jspTag) { 43 44 } 45 46 @Override 47 public JspTag getParent() { 48 return null; 49 } 50 51 @Override 52 public void setJspContext(JspContext jspContext) { 53 this.pageContext = (PageContext) jspContext; 54 } 55 56 @Override 57 public void setJspBody(JspFragment jspFragment) { 58 59 } 60 }
1 <tag> 2 <name>max</name> 3 <tag-class>simple.myself.tag.helloworld.MaxMin</tag-class> 4 <body-content>empty</body-content> 5 <attribute> 6 <name>max</name> 7 <required>true</required> 8 <rtexprvalue>false</rtexprvalue> 9 </attribute> 10 <attribute> 11 <name>min</name> 12 <required>true</required> 13 <rtexprvalue>false</rtexprvalue> 14 </attribute> 15 </tag>
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%--導入標簽庫--%> 3 <%@taglib prefix="hello" uri="http://hello.world.com" %> 4 <html> 5 <head> 6 <title>myselfTag</title> 7 </head> 8 <body> 9 <h3> 10 <%--<hello:world attr="${param.name}" count="10"></hello:world>--%> 11 <hello:max max="20" min="50"></hello:max> 12 </h3> 13 </body> 14 </html>
2. 獲取本地文件將其打印到頁面
1 package simple.myself.tag.helloworld; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.PageContext; 5 import javax.servlet.jsp.tagext.SimpleTagSupport; 6 import java.io.*; 7 import java.util.regex.Pattern; 8 9 /** 10 * 此標簽的功能是將文件輸出到頁面, 11 * 如果要輸出的文件中有<> 就需要利用正則表達式將其替換為 < 和 > 12 */ 13 public class IO extends SimpleTagSupport{ 14 15 private PageContext pageContext; 16 private String src; 17 18 public void setSrc(String src) { 19 this.src = src; 20 } 21 22 @Override 23 public void doTag() throws JspException, IOException { 24 // 利用 Reader 讀取字符文件 25 File file = new File(src); 26 pageContext = (PageContext) getJspContext(); 27 28 Reader reader = new FileReader(file); 29 // 加上緩沖流加快讀取速度 30 BufferedReader bufferedReader = new BufferedReader(reader); 31 String str; 32 33 while((str = bufferedReader.readLine()) != null) { 34 // 利用正則表達式將 <> 轉義 35 str = Pattern.compile("<").matcher(str).replaceAll("<"); 36 str = Pattern.compile(">").matcher(str).replaceAll(">"); 37 pageContext.getOut().print(str + "<br>"); 38 } 39 40 bufferedReader.close(); 41 reader.close(); 42 } 43 }
1 <tag> 2 <name>readFile</name> 3 <tag-class>simple.myself.tag.helloworld.IO</tag-class> 4 <body-content>empty</body-content> 5 <attribute> 6 <name>src</name> 7 <required>true</required> 8 <rtexprvalue>false</rtexprvalue> 9 </attribute> 10 </tag>
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%--導入標簽庫--%> 3 <%@taglib prefix="hello" uri="http://hello.world.com" %> 4 <html> 5 <head> 6 <title>myselfTag</title> 7 </head> 8 <body> 9 <h3> 10 <%--<hello:world attr="${param.name}" count="10"></hello:world>--%> 11 <hello:max max="20" min="50"></hello:max> 12 <hello:readFile src="C:\Users\lenovo\Desktop\error.txt"></hello:readFile> 13 </h3> 14 </body> 15 </html>
到這里我們就將自定義簡單標簽講完了,掌握了自定義 JSTL 標簽那么對於學習 JSTL 就更加簡單了,現在我們開始說一下 JSTL 吧。
1. JSTL 有許多的標簽庫,我們最常用是核心標簽庫,我們在使用之前首先需要將其 jar 包加入到 lib 目錄下,對於 IDEA 需要新建 lib 目錄;
2. <c:out value=""></c:out> 等同於 <%= %> ,但是 c:out 標簽可以對敏感字符進行自動轉換,如: <>,Value 值可以是 EL 表達式,但單獨使用 EL 表達式將不會轉換敏感字符
3. <c:set var=”屬性名” value=”屬性值” scope=””></c:set> value 屬性值可以使用 EL 表達式賦值,c:set 直接在指定范圍放置屬性
4. c:set 也可以為某域對象的范圍內的某 JavaBean 對象賦值 (其中 request 范圍內的 cust 屬性為某一 JavaBean 對象)
<c:set target=”${requestScope.cust }” property=”id” value=”${param.id }”></c:set>
5. <c:if test=""></c:if> test 表達式的值若為 true,則打印標簽體,我們還可以利用 scope 和 var 屬性將 boolean 結果存儲到域對象中,以便后面的使用。但是沒有對應的 else 標簽(我們可以利用 choose when otherwise 實現 if else)
6. <c:forEach items=""></c:forEach> 可以實現對集合、map、數組進行遍歷,其還有屬性 begin、 end 、step、 var、 item、varStatus
1).begin 表示從哪個下標開始(默認從 0 開始)
2). end 表示遍歷到哪結束
3). step 表示每次遍歷后增加幾(默認為 1)
4). var 將當前查詢的數據保存到鍵為 var 屬性的 pageContext 中
5). item 從域對象中獲取結合數據
6). varStatus 屬性還有擁有 index 、count、 first 、last
a. index 表示當前所操作的下標
b. count 表示當前所操作的對象是第幾個
c. first 返回 boolean 值,表示當前對象是不是第一個(所操作范圍之內,即第一個打印的其值為 true,並不是整個集合的第一個,取決於 begin 的值)
d. last 返回 boolean 值,表示當前對象是不是最后一個(所操作范圍之內,即最后一個打印的其值為 true,並不是整個集合的最后一個,取決於 end 的值)
上面的這些就是我們今天所講的內容,對於 JSTL 的核心標簽庫我們還沒有講完,更不用說其他的標簽庫,但是我們給大家講解了如何自定義 JSTL 標簽,所以對自己感興趣的標簽可以去閱讀源代碼,相信大家掌握了自定義標簽應該對閱讀源代碼沒有多大的難點。
謝謝閱讀,希望對您有用,有不對的地方或者更好的建議還望指出!