1. 程式人生 > 其它 >07、Java--JSP自定義標籤

07、Java--JSP自定義標籤

自定義標籤

自定義標籤

自定義標籤主要用於移除Jsp頁面中的java程式碼。

在JSP中使用自定義標籤的開發步驟如下:

開發一個對應的Java類。
配置這個Java類,使它成為一個標籤。
使用tablib指令引入。

編寫一個實現Tag介面的Java類(標籤處理類)

public class ViewTag implements Tag {
    private PageContext mPageContext;
    @Override
    public void setPageContext(PageContext pageContext) {
        mPageContext = pageContext;
    }
    @Override
    public void setParent(Tag tag) {
    }
    @Override
    public Tag getParent() {
        return null;
    }
    @Override
    public int doStartTag() throws JspException {
        System.out.println("呼叫doStartTag()方法");
        HttpServletRequest request = (HttpServletRequest) mPageContext.getRequest();
        JspWriter out = mPageContext.getOut();
        String ip = request.getRemoteAddr();
        try {
            out.write(ip);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public int doEndTag() throws JspException {
        System.out.println("呼叫doEndTag()方法");
        return 0;
    }
    @Override
    public void release() {
        System.out.println("呼叫release()方法");
    }
}

在WEB-INF/目錄下新建tld檔案,在tld檔案中對標籤處理器類進行描述

legend.tld檔案的程式碼如下:

<?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">
    <!-- description用來新增對taglib(標籤庫)的描述 -->
    <description>開發的自定義標籤庫</description>
    <!--taglib(標籤庫)的版本號 -->
    <tlib-version>1.0</tlib-version>
    <short-name>GaclTagLibrary</short-name>
    <!--
        為自定義標籤庫設定一個uri,uri以/開頭,/後面的內容隨便寫,如這裡的/legend ,
        在Jsp頁面中引用標籤庫時,需要通過uri找到標籤庫
        在Jsp頁面中就要這樣引入標籤庫:<%@taglib uri="/legend" prefix="legend"%>
    -->
    <uri>/legend</uri>
    <!--一個taglib(標籤庫)中包含多個自定義標籤,每一個自定義標籤使用一個tag標記來描述  -->
    <!-- 一個tag標記對應一個自定義標籤 -->
    <tag>
        <description>這個標籤的作用是用來輸出客戶端的IP地址</description>
        <!--
            為標籤處理器類配一個標籤名,在Jsp頁面中使用標籤時是通過標籤名來找到要呼叫的標籤處理器類的
            通過viewIP就能找到對應的com.legend.tag.ViewTag類
         -->
        <name>viewIP</name>
        <!-- 標籤對應的處理器類-->
        <tag-class>com.legend.tag.ViewTag</tag-class>
        <body-content>empty</body-content>
    </tag>
</taglib>

在Jsp頁面中使用自定義標籤

使用"<%@taglib uri="標籤庫的uri" prefix="標籤的使用字首"%>"指令引入要使用的標籤庫。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="xdp" uri="/legend" %>
<html>
    <head>
        <title>輸出客戶端IP</title>
    </head>
    <body>
        使用自定義標籤獲取IP地址是:<xdp:viewIP/>
    </body>
</html>

輸出結果:

使用自定義標籤獲取IP地址是:127.0.0.1

這就是開發和使用自定義標籤的好處,可以讓我們的Jsp頁面上不巢狀java程式碼,下面我們看下自定義標籤的呼叫過程:

setPageContext(PageContext pc) -> setParent(Tag t) -> doStartTag() -> doEndTag() -> release()

傳統標籤(暫略)

傳統標籤在實際開發中由於技術過於落後,所以不再使用,這裡待以後補充。

簡單標籤使用

由於傳統標籤使用三個標籤介面來完成不同的功能,顯得過於繁瑣,不利於標籤技術的推廣, SUN公司為降低標籤技術的學習難度,在JSP 2.0中

定義了一個更為簡單、便於編寫和呼叫的SimpleTag介面來實現標籤的功能。

SimpleTag介紹

實現SimpleTag介面的標籤通常稱之為簡單標籤,簡單標籤共定義5個方法:

方法 描述
setJspContext() 用於把JSP頁面的pageContext物件傳遞給標籤處理器物件。
setParent() 用於把父標籤處理器物件傳遞給當前標籤處理器物件。
getParent() 用於獲得當前標籤的父標籤處理器物件。
setJspBody() 用於把代表標籤體的JspFragment物件傳遞給標籤處理器物件。
doTag() 重要,用於完成所有的標籤邏輯,包括輸出、迭代、修改標籤體內容等。

其中方法的執行順序如下:

開發簡單標籤

SUN公司針對SimpleTag介面提供了一個預設的實現類SimpleTagSupport,SimpleTagSupport類中實現了SimpleTag介面的所有方法,

因此我們可以編寫一個類繼承SimpleTagSupport類,然後根據業務需要再重寫doTag方法。

控制jsp頁面某一部分內容執行

SimpleTagDemo.java

public class SimpleTagDemo extends SimpleTagSupport {
    /**
     * 簡單標籤使用doTag()方法就可以完成所有業務邏輯
     */
    @Override
    public void doTag() throws JspException, IOException {
        // 得到代表jsp標籤提的JspFragment
        JspFragment jspFragment = this.getJspBody();
        // 得到jsp頁面的PageContext物件
        PageContext pageContext = (PageContext) jspFragment.getJspContext();
        // 呼叫JspWriter將標籤內容輸出到瀏覽器
        jspFragment.invoke(pageContext.getOut());
    }
}

在WEB-INF目錄下新建一個simpletag.tld檔案,然後在simpletag.tld檔案中新增對該標籤處理類的描述,如下:

<?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">
    <!-- description用來新增對taglib(標籤庫)的描述 -->
    <description>SimpleTag自定義標籤庫</description>
    <!--taglib(標籤庫)的版本號 -->
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <!--
        為自定義標籤庫設定一個uri,uri以/開頭,/後面的內容隨便寫,如這裡的/simpletag ,
        在Jsp頁面中引用標籤庫時,需要通過uri找到標籤庫
        在Jsp頁面中就要這樣引入標籤庫:<%@taglib uri="/simpletag" prefix="gacl"%>
    -->
    <uri>/simpletag</uri>
    <!--一個taglib(標籤庫)中包含多個自定義標籤,每一個自定義標籤使用一個tag標記來描述  -->
    <!-- 一個tag標記對應一個自定義標籤 -->
    <tag>
        <description>SimpleTag(簡單標籤)</description>
        <!--
            為標籤處理器類配一個標籤名,在Jsp頁面中使用標籤時是通過標籤名來找到要呼叫的標籤處理器類的
            通過demo1就能找到對應的com.legend.simple.SimpleTagDemo1類
         -->
        <name>demo</name>
        <!-- 標籤對應的處理器類-->
        <tag-class>com.legend.simple.SimpleTagDemo</tag-class>
        <!--
        tld檔案中有四種標籤體型別 :empty  JSP  scriptless  tagdepentend
            在簡單標籤(SampleTag)中標籤體body-content的值只允許是empty和scriptless,不允許設定成JSP,如果設定成JSP就會出現異常
            在傳統標籤中標籤體body-content的值只允許是empty和JSP。如果標籤體body-content的值設定成tagdepentend,那麼就表示標籤
            體裡面的內容是給標籤處理器類使用的。
        -->
        <body-content>scriptless</body-content>
    </tag>
</taglib>

在jsp頁面中匯入並使用自定義標籤,如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="legend" uri="/simpletag" %>
<html>
    <head>
        <title>簡單標籤控制標籤體是否執行</title>
    </head>
    <body>
        <legend:demo>
            legend
        </legend:demo>
    </body>
</html>

輸出結果:

legend

控制jsp頁面內容重複執行

如果要重複輸出的話,我們只需要修改上面的例子中的java程式碼即可,修改SimpleTagDemo1的程式碼如下:

public class SimpleTagDemo1 extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jspFragment = getJspBody();
        // 迴圈輸出五次即可
        for (int i = 0; i < 5; i++) {
            jspFragment.invoke(null);
        }
    }
}

執行效果如下:

legend legend legend legend legend

修改jsp頁面內容輸出

public class SimpleTagDemo1 extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jspFragment = getJspBody();
        StringWriter writer = new StringWriter();
        // 將標籤體的內容寫入到StringWriter流中
        jspFragment.invoke(writer);
        // 獲取StringWriter流的內容,轉成字串,並轉換為大寫形式
        String content = writer.getBuffer().toString();
        content = content.toUpperCase();
        PageContext context = (PageContext) jspFragment.getJspContext();
        // 將修改後的content輸出到瀏覽器
        context.getOut().write(content);
    }
}

輸出結果:

LEGEND

控制整個jsp頁面執行

編寫一個類繼承SimpleTagSupport,然後再重寫doTag方法,在doTag方法丟擲SkipPageException異常即可,jsp收到這個異常,將忽略標籤餘下jsp頁面的執行。

public class SimpleTagDemo4 extends SimpleTagSupport{
    @Override
    public void doTag() throws JspException, IOException {
        // 丟擲異常,在此處斷開後續執行
        throw new SkipPageException();
    }
}

修改jsp檔案如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="legend" uri="/simpletag" %>
<html>
    <head>
        <title>簡單標籤控制標籤體是否執行</title>
    </head>
    <body>
        <h1>人生得意須盡歡</h1>
        <legend:demo1/>
        <h1>莫使金樽空對月</h1>
    </body>
</html>

此時執行到自定義標籤則會丟擲異常,導致後續的內容無法執行,所以輸出結果是:

人生得意須盡歡

注意:

如果一個專案中包含多個tld的檔案,只需要保證uri不一樣即可,如果存在一樣的情況,可以在jsp頁面使用另外一種引入方式:

<%@taglib uri="/WEB-INF/simpletag.tld" prefix="legend"%>

JspFragment類介紹

javax.servlet.jsp.tagext.JspFragment類是在JSP2.0中定義的,它的例項物件代表JSP頁面中的一段符合JSP語法規範的JSP片段,這段JSP片段中不能包含JSP指令碼元素。

WEB容器在處理簡單標籤的標籤體時,會把標籤體內容用一個JspFragment物件表示,並呼叫標籤處理器物件的setJspBody方法把JspFragment物件傳遞給標籤處理器物件。

JspFragment類中只定義了兩個方法,如下所示:

getJspContext():用於返回代表呼叫頁面的JspContext物件.
invoke(Writer out):用於執行JspFragment物件所代表的JSP程式碼片段,引數out用於將JspFragment物件的執行結果寫入到輸出流中,
如果傳遞引數out的值為null,則將執行結果寫入到JspContext.getOut()方法返回的輸出流物件中。

spFragment.invoke方法是JspFragment最重要的方法,利用這個方法可以控制是否執行和輸出標籤體的內容、是否迭代執行標籤體的內容或對標籤體的執行結果進行修改後再輸出。

開發屬性標籤

自定義標籤可以定義一個或多個屬性,這樣,在JSP頁面中應用自定義標籤時就可以設定這些屬性的值,通過這些屬性為標籤處理器傳遞引數資訊,從而提高標籤的靈活性和複用性。

要想讓一個自定義標籤具有屬性,通常需要完成兩個任務:

在標籤處理器中編寫每個屬性對應的setter方法
在TLD檔案中描術標籤的屬性

為自定義標籤定義屬性時,每個屬性都必須按照JavaBean的屬性命名方式,在標籤處理器中定義屬性名對應的setter方法,用來接收 JSP頁面呼叫自定義標籤時傳遞進來的屬性值。

在標籤處理器中定義相應的set方法後,JSP引擎在解析執行開始標籤前,也就是呼叫doStartTag方法前,會呼叫set屬性方法,為標籤設定屬性。

tld檔案中用於描述標籤屬性的<attribute>元素說明

<tag>元素的<attribute>子元素用於描述自定義標籤的一個屬性,自定義標籤所具有的每個屬性都要對應一個<attribute>元素

<tag>
    <!-- 標籤名 -->
    <name>demo</name>
    <!-- 標籤處理器類-->
    <tag-class>com.legend.simple.SimpleTagDemo</tag-class>
    <!-- 標籤體允許的內容-->
    <body-content>scriptless</body-content>
    
    <!-- 標籤的屬性描述 -->
    <attribute>
        <description>描述標籤的count屬性</description>
        <!-- 標籤的count屬性 -->
        <name>count</name>
        <required>true</required>
        <!-- rtexprvalue用來指示標籤的屬性值是否可以是一個表示式,
        一般設定為true,true就表示允許標籤的屬性值可以是一個表示式-->
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>

<attribute\>元素的子元素說明:

屬性名 是否必須 描述
description 用於指定屬性的描述資訊。
name 用於指定屬性的名稱。大小寫敏感,不能以jsp、_jsp、java和sun開頭。
required 用於指定在JSP頁面中呼叫自定義標籤時是否必須設定這個屬性。true表示必須設定,false則可以設定或不設定該屬性。
rtexprvalue 用於執行屬性值是一個靜態值或動態值,true表示可以指定屬性值是動態元素,false則表示只能指定屬性的值為靜態的文字值。
type 用於指定屬性值的Java型別。

範例1:通過標籤的屬性控制標籤體的執行次數

CustomAttrTag.java

public class CustomAttrTag extends SimpleTagSupport {
    private int count;
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jspFragment = getJspBody();
        for (int i = 0; i < count; i++) {
            jspFragment.invoke(null);
        }
    }
}

在WEB-INF目錄下的tld檔案中新增對該標籤的描述,如下所示:

<?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">
    <description>簡單屬性標籤</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <uri>/simpleattr</uri>
    <tag>
        <!-- 標籤名 -->
        <name>attrtag</name>
        <!-- 標籤處理器類-->
        <tag-class>com.legend.simple.CustomAttrTag</tag-class>
        <!-- 標籤體允許的內容-->
        <body-content>scriptless</body-content>
        <!-- 標籤的屬性描述 -->
        <attribute>
            <description>描述標籤的count屬性</description>
            <!-- 標籤的count屬性 -->
            <name>count</name>
            <required>true</required>
            <!-- rtexprvalue用來指示標籤的屬性值是否可以是一個表示式,
            一般設定為true,true就表示允許標籤的屬性值可以是一個表示式-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

在jsp頁面引入標籤庫並使用自定義標籤

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="legend" uri="/simpleattr" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%--使用自定義屬性標籤顯示結果--%>
        <legend:attrtag count="5">
            <h1>Hello World</h1>
        </legend:attrtag>
    </body>
</html>

輸出結果:

Hello World
Hello World
Hello World
Hello World
Hello World

注意:如果標籤的屬性值是8種基本資料型別,那麼在JSP頁面在傳遞字串時,JSP引擎會自動轉換成相應的型別,但如果標籤的屬性值是複合資料型別,那麼JSP引擎是無法自動轉換的。

範例2:標籤屬性值是複合資料型別的賦值

CustomAttrTag.java

public class CustomAttrTag extends SimpleTagSupport {
    private Date date;
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    @Override
    public void doTag() throws JspException, IOException {
        getJspContext().getOut().write(date.toLocaleString());
    }
}

在WEB-INF目錄下的tld檔案中新增對該標籤的描述,如下所示:

<?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">
    <description>簡單屬性標籤</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <uri>/newSimpleAttr</uri>
    <tag>
        <name>attrtag</name>
        <tag-class>com.legend.simple.CustomAttrTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <description>描述標籤的count屬性</description>
            <name>date</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

在jsp頁面引入標籤庫並使用自定義標籤:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/newSimpleAttr" prefix="legend"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>如果標籤接收的屬性值是一個複合資料型別,該如何給標籤的屬性賦值</title>
    </head>
    <body>
        <%--
        在jsp頁面中使用自定義標籤,標籤有一個date屬性 ,是一個複合資料型別
          如果標籤的屬性值是8種基本資料型別,那麼在JSP頁面在傳遞字串時,JSP引擎會自動轉換成相應的型別
          但如果標籤的屬性值是複合資料型別,那麼JSP引擎是無法自動轉換的--%>
        <%--如果一定要給標籤的複合屬性賦值,那麼可以採用表示式的方式給複合屬性賦值,如下所示: --%>
        <%
            Date d = new Date();
            request.setAttribute("date", d);
        %>
        <legend:attrtag date="${date}"/>
        <hr/>
        <legend:attrtag date="<%=new Date()%>"/>
    </body>
</html>

輸出結果:

2017-7-4 4:25:20


2017-7-4 4:25:20

簡單標籤實戰

開發防盜鏈標籤

編寫標籤處理器類:RefererTag.java

public class RefererTag extends SimpleTagSupport {
    // 網站域名
    private String site;
    // 要跳轉的頁面
    private String page;
    @Override
    public void doTag() throws JspException, IOException {
        PageContext pageContext = (PageContext) getJspContext();
        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
        // 獲取請求的來路
        String referer = request.getHeader("referer");
        // 如果來路是空或者不是我們自己的網址則重定向到page頁面
        if (referer == null || !referer.startsWith(site)){
            HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
            String webRoot = request.getContextPath();
            // 重定向到web頁面
            if (page.startsWith(webRoot)) {
                response.sendRedirect(page);
            }else {
                response.sendRedirect(webRoot + page);
            }
            // 重定向後,控制保護的頁面不被執行
            throw new SkipPageException();
        }
    }
    public void setSite(String netSite) {
        this.site = netSite;
    }
    public void setPage(String page) {
        this.page = page;
    }
}

在WEB-INF目錄下tld檔案中新增對該標籤的描述

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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">
    <description>防盜鏈標籤</description>
    <tlib-version>1.0</tlib-version>
    <short-name>TagLib</short-name>
    <uri>/legendTagLib</uri>
    <tag>
        <name>referer</name>
        <tag-class>com.legend.simple.RefererTag</tag-class>
        <body-content>empty</body-content>
        <!--兩個自定義標籤屬性-->
        <attribute>
            <description>描述標籤的site屬性</description>
            <name>site</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <description>描述標籤的page屬性</description>
            <name>page</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

在jsp頁面中匯入標籤庫並使用防盜鏈標籤

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="legend" uri="/legendTagLib"%>
<%--在Jsp頁面使用防盜鏈標籤
    當用戶嘗試通過URL地址訪問頁面時,防盜鏈標籤的標籤處理器就會將其重定向到其他jsp檔案--%>
<legend:referer site="http://localhost:8080" page="/index.jsp"/>
<html>
    <head>
        <title>防盜鏈標籤測試</title>
    </head>
    <body>
        網站內部資料
    </body>
</html>

其中跳轉到到的index.jsp標籤如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>公司網站</title>
    </head>
    <body>
        <h1>網站首頁</h1>
        <h1><a href="referertag.jsp">檢視資料</a></h1>
    </body>
</html>

當我們通過 http://localhost:8080/referertag.jsp 去訪問時,會自動跳轉到index.jsp。如果想檢視referertag.jsp的內容可以直接通過index.jsp中的檢視網站即可。

開發<c:if>標籤

編寫標籤處理器類:IFTag.java

public class IfTag extends SimpleTagSupport{
    private boolean flag;
    @Override
    public void doTag() throws JspException, IOException {
        PageContext pageContext = (PageContext) getJspContext();
        if (flag) {
            pageContext.getOut().write("您好,世界!");
        }
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

在WEB-INF目錄下tld檔案中新增對該標籤的描述

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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">
    <description>if標籤</description>
    <tlib-version>1.0</tlib-version>
    <short-name>TagLib</short-name>
    <tag>
        <description>if標籤</description>
        <name>if</name>
        <tag-class>com.legend.simple.IfTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <description>描述標籤的site屬性</description>
            <name>flag</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

在jsp頁面中匯入標籤庫並使用if標籤

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="/WEB-INF/ifTag.tld"%>
<html>
    <head>
        <title>if標籤測試</title>
    </head>
    <body>
        <%--if標籤的flag屬性值為true ,標籤體的內容會輸出--%>
        <c:if flag="true"/>
        <%--if標籤的flag屬性值為false ,標籤體的內容不會輸出--%>
        <c:if flag="false"/>
    </body>
</html>

開發when和otherwise

<c:when>標籤和<c:otherwise>標籤對應著兩個不同的標籤處理器類,我們希望做到的效果是,如果<c:when>標籤執行了,那麼就

<c:otherwise>標籤就不要再執行,所需需要建立父標籤來讓兩個標籤共享變數。

開發父標籤ChooseTag.java

public class OtherWiseTag extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        // 獲取父標籤例項
        ChooseTag parentTag = (ChooseTag) getParent();
        // 如果父標籤下的when標籤沒有執行過
        if (parentTag.isExecute() == false) {
            getJspBody().invoke(null);
            //設定父標籤的isExecute屬性為true,通知父標籤自己已經執行過
            parentTag.setExecute(true);
        }
    }
}
  • 開發when標籤和otherwise標籤

whenTag.java

public class WhenTag extends SimpleTagSupport {
    private boolean test;
    @Override
    public void doTag() throws JspException, IOException {
        // 獲取標籤的父標籤
        ChooseTag parentTag = (ChooseTag) getParent();
        if (test == true && parentTag.isExecute() == false) {
            // 輸出標籤的內容
            getJspBody().invoke(null);
            // 將父標籤的isExecute設定為true,通知父標籤自己已經執行過
            parentTag.setExecute(true);
        }
    }
    public void setTest(boolean test) {
        this.test = test;
    }
}

OtherWise.java

public class OtherWiseTag extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        // 獲取父標籤例項
        ChooseTag parentTag = (ChooseTag) getParent();
        // 如果父標籤下的when標籤沒有執行過
        if (parentTag.isExecute() == false) {
            getJspBody().invoke(null);
            //設定父標籤的isExecute屬性為true,通知父標籤自己已經執行過
            parentTag.setExecute(true);
        }
    }
}

在WEB-INF目錄下tld檔案中新增對ChooseTag、WhenTag、OtherWiseTag這三對標籤的描述

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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">
    <description>when和otherwise標籤</description>
    <tlib-version>1.0</tlib-version>
    <short-name>choose</short-name>
    <tag>
        <description>choose標籤</description>
        <name>choose</name>
        <tag-class>com.legend.simple.ChooseTag</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    <tag>
        <description>when標籤</description>
        <name>when</name>
        <tag-class>com.legend.simple.WhenTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <description>when標籤的test屬性</description>
            <name>test</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    <tag>
        <description>otherwise標籤</description>
        <name>otherwise</name>
        <tag-class>com.legend.simple.OtherWiseTag</tag-class>
        <body-content>scriptless</body-content>
    </tag>
</taglib>

在jsp頁面中匯入標籤庫並測試when和otherwise標籤

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="/WEB-INF/chooseTag.tld"%>
<html>
    <head>
        <title>when和otherwise標籤</title>
    </head>
    <body>
        <c:choose>
            <c:when test="${user==null}">
                when標籤輸出的內容:<h3>使用者為空</h3>
            </c:when>
            <c:otherwise>
                使用者不為空
            </c:otherwise>
        </c:choose>
        <hr/>
        <c:choose>
            <c:when test="${user!=null}">
                使用者不為空
            </c:when>
            <c:otherwise>
                otherwise標籤標籤體輸出的內容:<h3>使用者為空</h3>
            </c:otherwise>
        </c:choose>
    </body>
</html>

輸出結果:

when標籤輸出的內容:
使用者為空
otherwise標籤標籤體輸出的內容:
使用者為空

JSTL庫

JSTL標籤庫的使用是為彌補html標籤的不足,規範自定義標籤的使用而誕生的。使用JSLT標籤的目的就是不希望在jsp頁面中出現java邏輯程式碼。

JSTL標籤庫有很多種分類,如下所示:

核心標籤(用得最多)
國際化標籤(I18N格式化標籤)
資料庫標籤(SQL標籤,很少使用)
XML標籤(幾乎不用)
JSTL函式(EL函式)

JSTL的核心標籤庫標籤共13個,使用這些標籤能夠完成JSP頁面的基本功能,減少編碼工作。從功能上可以分為4類:表示式控制標籤、流程控制標籤、

迴圈標籤、URL操作標籤。

(1)表示式控制標籤:out標籤、set標籤、remove標籤、catch標籤。
(2)流程控制標籤:if標籤、choose標籤、when標籤、otherwise標籤。
(3)迴圈標籤:forEach標籤、forTokens標籤。
(4)URL操作標籤:import標籤、url標籤、redirect標籤、param標籤。

在JSP頁面引入核心標籤庫的程式碼為:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

如果使用的idea的話則需要手動去引入JSTL庫:

首先下載JSTL的庫進行解壓,然後拷貝lib下的兩個jar包到工程的WEB-INF下的lib資料夾下。

然後選擇File -> Setting -> languages&Frameworks -> Schemas and DTDs -> +號,然後在URL輸出如下內容:

http://java.sun.com/jsp/jstl/core

之後選擇explorer找到解壓檔案的tld目錄下的c.tld檔案,然後儲存即可。

表示式標籤

<c:out \>標籤

<c:out \>標籤主要是用來輸出資料物件(字串、表示式)的內容或結果。

<c:out \>標籤的使用有兩種語法格式:

【語法1】:<c:out value=”要顯示的資料物件” [escapeXml=”true|false”] [default=”預設值”]/>
【語法2】:<c:out value=”要顯示的資料物件” [escapeXml=”true|false”]>預設值</c:out>

這兩種方式沒有本質的區別,只是格式上的差別。[escapeXml=”true|false”] [default=”預設值”]這些使用[]屬性表示是不是必須的。

<c:out>標籤的屬性如下所示:

屬性名 是否支援EL 屬性型別 描述
value true Object 指定要輸出的內容。
escapeXml true Boolean 指定是否將特殊字元進行HTML編碼轉換後再進行輸出。
default true Object 當value屬性的值為空時,所輸出的預設值。

範例:<c:count>標籤的使用:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <title>JSTL--out標籤的使用</title>
    </head>
    <body>
        <h3><c:out value="下面的程式碼演示了c:out的使用,以及在不同屬性值狀態下的結果。"/></h3>
        <hr/>
        <ul>
            <%--(1)直接輸出了一個字串。 --%>
            <li>(1)<c:out value="JSTL的out標籤的使用" /></li>
            <li>(2)<c:out value="<a href='http://www.cnblogs.com/'>點選連結到部落格園</a>" /></li>
            <%--escapeXml="false"表示value值中的html標籤不進行轉義,而是直接輸出 --%>
            <li>(3)<c:out value="<a href='http://www.cnblogs.com/'>點選連結到部落格園</a>" escapeXml="false"/></li>
            <%--(4)字串中有轉義字元,但在預設情況下沒有轉換。 --%>
            <li>(4)<c:out value="&lt未使用字元轉義&gt" /></li>
            <%--(5)使用了轉義字元&lt和&gt分別轉換成<和>符號。 --%>
            <li>(5)<c:out value="&lt使用字元轉義&gt" escapeXml="false"></c:out></li>
            <%--(6)設定了預設值,從EL表示式${null}得到空值,所以直接輸出設定的預設值。 --%>
            <li>(6)<c:out value="${null}">使用了預設值</c:out></li>
            <%--(7)未設定預設值,輸出結果為空。 --%>
            <li>(7)<c:out value="${null}"></c:out></li>
            <%--(8)設定了預設值,從EL表示式${null}得到空值,所以直接輸出設定的預設值。 --%>
            <li>(8)<c:out value="${null}" default="預設值"/></li>
            <%--(9)未設定預設值,輸出結果為空。 --%>
            <li>(9)<c:out value="${null}"/></li>
        </ul>
    </body>
</html>

<c:set>標籤

<c:set>標籤用於把某一個物件存在指定的域範圍內,或者將某一個物件儲存到Map或者JavaBean物件中。

<c:set>標籤的使用有四種語法格式:

語法1:存值,把一個值放在指定的域範圍內。
  <c:set value=”值1” var=”name1” [scope=”page|request|session|application”]/>
  含義:把一個變數名為name1值為“值1”的變數儲存在指定的scope範圍內。
語法2:
  <c:set var=”name2” [scope=”page|request|session|application”]>
    值2
  </c:set>
  含義:把一個變數名為name2,值為值2的變數儲存在指定的scope範圍內。
語法3:
  <c:set value=”值3” target=”JavaBean物件” property=”屬性名”/>
  含義:把一個值為“值3”賦值給指定的JavaBean的屬性名。相當與setter()方法。
語法4:
  <c:set target=”JavaBean物件” property=”屬性名”>
    值4
  </c:set>
    含義:把一個值4賦值給指定的JavaBean的屬性名。

語法1和語法2是向scope範圍內儲存一個值,語法3和語法4是給指定的JavaBean賦值。

<c:set>標籤的屬性如下所示:

屬性名 是否支援EL 屬性型別 描述
value true Object 用於指定屬性值。
var false String 用於指定要設定的Web域屬性的名稱。
scope false String 用於指定屬性所在的Web域。
target true Object 用於指定要設定屬性的物件,這個物件必須是JavaBean或Map。
property true String 用於指定當前要為物件設定的屬性名稱。

範例:<c:set>標籤的使用:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="person" class="com.legend.jstl.Person"/>
<%--負責例項化Bean,id指定例項化後的物件名,可以通過${person}得到person在記憶體中的值--%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL--set標籤</title>
    </head>
    <body>
        <h3>程式碼給出了給指定scope範圍賦值的示例。</h3>
        <ul>
            <%--通過<c:set>標籤將data1的值放入page範圍中。--%>
            <li>把一個值放入page域中:<c:set var="data1" value="legend" scope="page"/></li>
            <%--使用EL表示式從pageScope得到data1的值。--%>
            <li>從page域中得到值:${pageScope.data1}</li>
            <%--通過<c:set>標籤將data2的值放入request範圍中。--%>
            <li>把一個值放入request域中:<c:set var="data2" value="vincent" scope="request"/></li>
            <%--使用EL表示式從requestScope得到data2的值。--%>
            <li>從request域中得到值:${requestScope.data2}</li>
            <%--通過<c:set>標籤將值name1的值放入session範圍中。--%>
            <li>把一個值放入session域中。<c:set var="name1" value="uding" scope="session"></c:set></li>
            <%--使用EL表示式從sessionScope得到name1的值。--%>
            <li>從session域中得到值:${sessionScope.name1} </li>
            <%--把name2放入application範圍中。 --%>
            <li>把一個值放入application域中。<c:set var="name2" scope="application">kevin</c:set></li>
            <%--使用EL表示式從application範圍中取值,用<c:out>標籤輸出使得頁面規範化。 --%>
            <li>使用out標籤和EL表示式巢狀從application域中得到值:
                <c:out value="${applicationScope.name2}">未得到name的值</c:out>
            </li>
            <%--不指定範圍使用EL自動查詢得到值 --%>
            <li>未指定scope的範圍,會從不同的範圍內查詢得到相應的值:${data1}、${data2}、${name1}、${name2}</li>
        </ul>
        <hr/>
        <h3>使用Java指令碼實現以上功能</h3>
        <ul>
            <%--注意:使用<%=%>的方式代替out.println()比較好--%>
            <li>把一個值放入page域中。<%pageContext.setAttribute("data1","legend");%></li>
            <li>從page域中得到值:<%out.println(pageContext.getAttribute("data1"));%></li>
            <li>把一個值放入request域中。<%request.setAttribute("data2","vincent");%></li>
            <li>從request域中得到值:<%out.println(request.getAttribute("data2"));%></li>
            <li>把一個值放入session域中。<%session.setAttribute("name1","uding");%></li>
            <li>從session中域得到值:<%=session.getAttribute("name1") %></li>
            <li>把另一個值放入application域中。<%application.setAttribute("name2","kevin");%></li>
            <li> 從application域中得到值:<%=application.getAttribute("name2")%>;</li>
            <li>未指定scope的範圍,會從不同的範圍內查詢得到相應的值:
                <%=pageContext.findAttribute("data1")%>、
                <%=pageContext.findAttribute("data2")%>、
                <%=pageContext.findAttribute("name1")%>、
                <%=pageContext.findAttribute("name2")%>
            </li>
        </ul>
        <hr/>
        <h3>操作JavaBean,設定JavaBean的屬性值</h3>
        <%--設定JavaBean的屬性值,等同與setter方法,Target指向例項化後的物件,property指向要插入值的引數名。
        注意:使用target時一定要指向例項化後的JavaBean物件,要跟<jsp:useBean>配套使用--%>
        <c:set target="${person}" property="name">legend</c:set>
        <c:set target="${person}" property="age">25</c:set>
        <ul>
            <li>使用的目標物件為:${person}</li>
            <li>從Bean中獲得的name值為:<c:out value="${person.name}"></c:out></li>
            <li>從Bean中獲得的age值為:<c:out value="${person.age}"></c:out></li>
        </ul>
        <hr/>
        <h3>操作Map</h3>
        <%
            Map map = new HashMap();
            request.setAttribute("map",map);
        %>
        <%--將data物件的值儲存到map集合中 --%>
        <c:set property="data" value="legend" target="${map}"/>
        ${map.data}
    </body>
</html>

jsp頁面中使用到的javabean.Person類的程式碼如下:

public class Person {
    private String name;
    private String age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
}

輸出結果:

程式碼給出了給指定scope範圍賦值的示例。
把一個值放入page域中:
從page域中得到值:legend
把一個值放入request域中:
從request域中得到值:vincent
把一個值放入session域中。
從session域中得到值:uding
把一個值放入application域中。
使用out標籤和EL表示式巢狀從application域中得到值: kevin
未指定scope的範圍,會從不同的範圍內查詢得到相應的值:legend、vincent、uding、kevin
使用Java指令碼實現以上功能
把一個值放入page域中。
從page域中得到值:legend
把一個值放入request域中。
從request域中得到值:vincent
把一個值放入session域中。
從session中域得到值:uding
把另一個值放入application域中。
從application域中得到值:kevin
kevin
未指定scope的範圍,會從不同的範圍內查詢得到相應的值: legend、 vincent、 uding、 kevin
操作JavaBean,設定JavaBean的屬性值
使用的目標物件為:com.legend.jstl.Person@2b03228f
從Bean中獲得的name值為:legend
從Bean中獲得的age值為:25
操作Map
legend

remove標籤

<c:remove>標籤主要用來從指定的JSP範圍內移除指定的變數。

<c:remove var=”變數名” [scope=”page|request|session|application”]/>

範例:<c:remove>標籤的使用:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL--remove標籤</title>
    </head>
    <body>
        <ul>
            <c:set var="name" scope="session">legend</c:set>
            <c:set var="age" scope="session">25</c:set>
            <li><c:out value="${sessionScope.name}"></c:out></li>
            <li><c:out value="${sessionScope.age}"></c:out></li>
            <%--使用remove標籤移除age變數 --%>
            <c:remove var="age" />
            <li><c:out value="${sessionScope.name}"></c:out></li>
            <li><c:out value="${sessionScope.age}"></c:out></li>
        </ul>
    </body>
</html>

輸出結果:

legend
25
legend

<c:catch>標籤

<c:catch>標籤用於捕獲巢狀在標籤體中的內容丟擲的異常。

<c:catch [var="varName"]>容易產生異常的程式碼</c:catch>

var屬性用於標識<c:catch>標籤捕獲的異常物件,它將儲存在page這個Web域中。

範例:<c:catch>標籤的使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL: --表示式控制標籤“catch”標籤例項</title>
    </head>
    <body>
        <h4>catch標籤例項</h4>
        <hr>
        <%--把容易產生異常的程式碼放在<c:catch></c:catch>中,
        自定義一個變數errorInfo用於儲存異常資訊 --%>
        <c:catch var="errorInfo">
            <%--實現了一段異常程式碼,向一個不存在的JavaBean中插入一個值--%>
            <c:set target="person" property="hao"></c:set>
        </c:catch>
        <%--用EL表示式得到errorInfo的值,並使用<c:out>標籤輸出 --%>
        異常:<c:out value="${errorInfo}" /><br />
        異常 errorInfo.getMessage:<c:out value="${errorInfo.message}" /><br />
        異常 errorInfo.getCause:<c:out value="${errorInfo.cause}" /><br />
        異常 errorInfo.getStackTrace:<c:out value="${errorInfo.stackTrace}" />
    </body>
</html>

執行結果:

catch標籤例項
異常:javax.servlet.jsp.JspTagException: Invalid property in &lt;set&gt;: "hao"
異常 errorInfo.getMessage:Invalid property in &lt;set&gt;: "hao"
異常 errorInfo.getCause:
異常 errorInfo.getStackTrace:[Ljava.lang.StackTraceElement;@4afd104f

流程控制標籤

<c:if>標籤

<c:if>標籤和程式中的if語句作用相同,用來實現條件控制。

【語法1】:沒有標籤體內容(body)
  <c:if test="testCondition" var="varName" [scope="{page|request|session|application}"]/>
【語法2】:有標籤體內容
  <c:if test="testCondition" [var="varName"] [scope="{page|request|session|application}"]>
        標籤體內容
  </c:if>
【引數說明】:
 (1)test屬性用於存放判斷的條件,一般使用EL表示式來編寫。
 (2)var屬性用來存放判斷的結果,型別為true或false。
 (3)scopes屬性用來指定var屬性存放的範圍。

<c:if>標籤的屬性如下所示:

屬性名 是否支援EL 屬性型別 描述
test true boolean 決定是否處理標籤體中的內容的條件表示式
var false String 將test屬性的執行結果儲存到某個Web域中的某個屬性的名稱。
scope false String 指定將test屬性的執行結果儲存到哪個Web域中。

範例:<c:if>標籤的使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <title>JSTL--if標籤</title>
    </head>
    <body>
        <h4>if標籤示例</h4>
        <hr>
        <form action="index.jsp" method="post">
            <input type="text" name="uname" value="${param.uname}">
            <input type="submit" value="登入">
        </form>
        <%--使用if標籤進行判斷並把檢驗後的結果賦給adminchock,儲存在預設的page範圍中。 --%>
        <c:if test="${param.uname=='admin'}" var="adminchock">
            <%--可以把adminchock的屬性範圍設定為session,這樣就可以在其他的頁面中得到adminchock的值,
            使用<c:if text=”${adminchock}”><c:if>判斷,實現不同的許可權。 --%>
            <c:out value="管理員歡迎您!"/>
        </c:if>
        <%--使用EL表示式得到adminchock的值,如果輸入的使用者名稱為admin將顯示true。 --%>
        ${adminchock}
    </body>
</html>

輸出結果:

  • <c:choose>、<c:when>和<c:otherwise>

<c:choose> <c:when>和<c:otherwise>這3個標籤通常情況下是一起使用的,<c:choose>標籤作為<c:when>和<c:otherwise>標籤的父標籤來使用。

使用<c:choose>,<c:when>和<c:otherwise>三個標籤,可以構造類似 “if-else if-else” 的複雜條件判斷結構。

<c:choose>
     <c:when test="條件1">
          //業務邏輯1
     <c:when>
       <c:when test="條件2">
          //業務邏輯2
     <c:when>
       <c:when test="條件n">
          //業務邏輯n
     <c:when>
     <c:otherwise>
          //業務邏輯
       </c:otherwise>
</c:choose>

範例:<c:choose>及其巢狀標籤用法

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%--引入JSTL核心標籤庫 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL-- choose及其巢狀標籤</title>
    </head>
    <body>
        <h4>choose及其巢狀標籤</h4>
        <hr/>
        <%--通過set標籤設定score的值為85 --%>
        <c:set var="score" value="85"/>
        <c:choose>
            <%--使用<c:when>進行條件判斷。
                如果大於等於90,輸出“您的成績為優秀”;
                如果大於等於70小於90,輸出“您的成績為良好”;
                大於等於60小於70,輸出“您的成績為及格”;
                其他(otherwise)輸出“對不起,您沒能通過考試”。
             --%>
            <c:when test="${score>=90}">
                你的成績為優秀!
            </c:when>
            <c:when test="${score>70 && score<90}">
                您的成績為良好!
            </c:when>
            <c:when test="${score>60 && score<70}">
                您的成績為及格
            </c:when>
            <c:otherwise>
                對不起,您沒有通過考試!
            </c:otherwise>
        </c:choose>
    </body>
</html>

執行結果:

choose及其巢狀標籤示例
您的成績為良好!

<c:forEach>標籤

<c:forEach>標籤根據迴圈條件遍歷集合(Collection)中的元素。

<c:forEach
  var=”name”
  items=”Collection”
  varStatus=”StatusName”
  begin=”begin”
  end=”end”
  step=”step”>
    本體內容
</c:forEach>
【引數解析】:
  (1)var設定變數名用於儲存從集合中取出元素。
  (2)items指定要遍歷的集合。
  (3)varStatus設定變數名,該變數用於存放集合中元素的資訊。    
  (4)begin、end用於指定遍歷的起始位置和終止位置(可選)。
  (5)step指定迴圈的步長

<c:forEach>包含如下屬性:

屬性名 是否支援EL 屬性型別 描述
var NO String 必須具備,且無預設值。
items YES Arrays Collection Iterator Enumeration Map String[] args 必須具備,且無預設值。
begin YES int 非必須具備,預設值為0。
end YES int 非必須具備,預設值為集合最後一個元素。
step YES int 非必須具備,預設值為1。
varStatus NO String 非必須具備,且無預設值。 varStatus包含四個狀態: index:當前迴圈的索引值。 count:迴圈的次數。 first:是否為第一個位置。 last:是否為最後一個位置。

範例:<c:forEach>標籤的使用:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page import="java.util.ArrayList"%>
<html>
    <head>
        <title>JSTL: -- forEach標籤例項</title>
    </head>
    <body>
        <h4><c:out value="forEach例項"/></h4>
        <% 
               List<String>list = new ArrayList<String>(); 
               list.add(0, "貝貝"); 
               list.add(1, "晶晶"); 
               list.add(2, "歡歡"); 
               list.add(3, "瑩瑩"); 
               list.add(4, "妮妮"); 
               request.setAttribute("list", list); 
        %>
        <B><c:out value="不指定begin和end的迭代:" /></B><br>
        <%--不使用begin和end的迭代,從集合的第一個元素開始,遍歷到最後一個元素。 --%>
        <c:forEach var="fuwa" items="${list}">
            &nbsp;<c:out value="${fuwa}"/><br/>
        </c:forEach>
        <B><c:out value="指定begin和end的迭代:" /></B><br>
        <%--指定begin的值為1、end的值為3、step的值為2,
            從第二個開始首先得到晶晶,每兩個遍歷一次,
            則下一個顯示的結果為瑩瑩,end為3則遍歷結束。 --%>
        <c:forEach var="fuwa" items="${list}" begin="1" end="3" step="2">
            &nbsp;<c:out value="${fuwa}"/><br/>
        </c:forEach>
        <B><c:out value="輸出整個迭代的資訊:" /></B><br>
        <%--指定varStatus的屬性名為s,並取出儲存的狀態資訊 --%>
        <c:forEach var="fuwa" 
                   items="${list}" 
                   begin="3" 
                   end="4" 
                   varStatus="s" 
                   step="1">
             &nbsp;<c:out value="${fuwa}" />的四種屬性:<br>
             &nbsp;&nbsp;&nbsp;&nbsp;所在位置,即索引:<c:out value="${s.index}" /><br>
             &nbsp;&nbsp;&nbsp;&nbsp;總共已迭代的次數:<c:out value="${s.count}" /><br>
             &nbsp;&nbsp;&nbsp;&nbsp;是否為第一個位置:<c:out value="${s.first}" /><br>
             &nbsp;&nbsp;&nbsp;&nbsp;是否為最後一個位置:<c:out value="${s.last}" /><br>  
        </c:forEach>
    </body>
</html>

<c:forTokens>標籤

<c:forTokens>標籤用於瀏覽字串,並根據指定的字元將字串擷取。

<c:forTokens items=”strigOfTokens”
        delims=”delimiters”
        [var=”name”
        begin=”begin”
        end=”end”
        step=”len”
        varStatus=”statusName”] >
    本體內容
</c:forTokens>
【引數說明】
  (1)items指定被迭代的字串。
  (2)delims指定使用的分隔符。
  (3)var指定用來存放遍歷到的成員。
  (4)begin指定遍歷的開始位置(int型從取值0開始)。
  (5)end指定遍歷結束的位置(int型,預設集合中最後一個元素)。
  (6)step遍歷的步長(大於0的整型)。
  (7)varStatus存放遍歷到的成員的狀態資訊。

範例:<c:forTokens>標籤的使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL: -- forTokens標籤例項</title>
    </head>
    <body>
        <h4><c:out value="forToken例項"/></h4>
        <hr/>
        <%--提示:分隔符的作用是根據標識,擷取字串。
            如果未設定分隔符或在字串中沒有找到分隔付,將把整個元素作為一個元素擷取。
            在實際應用中用於在除去某些符號在頁面中顯示。 --%>
        <c:forTokens var="str" items="北、京、歡、迎、您" delims="、">
            <c:out value="${str}"></c:out><br/>
        </c:forTokens>
        <br/>
        <c:forTokens items="123-4567-8854" delims="-" var="t">
            <c:out value="${t}"></c:out><br/>
        </c:forTokens>
        <br/>
        <c:forTokens items="1*2*3*4*5*6*7" 
                    delims="*" 
                    begin="1" 
                    end="3" 
                    var="n" 
                    varStatus="s">
                     &nbsp;<c:out value="${n}" />的四種屬性:<br>
                      &nbsp;&nbsp;&nbsp;&nbsp;所在位置,即索引:<c:out value="${s.index}" /><br>
                      &nbsp;&nbsp;&nbsp;&nbsp;總共已迭代的次數:<c:out value="${s.count}" /><br>
                      &nbsp;&nbsp;&nbsp;&nbsp;是否為第一個位置:<c:out value="${s.first}" /><br>
                      &nbsp;&nbsp;&nbsp;&nbsp;是否為最後一個位置:<c:out value="${s.last}" /><br>
        </c:forTokens>
    </body>
</html>

URI操作標籤

  • <c:import>標籤

    該標籤可以把其他靜態或動態檔案包含到本JSP頁面,與<jsp:include>的區別為:<jsp:include>只能包含同一個web應用中的檔案。而<c:import>可以包含其他web應

用中的檔案,甚至是網路上的資源。

【語法1】:
    <c:import
        url=”url”
        [context=”context”]
        [value=”value”]
        [scope=”page|request|session|application”]
        [charEncoding=”encoding”]/>
【語法2】:
    <c:import
        url=”url”
        varReader=”name”
        [context=”context”]
        [charEncoding=”encoding”]/>
【引數說明】:
    (1)URL為資源的路徑,當引用的資源不存在時系統會丟擲異常,因此該語句應該放在<c:catch></c:catch>語句塊中捕獲。
    (2)引用資源有兩種方式:絕對路徑和相對路徑。
        使用絕對路徑的示例如下:<c:import url=”http://www.baidu.com”>
        使用相對路徑的示例如下:<c:import url=”aa.txt”>,aa.txt放在同一檔案目錄。
    (3)如果以“/”開頭表示應用的根目錄下。例如:tomcat應用程式的根目錄資料夾為webapps。匯入webapps下的檔案bb.txt的編寫方式為:<c:import url=”/bb.txt”>
        如果訪問webapps管理資料夾中其他web應用就要用context屬性。
    (4)context屬性用於在訪問其他web應用的檔案時,指定根目錄。例如,訪問root下的index.jsp的實現程式碼為:<c:import url=”/index.jsp” context=”/root”>
        等同於webapps/root/index.jsp
    (5)var、scope、charEncoding、varReader是可選屬性。

範例:<c:import>標籤的使用:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL: -- import標籤例項</title>
    </head>
    <body>
         <h4><c:out value="import例項"/></h4>
         <hr/>
         <h4><c:out value="絕對路徑引用的例項" /></h4>
         <%--使用絕對路徑匯入百度首頁,
             匯入時使用<c:catch></c:catch>捕獲異常。
          --%>
         <c:catch var="error1">
             <c:import url="http://wwww.baidu.com" charEncoding="utf-8"/>
         </c:catch>
             ${error1}
         <hr/>
         <h4>
              <c:out value="相對路徑引用本應用中的檔案" />
         </h4>
         <%--使用相對路徑匯入同一資料夾下的“JSTL的import標籤使用說明”檔案,
             接收的字元編碼格式使用charEncoding設定為utf-8。 --%>
         <c:catch var="error2">
             <c:import url="JSTL的import標籤使用說明" charEncoding="utf-8"/>
         </c:catch>
          ${error2}
         <hr/>
          <h4><c:out value="使用字串輸出相對路徑引用的例項,並儲存在session範圍內" /></h4>
          <%--匯入“JSTL的import標籤使用說明.txt”,
              使用var定義的變數接收要匯入的檔案,並存儲在session中,
              如果在其他頁面同樣也要匯入該檔案,只須使用<c:out>輸出“JSTL的import標籤使用說明.txt”的值即可。
          --%>
          <c:catch var="error3">
               <c:import 
                   var="myurl" 
                   url="JSTL的import標籤使用說明" 
                   scope="session" 
                   charEncoding="utf-8"/>
               <c:out value="${myurl}"></c:out>
               <hr/>
            <c:out value="${myurl}" />
          </c:catch>
               ${error3}
    </body>
</html>
  • <c:url>標籤

    <c:url>標籤用於在JSP頁面中構造一個URL地址,其主要目的是實現URL重寫。

【語法1】:指定一個url不做修改,可以選擇把該url儲存在JSP不同的範圍中。
    <c:url
        value=”value”
        [var=”name”]
        [scope=”page|request|session|application”]
        [context=”context”]/>
        
【語法2】:配合 <c:param>標籤給url加上指定引數及引數值,可以選擇以name儲存該url。
    <c:url
        value=”value”
        [var=”name”]
        [scope=”page|request|session|application”]
        [context=”context”]>
          <c:param name=”引數名” value=”值”>
    </c:url>

<c:url>標籤包含如下屬性:

屬性名 是否支援EL 屬性型別 描述
value true String 指定要構造的URL。
var false String 指定將構造出的URL結果儲存到Web域中的屬性名稱。
scopr false String 指定將構造出的URL結果儲存到哪個Web域中。

範例:<c:url>標籤的使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
    <head>
        <title>JSTL: -- url標籤例項</title>
    </head>
    <body>
        <c:out value="url標籤使用"></c:out>
        <h4>使用url標籤生成一個動態的url,並把值存入session中.</h4>
        <hr/>
        <c:url value="http://www.baidu.com" var="url" scope="session">
        </c:url>
        <a href="${url}">百度首頁(不帶引數)</a>
        <hr/>
        <h4>
            配合 &lt;c:param&gt;標籤給url加上指定引數及引數值,生成一個動態的url然後儲存到paramUrl變數中
        </h4>
        <c:url value="http://www.baidu.com" var="paramUrl">
            <c:param name="userName" value="孤傲蒼狼"/>
            <c:param name="pwd">123456</c:param>
        </c:url>
        <a href="${paramUrl}">百度首頁(帶引數)</a>
    </body>
</html>

redirect標籤

<c:redirect>標籤用來實現請求的重定向。同時可以配合使用<c:param>標籤在url中加入指定的引數。

【語法1】:
    <c:redirect url=”url” [context=”context”]/>
【語法2】:
    <c:redirect url=”url”[context=”context”]>
        <c:param name=”name1” value=”value1”>
    </c:redirect>
    
【引數說明】:
   (1)url指定重定向頁面的地址,可以是一個string型別的絕對地址或相對地址。
   (2)context用於匯入其他web應用中的頁面。

<c:redirect>標籤包含如下屬性:

屬性名 是否支援EL 屬性型別 描述
url true String 指定要轉發或重定向到的目標資源的URL地址。
contexr true String 當要使用相對路徑重定向到同一個伺服器下的其他Web應用程式中的資源時,context屬性指定其他Web應用程式的名稱。

範例:<c:redirect>標籤的使用:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <title>JSTL: -- redirect標籤例項</title>
    </head>
    <body>
        <c:redirect url="http://www.baidu.com">
            <%--在重定向時使用<c:param>標籤為URL添加了兩個引數:uname=GACL和password=123 --%>
            <c:param name="uname">GACL</c:param>
            <c:param name="password">123</c:param>
        </c:redirect>
    </body>
</html>
  • <c:param>標籤

    在JSP頁面進行URL的相關操作時,經常要在URL地址後面附加一些引數。<c:param>標籤可以巢狀在<c:import>、<c:url>或<c:redirect>標籤內,為這些標籤

所使用的URL地址附加引數。

<c:param>標籤在為一個URL地址附加引數時,將自動對引數值進行URL編碼,例如,如果傳遞的引數值為“中國”, 則將其轉換為“%d6%d0%b9%fa”後再附加

到URL地址後面,這也就是使用<c:param>標籤的最大好處。

範例1:與<c:url>標籤巢狀使用:

<c:url value="http://www.baidu.com" var="paramUrl">
     <c:param name="userName" value="legend"/>
     <c:param name="pwd">123456</c:param>
</c:url>
<a href="${paramUrl}">百度首頁(帶引數)</a>

範例2:與<c:redirect>標籤巢狀使用:

<c:redirect url="http://www.baidu.com">
     <%--在重定向時使用<c:param>標籤為URL添加了兩個引數:uname=123456和password=123 --%>
     <c:param name="uname">123456</c:param>
     <c:param name="password">123</c:param>
</c:redirect>