Java Web 自定義標簽


1.   自定義標簽

由於在JSP頁面中直接嵌入Java代碼會導致頁面開起來非常混亂,不方便和美工等配合工作,為此,JSP提供了自定義標簽技術,可以代替直接嵌入Java代碼的方式提供動態邏輯,但自定義標簽本質上仍然是Java代碼

 

 

1.1. JSTL

JSTL(JavaServer Pages Standard Tag Library),JSP標准標簽庫,是一組JSP自定義標簽。這些標簽原本由第三方開發實現,由於效果質量非常好,sun公司就把這些標簽作為標准標簽打包成庫並加以推廣

 

現在先學習JSTL中主要自定義標簽的用法,后面再學習如何定義自己的自定義標簽

 

JSTL按照標簽功能分為多個庫,主要有:

標簽庫

uri

建議前綴

核心標簽庫

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

c

格式化標簽庫

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

fmt

函數庫

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

fn

 

1.1.1. 核心標簽庫

主要包含<c:out>、<c:if>、<c:forEach>標簽,要想在JSP頁面中使用這些標簽,需要使用<%@ taglib >指令引入核心標簽庫的配置文件(tld文件在對應jar包的META-INF下面)

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

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

 

指定taglib時需要引入帶jsp的uri,這套是新版本(舊版本有時候不好用)

 

<c:out>

先把EL表達式計算結果中的特殊字符比如<、& 轉換為對應的實體字符,再輸出到HTML格式的響應中

 

JSP頁面中

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

 

<c:out value="${ '<hello>' }" ></c:out>

 

 

對應JSP生成的Servlet中主要的java代碼

OutTag outTag = tagHandlerPool.get(OutTag.class);

outTag.setValue(PageContextImpl.proprietaryEvaluate("${ '<hello>' }", Object.class, pageContext, null));

outTag.doStartTag();

 

每個自定義標簽都對應一個標簽類,比如<c:out>對應OutTag,在JSP頁面中每使用一次標簽,就會執行一次對應標簽對象的doStartTag()方法

 

和EL一樣,自定義標簽也是在服務器端執行的,客戶端也看不到自定義標簽,普通HTML注釋對自定義標簽也是無效的...

 

瀏覽器源代碼

&lt;hello&gt;

 

<c:if>

相當於Java中的if語句,當EL表達式的值為true時,就會執行其標簽體內容,也就是說會把標簽體內容加入到HTML格式的響應中。如果為false,就會跳過標簽體內容

 

<c:if test="${ param.age<18 }">

    禁

</c:if>

 

 

<c:forEach>

可以實現普通for循環和增強for循環兩種效果

 

普通for循環效果

<c:forEach var="i" begin="0" step="1" end="5">

    <c:out value="${ i }"></c:out> <br/>

</c:forEach>

 

var指定循環變量,每次循環開始時,內部都會調用pageContext.setAttribute("i", value),所以循環時可以使用EL表達式取出i當前的值。整個循環結束后,內部會調用pageContext.removeAttribute("i") 清理數據

 

begin指定循環變量的開始值

 

step指定循環變量的自增量,也稱為步長,默認為1

 

end指定循環變量的結束值,其實循環條件是i <= end

 

需要注意以上屬性都不支持EL表達式

 

增強for循環效果用來變量集合、數組

<c:forEach items="${ requestScope.userList }" var="user">

    <c:out value="${ user.name }"></c:out> <br/>

</c:forEach>

 

items指定待遍歷的集合或者數組,必須使用EL表達式

 

1.1.2. 格式化標簽庫

提供了<fmt:formatDate>標簽用來在JSP頁面中把Date對象轉換為指定格式的字符串,並輸出到HTML格式的響應中

 

<fmt:formatDate value="${ requestScope.user.birthday }" pattern="yyyy-MM-dd"/>

 

 

 

1.1.3. 函數庫

函數庫中提供了很多可以在EL表達式中使用的函數,其實就是一些靜態方法,絕大部分都是操作字符串的,比如fn:length、fn:contains、fn:toLowerCase、fn:toUpperCase、fn:trim、fn:split、fn:join、fn:indexOf、fn:replace、fn:startsWith、fn:endWith、fn:substring

 

${ fn:length('hello') }

${ fn:contains('hello','el') }

 

 

 

1.2. 定義自己的自定義標簽

定義並使用自己的標簽分為三個步驟:

1 編寫自定義標簽類

2 在.tld文件中標簽類

3 在JSP頁面中引入tld文件后便可使用自定義標簽

 

下面以模仿<c:if test=””>為例說明

 

1 MyIfTag.java

public class MyIfTag extends SimpleTagSupport {

 

    private Boolean test; //對應標簽的test屬性

 

    @Override

    public void doTag() throws JspException, IOException {

        if (test != null && test) {

            Writer writer = getJspContext().getOut();

            JspFragment tagBody = getJspBody();

            tagBody.invoke(writer);

        }

    }

    public Boolean getTest() {

        return test;

    }

    public void setTest(Boolean test) {

        this.test = test;

    }

}

 

標簽中需要用到到屬性,需要對應標簽類中的字段,並為字段提交get/set方法

 

如果標簽中有default屬性,由於default在Java中是關鍵字,可以使用_default變量名,並提供setDefault()方法給_default賦值

 

JspFragment表示標簽體內容,標簽體內容可能為空,也可能包含其他標簽,也可能嵌入Java代碼,其invoke(writer)方法會執行標簽體內容,並使用指定writer把執行結果輸出到響應中

 

這里並沒有出現前面說的doStartTag()方法,原因是doStartTag()屬於早期標簽類實現方式,有些復雜。這里使用的是簡易的實現方式,即繼承SimpleTagSupport

 

 

2 mytag.tld

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"

    version="2.1">

   

    <tlib-version>1</tlib-version>   <!-- 標簽庫內部版本號 -->

    <short-name>my</short-name>   <!-- 建議前綴 -->

    <uri>/my-tag</uri>   <!-- 標簽庫uri -->

   

    <tag>   <!-- 用來定義標簽 -->

        <name>if</name>   <!-- 標簽名稱 -->  

        <tag-class>com.rupeng.web.tag.MyIfTag</tag-class>   <!-- 標簽類 -->

        <body-content>scriptless</body-content>   <!-- 表示標簽體中不可嵌入Java代碼 -->

        <attribute>   <!-- 用來定義標簽屬性 -->

            <name>test</name>   <!-- 屬性名稱 -->

            <required>true</required>   <!-- 屬性是否必須 -->

            <rtexprvalue>true</rtexprvalue>   <!-- 屬性是否支持EL表達式 -->

        </attribute>

    </tag>

</taglib>

 

<body-content>用來指定標簽體內容類型,取值如下:

empty

標簽體為空

scriptless

標簽體中不可嵌入Java代碼,其他無限制

JSP

標簽體內容不做限制(當前JSP版本已廢棄此選項)

 

 

3 JSP頁面中

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

<%@ taglib uri="/my-tag" prefix="my" %>

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8">

        <title>自定義標簽</title>

    </head>

    <body>

        <my:if test="${ param.age<18 }">禁</my:if>

    </body>

</html>

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM