Spring MVC -- JSP標准標簽庫(JSTL)


JSP標准標簽庫(JavaServer Pages Standard Tag Library,JSTL)是一個JSP標簽集合,它封裝了JSP應用的通用核心功能。JSTL支持通用的、結構化的任務,比如迭代,條件判斷,XML文檔操作,國際化標簽,SQL標簽。 除了這些,它還提供了一個框架來使用集成JSTL的自定義標簽。

引入JSTL主要有以下兩個優點:

  • 可以消除JSP頁面中嵌入的JSP腳本,JSTL與EL相結合,會更加方便以及美觀;
  • 各套框架(struts,SpringMVC等)都有自己的標簽庫,比如之前博客介紹到的SpringMVC中的表單標簽庫,這時JSTL可以作為公共、通用的,橫行於各框架中。

本篇博客要介紹的JSTL中最重要的標簽,尤其是訪問有界對象(pageScope、requestScope、sessionScope、applicationScope)、遍歷集合、以及格式化數字和日期的那些標簽。如果有興趣進一步了解,可以在JSTL規范文檔中找到所有JSTL標簽的完整版說明。

注意:隨着EL 3.0的發布,所有的JSTL核心標記都可以用EL表達式替代。然而,有些舊項目中包含JSTL,因此掌握JSTL仍然是很有必要的。

一 下載JSTL

JSTL目前的最新版本是1.2,這是由JSR-52專家組在JCP(www.jcp.org)上定義的,JSTL庫可以在以下網站下載:

點擊Download,打開如下頁面:

我們只需要下載前兩個即可:

  • taglibs-standard-impl-1.2.5.jar:JSTL 1.2規范的實現包;
  • taglibs-standard-spec-1.2.5.jar:JSTL  1.2 API,包含了JSTL規范中定義的類型;

剩下兩個包:taglibs-standard-jstlel-1.2.5.jar和taglibs-standard-compat-1.2.5.jar都是為了兼容舊項目,這兩個包都是JSTL 1.0規范的實現包,這里不做過多討論。

二 JSTL庫 

JSTL是標准標簽庫,但是它是通過多個標簽庫來暴露其行為的。根據JSTL標簽所提供的功能,可以將其分為5個類別:

區域 子函數 URI 前綴
核心 變量支持 http://java.sun.com/jsp/jstl/core c
流控制
URL管理
其他
XML 核心 http://java.sun.com/jsp/jstl/xml x
流控制
轉換
國際化 語言區域 http://java.sun.com/jsp/jstl/fmt fmt
消息格式化
數字和日期格式化
數據庫 SQL http://java.sun.com/jsp/jstl/sql sql
函數 集合長度 http://java.sun.com/jsp/jstl/functions fn
字符串操作

在JSP頁面中使用JSTL庫,必須通過以下格式使用taglib指令:

<%@ taglib uri="uri" prefix="prefix" %>

例如,要使用Core庫,必須在JSP頁面的開頭處做以下聲明:

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

這個前綴可以使任意的,但是采用慣例能使團隊的其他開發人員以及后續加入該項目的其他人員更容易熟悉這些代碼,因此,建議使用預訂的前綴。

三 核心標簽

核心標簽是最常用的 JSTL標簽。引用核心標簽庫的語法如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
標簽 描述
<c:out> 用於在JSP中顯示數據,就像<%= ... >
<c:set> 用於保存數據
<c:remove> 用於刪除數據
<c:catch> 用來處理產生錯誤的異常狀況,並且將錯誤信息儲存起來
<c:if> 與我們在一般程序中用的if一樣
<c:choose> 本身只當做<c:when>和<c:otherwise>的父標簽
<c:when> <c:choose>的子標簽,用來判斷條件是否成立
<c:otherwise> <c:choose>的子標簽,接在<c:when>標簽后,當<c:when>標簽判斷為false時被執行
<c:import> 檢索一個絕對或相對 URL,然后將其內容暴露給頁面
<c:forEach> 基礎迭代標簽,接受多種集合類型
<c:forTokens> 根據指定的分隔符來分隔內容並迭代輸出
<c:param> 用來給包含或重定向的頁面傳遞參數
<c:redirect> 重定向至一個新的URL.
<c:url> 使用可選的查詢參數來創造一個URL

1、out標簽

下面首先介紹Core庫中用來操作有界變量的一般行為:out、set、remove。

在運算表達式時,out標簽是將結果輸出到當前的JspWriter。out語法有兩種形式,即有body content和沒有body content。

    <c:out value="value" [escapeXml="true"] [default="defaultValue"]/>    
    <c:out value="value" [escapeXml="true"] >
        defaultValue
    </c:out>

注意:在標簽的語法中,[]是可選的屬性。

out標簽的屬性如下:

屬性 類型 描述
value 對象 要計算的表達式
escapeXml 布爾 當設置為true時,將value中的值以字符串的形式原封不動的顯示出來;當設置為false,將value中的html標簽以HTML格式顯示;默認是true
default 對象 默認值,當賦予給value屬性的EL表達式返回null時,就會使用該默認值。

例如,下列的out標簽將輸出有界變量x的值:

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

其中x為字符串類型,值為“測試”。則在頁面顯示結果為:

當把escapeXml設置false時,out會將字符實體碼&lt;&gt;&#039;&#034;&amp轉換成html對應的字符<、>、'、“和&。

    <c:out value="&lt;&gt;&#039;&#034;&amp;"  escapeXml="false"  /><br>
    <c:out value="&lt;&gt;&#039;&#034;&amp;"  escapeXml="true"  /><br>    

輸出如下:

2、url標簽

url標簽是非常有用的,簡而言之,url標簽執行以下任意操作:

  • 如果當前上下文路徑為"/"(即應用程序部署為默認上下文“/”,“/”表示:服務器根路徑),則它將空字符串附加到指定的路徑;
  • 如果當前上下文路徑不是“/”,它會將上下文路徑添加到指定的路徑。

本節將會通過一個小的應用程序來解釋url標簽的重要性,應用程序的結構如下圖:

該應用由兩個JSP頁面main.jsp和admin.jsp組成。main.jsp文件位於應用程序根目錄中,admin.jsp位於admin文件夾中。二者都需要顯示在圖像文件夾中的兩個圖像,image1.png,image2.png。請注意,圖片的絕對路徑是:

http://host/context/image/image1.png
http://host/context/image/image2.png

因為兩個圖片從不同的位置被引用多次,為了方便使用,用一個包含文件來引用它們。任何需要顯示圖像的JSP頁面僅需要將包含文件添加到文件中即可。

(1)inc1.jsp:

inc1.jsp
<img src="image/image1.png"/>
<img src="../image/image2.png"/>

第一個包含文件包含路徑是相對當前頁的路徑,假設main.jsp頁面的URL是http://host/context/main.jsp,那么這兩個圖像的URL將被解析為以下URL:

http://host/context/image/image1.png
http://host/context/../image/image2.png

不難想象,結果不太令人滿意,第一個圖像能正常顯示,但是第二個圖像不能。

當通過http://host/context/admin/admin.jsp訪問管理頁面時,圖像的URL解析成如下:

http://host/context/admin/image/image1.png
http://host/context/admin/../image/image2.png

結果第一個圖像不能正常顯示,但是第二個圖像將顯示。

很明顯,使用相對路徑並不能總工作,因為可以從不同的目錄中的JSP頁面調用包含文件。我們唯一希望的是使圖像URL相對於應用程序本身,所以就有了第二個包含文件inc2.jsp。

(2) inc2.jsp:

inc2.jsp
<img src="/image/image1.png"/>
<img src="/image/image2.png"/>

這樣看起來不錯,應該能工作了吧?遺憾的是,它並不適用於所有情況。這是因為在開發應用程序時,部署上下文路徑通常是未知的。根據應用程序是否部署為默認上下文,admin.jsp頁面可能具有以下URL之一:

http://host/context/admin/admin.jsp
http://host/admin/admin.jsp

在這兩種情況下,瀏覽器不知道上下文路徑。事實上,在第一個URL的情況下,它會認為應用程序被部署為默認上下文(即服務器根路徑),context是一個目錄。因此,它將解析到第一個圖像的URL為:

http://host/image/image1.png

很顯然圖像無法正常工作。實際上,僅當應用程序真正被部署到默認上下文時(即admin.jsp的URL為http://host/admin/admin.jsp),才能正確顯示這兩個圖像。

注意:<img src="/image/image1.png"/>這個根路徑並不是指的應用程序的根路徑,而是服務器根路徑,或者說是http://localhost:port/;

(2) inc3.jsp:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
inc3.jsp
<img src="<c:url value="/image/image1.png"/>"/>
<img src="<c:url value="/image/image2.png"/>"/>

這種寫法解決了我們的問題,因為url標簽在服務器上執行,它知道上下文路徑是什么。所以,它可以正確的解析圖像的路徑。這里的"/"指的就是應用程序的根路徑

(4) inc4.jsp:

inc4.jsp
<!-- 通過EL定義cp變量,但是不在html中顯示 -->
<!-- ${cp=pageContext.request.contextPath} -->
<img src="${cp=="/"? "" : cp}/image/image1.png"/>
<img src="${cp=="/"? "" : cp}/image/image2.png"/>
<br/>
${cp}

下面這種采用EL表達式的寫法,我們使用以下EL表達式獲取上下文路徑:

${pageContext.request.contextPath} 

相同的表達式將會被多次使用,因此創建了一個變量:

${cp=pageContext.request.contextPath}

然而,該值仍然會發送到瀏覽器中顯示,所以需要將其放在一個HTML注釋中。然后,只需要測試上下文路徑是"/"還是別的東西。

${cp=="/"? "" : cp}

main.jsp:

<!DOCTYPE html>
<html>
    <head>
        <title>Main Page</title>
        <style>
            img {
                width:200px;
            }
        </style>
    </head>
    <body>
        <h2>Main Page</h2>
        <%@include file="include/inc1.jsp"%>
        <hr/>
        <%@include file="include/inc2.jsp"%>
        <hr/>
        <%@include file="include/inc3.jsp"%>                
        <hr/>
        <%@include file="include/inc4.jsp"%>                
        
    </body>
</html>

admin.jsp:

<!DOCTYPE html>
<html>
    <head>
        <title>Admin</title>
        <style>
            img {
                width:200px;
            }
        </style>
    </head>
    <body>
        <h2>Admin</h2>
        <%@include file="../include/inc1.jsp"%>
        <hr/>
        <%@include file="../include/inc2.jsp"%>                
        <hr/>
        <%@include file="../include/inc3.jsp"%>                
        <hr/>
        <%@include file="../include/inc4.jsp"%>                
    </body>
</html>

下面顯示了非默認上下文中的admin.jsp頁面:

可以看到上下文路徑是:/jstl-demo。

3、set標簽

利用set標簽,可以完成以下工作:

  • 創建一個字符串和一個引用該字符串的有界變量;
  • 創建一個引用現存有界對象的有界變量;
  • 設置有界對象的屬性;

注意:有界對象指的是隱式對象pageScope、requestScope、sessionScope、applicationScope。

如果用set創建有界變量,那么在該標簽出現后的整個JSP頁面中都可以使用該變量。

set便簽的語法有4種形式。

(1)第一種像是用於創建一個有界變量,並用value屬性在其中定義一個要創建的字符串或者現存有界對象。

<c:set value="value" var="varName" [scope="{page|request|session|application}"]/>

這里的scope屬性指定了有界變量的范圍,默認變量范圍是page。

例如,下面的set標簽則創建了字符串"The wisest fool",並將其賦給新創建的頁面范圍變量foo:

 <c:set var="foo" value="The wisest fool"/>
 ${foo}    

輸出如下:

下面的set標簽則創建了一個名為job的有界變量,它引用requestScope對象的position屬性,變量job的范圍為page:

 <c:set var="job" value="${requestScope.position}" scope="page"/>

(2)第二種形式與第一種形式相似,只是要創建的字符串或者要引用的有界對象是作為body content賦值的:

<c:set  var="varName" [scope="{page|request|session|application}"]>
   body content
</c:set>

第二種形式允許在body content中有JSP代碼。

(3)第三種形式是設置有界對象的屬性值。target屬性用於指定有界對象,property屬性用於指定有界對象的屬性。對該屬性的賦值是通過value屬性進行的:

<c:set target="target" property="propertyName" value="value"/>

例如,下面的set標簽是將字符串"Tokyo"賦予有界對象address的city屬性:

 <c:set target="${address}" property="city" value="Tokyo"/>    
 ${address.city}

輸出如下:

注意:必須在target屬性中用一個EL表達式來引用這個有界對象。

(4)第4種方式與第三種形式相似,只是賦值是作為body content完成的:

<c:set target="target" property="propertyName">
  body content
</c:set>

例如,下面的set標簽是將字符串"Beijing"賦予有界對象address的city屬性:

<c:set target="${address}" property="city">
  Beijing
</c:set>

set標簽的屬性見表:

屬性 類型 描述
value 對象 要創建的字符串,或者要引用的有界對象,或者新的屬性值
var 字符串 要創建的有界變量
scope 字符串 新創建的有界變量的范圍
target 對象 其屬性要被賦予新值的有界對象;這必須是一個JavaBeans實例或者Java.util.Map對象
property 字符串 target所指定對象,要被賦予新值的屬性名稱

4、remove標簽

remove標簽用於刪除有界對象,其語法如下:

<c:remove var="varName" [scope="{page|request|session|application}"]/>

注意:有界對象引用的對象不能刪除,因此,如果另一個有界對象也引用了同一個對象,仍然可以通過另一個有界變量訪問該對象。

remove標簽的屬性見表:

屬性 類型 描述
var 字符串 要刪除的有界變量的名稱
scope 字符串 要刪除的有界變量的范圍,默認是page

例如,下面的remove標簽刪除了頁面范圍的變量job:

 <c:remove var="job" scope="page"/>

下面介紹Core庫中執行條件行為的標簽。JSTL中執行條件行為的標簽有4個,即if、choose、when、otherwise。

5、if標簽

if標簽是對某一個條件進行測試,假設結果為true,就處理它的body content。測試結果保存在Boolean對象中,並創建有界變量來引用這個Boolean對象,利用var屬性和scope屬性分別定義有界變量的名稱和范圍。

 if的語法有兩種形式。第一種形式沒有body content。

<c:if test="testCondition" var="varName" [scope="{page|request|session|application}"] />

在這種情況下,var定義的有界對象一般是由其他標簽在同一個JSP的后續階段進行測試。

第二種形式是使用一個body content:

    <c:if test="testCondition" [var="varName"] [scope="{page|request|session|application}"]>
        body content
    </c:if>

 

body content是JSP,當測試條件的結果為true時,就會得到處理。例如:

    <c:if test="${param.user='ken' && param.password == 'blackcomb'}" scope="page">
        You logged in successfully.
    </c:if>

if標簽的屬性見表:

屬性 類型 描述
test 布爾 決定是否處理任何現有body content的測試條件
var 字符串 引用測試條件值的有界變量名稱;var的類型是Boolean
scope 字符串 var定義的有界變量的范圍

為了模擬else,下面使用了兩個if標簽,並使用了相反的條件。例如,如果user和password參數的值為"ken"和“blackcomb”,以下代碼片段將顯示 "You logged in successfully.",否則,將顯示"Login failed":

    <c:if test="${param.user='ken' && param.password == 'blackcomb'}" scope="page">
        You logged in successfully.
    </c:if>
    <c:if test="${!(param.user='ken' && param.password == 'blackcomb')}" scope="page">
        Login failed.
    </c:if>

下面的if標簽測試user和password參數值是否分別為“key”和"blackcomb",並將結果保存在頁面范圍的變量loggedIn中。之后,利用一個EL表達式,如果loggedIn變量值為true,則顯示"You logged in successfully.",否則,將顯示"Login failed":

   <c:if  var="loggedIn" test="${param.user='ken' && param.password == 'blackcomb'}"  scope="page">
    ...
   ${loggedIn ? "You logged in successfully.":"Login failed."}

6、choose、when和otherwise標簽

choose和when標簽的作用與Java中的關鍵字switch和case類似。也就是說,他們是用來為相互排斥的條件執行提供上下文的。choose標簽中的必需嵌入有一個或者多個when標簽,並且每個when標簽都表示一種可以計算和處理的情況。otherwise標簽則用於默認的條件快,假設沒有任何一個when標簽的測試條件結果為true,otherwise就會得到處理。假如是這種情況,otherwise就必須放在最后一個when之后。

choose和otherwise標簽沒有屬性,when標簽必須帶有定義測試條件的test屬性,用來決定是否應該處理body content。

舉個例子,以下代碼是測試參數status的值,如果status的值為full,將顯示“You ara a full member.”;如果這個值是student,則顯示“You are a student member.”;如果status參數不存在,或者它的值既不是full也不是student,那么這段代碼將不顯示任何內容:

    <c:choose>
        <c:when test="${ param.status=='full'}">
            You are a full member.
        </c:when> 
        <c:when test="${ param.status=='sdtudent'}">
            You are a student member.
        </c:when> 
    </c:choose>

下面的例子與前面的例子相似,但是它利用了otherwise標簽,如果status參數不存在,或者它的值不是full或student,則顯示“Please register.”:

    <c:choose>
        <c:when test="${ param.status=='full'}">
            You are a full member.
        </c:when> 
        <c:when test="${ param.status=='sdtudent'}">
            You are a student member.
        </c:when> 
        <c:otherwise>
            Please register.
        </c:otherwise>
    </c:choose>

下面介紹Core庫中執行遍歷行為的標簽。JSTL中執行遍歷行為的標簽有2個,forEach和forTakens。這些標簽封裝了Java中的for,while,do-while循環。

7、forEach標簽

forEach標簽會無數次的反復遍歷body content或者集合對象。可以遍歷的對象包括java.util.Collection和java.util.Map的所有實現,以及對象數組或者基本類型。也可以遍歷java.util.Iterator和java.util.Enumeration,但不應該在多個行為中使用Iterator或者Enumeration,因為無法重置Iterator或者Enumeration。

forEach標簽的語法有兩種形式。第一種形式是固定次數的重復body content:

    <c:forEach [var="varName"] begin="begin" end="end" step="step">
        body content
    </c:forEach>

第二種形式用於遍歷集合對象:

    <c:forEach items="collection" [var="varName"] [varStatus="varStatusName"] [begin="beagin"]  [end="end"] [step="step"]>
        body content
    </c:forEach>

body content是JSP。

如果要遍歷Map,要分別利用key和value屬性引用一個Map key和一個Map value,遍歷Map的偽代碼如下所示:

    <c:forEach var="mapItem" items="map" >
        ${mapItem.key}:${mapItem.value}<br/>
    </c:forEach>

forEach屬性見表:

屬性 描述  類型   默認值
items 要被遍歷的集合 支持的任意類型
begin 開始的元素(0=第一個元素,1=第二個元素) 整數 0
end 最后一個元素(0=第一個元素,1=第二個元素) 整數 Last element
step 每一次迭代的步長 整數 1
var 引用遍歷的當前項的有界變量名稱 字符串
varStatus 保存遍歷狀態的有界變量名稱,類型值為javax.servlet.jsp.jstl.core.LoopTagStatus 字符串

例如,下列的forEach標簽將顯示“1,2,3,4,5”:

    <c:forEach var="x" begin="1" end="5" step="1">
        ${x }
    </c:forEach>

下面的forEach標簽將遍歷有界變量address的phones屬性:

    <c:forEach var="phone" items="${address.phones}" >
        ${phone}<br/>
    </c:forEach>

對於每次變量,forEach標簽都會創建一個有界變量,變量名通過var屬性定義。在本例中,有界變量名為phone。forEach標簽中的EL表達式用於顯示phone的值,這個有界變量只存在於開始和結束的forEach標簽之間,一到結束的forEach標簽前,它就會被刪除。

forEach標簽有一個類型為javax.servlet.jsp.jstl.core.LoopTagStatus的變量varStatus,LoopTagStatus接口帶有count屬性,它返回當前遍歷的“次數”。第一次遍歷時,varStatus.count值為1,;第二次遍歷時,varStatus.count值為2。依此類推,通過測試varStatus.count%2的余數,可以知道該標簽正在處理的是偶數編號的元素,還是奇數編號的元素。

8、forTakens標簽

forTakens標簽可以指定的分隔符來分隔內容並迭代輸出,相當於Java.util.StirngTokenizer類。,其語法如下:

    <c:forTokens items="stringOfTakens" [delims="delimiters"] [var="varName"] [varStatus="varStatusName"] [begin="beagin"]  [end="end"] [step="step"]>
        body content
    </c:forTokens>

body content是JSP,forTakens標簽的屬性如下:

 屬性 描述 類型  默認值 
items 要被遍歷的token字符串 支持的任意類型
begin 開始的元素(0=第一個元素,1=第二個元素) 整數 0
end 最后一個元素(0=第一個元素,1=第二個元素) 整數 Last element
step 每一次迭代的步長 整數 1
var 引用遍歷的當前項的有界變量名稱 字符串
varStatus 保存遍歷狀態的有界變量名稱,類型值為javax.servlet.jsp.jstl.core.LoopTagStatus 字符串
delims 一組分隔符 字符串

下面是一個forTakens示例:

    <c:forTokens var="item" items="Argentina,Brazil,Chile" delims=",">
        <c:out value="${item}" /><br/>
    </c:forTokens>

當將以上forTakens黏貼到JSP中時,它將會產生以下結果:

四 格式化標簽

JSTL格式化標簽用來格式化並輸出文本、日期、時間、數字。引用格式化標簽庫的語法如下:

<%@ taglib prefix="fmt"  uri="http://java.sun.com/jsp/jstl/fmt" %>
標簽 描述
<fmt:formatNumber> 使用指定的格式或精度格式化數字
<fmt:parseNumber> 解析一個代表着數字,貨幣或百分比的字符串
<fmt:formatDate> 使用指定的風格或模式格式化日期和時間
<fmt:parseDate> 解析一個代表着日期或時間的字符串
<fmt:bundle> 綁定資源
<fmt:setLocale> 指定地區
<fmt:setBundle> 綁定資源
<fmt:timeZone> 指定時區
<fmt:setTimeZone> 指定時區
<fmt:message> 顯示資源配置文件信息
<fmt:requestEncoding> 設置request的字符編碼

1、formatNumber標簽

formatNumber標簽用於格式化數字。你可以根據需要,利用這個標簽的各種屬性來獲取自己想要的格式。formatNumber的語法格式有以下兩種形式,第一種沒有body content:

<fmt:formatNumber  value="numericValue" 
       [type="{number|currency|percent}"] 
       [pattern="customPattern"]
       [currencyCode="currencyCode"]
       [currencySymbol="currencySymbol"]
       [groupingUsed="{true|false}"]
       [maxIntegerDigits="maxIntegerDigits"]
       [minIntegerDigits="minIntegerDigits"]
       [maxFractionDigits="maxFractionDigits"]
       [minFractionDigits="minFractionDigits"]
       [var="varName"]
       [scope="{page|request|session|application}"]
/>

第二種形式有body content:

<fmt:formatNumber  [type="{number|currency|percent}"] 
       [pattern="customPattern"]
       [currencyCode="currencyCode"]
       [currencySymbol="currencySymbol"]
       [groupingUsed="{true|false}"]
       [maxIntegerDigits="maxIntegerDigits"]
       [minIntegerDigits="minIntegerDigits"]
       [maxFractionDigits="maxFractionDigits"]
       [minFractionDigits="minFractionDigits"]
       [var="varName"]
       [scope="{page|request|session|application}"]>
    numeric value to be formatted
</fmt:formatNumber>

body content是JSP,formatNumber標簽的屬性見下表:

屬性 描述 類型 默認值
value 要顯示的數字 字符串或者數字
type 說明該值是要被格式化成數字、貨幣還是百分比。屬性值如下:number,currency,或 percent類型 字符串 number
pattern 指定一個自定義的格式化模式用於輸出 字符串
currencyCode ISO 4217貨幣代碼(當type="currency"時) 字符串 取決於默認區域
currencySymbol 貨幣符號 (當type="currency"時) 字符串 取決於默認區域
groupingUsed 說明輸出結果中是否包含組分隔符 布爾 true
maxIntegerDigits 規定輸出結果中整數部分最多幾位數字 整數
minIntegerDigits 規定輸出結果中整數部分最少幾位數字 整數
maxFractionDigits 規定輸出結果中小數部分最多幾位數字 整數
minFractionDigits 規定輸出結果中小數部分最少幾位數字 整數
var 將輸出結果存儲為字符串的有界變量名稱 字符串
scope var的作用域 字符串 page

formatNumber標簽的用途之一就是將數字格式化成貨幣。為此:

  • 當type屬性為currency時,可以利用currencyCode屬性來定義一個ISO 4217貨幣代碼。部分ISO 4217貨幣代碼見表:
貨幣 ISO 4217貨幣代碼 大單位名稱 小單位名稱
加拿大元 CAD 加元
人民幣 CNY
歐元 EUR 歐元
日元 JPY 日元
英鎊 GBP 英鎊 便士
美元 USD 美元 美分
  • 如果type屬性為percent或number,那么就可以使用其它幾個格式化數字屬性。maxIntegerDigits屬性和minIntegerDigits屬性允許指定整數的長度,若實際數字超過了maxIntegerDigits所指定的最大值,則數字將會被截斷;minFractionalDigits屬性和maxFractionalDigits屬性允許指定小數點后的位數。若實際的數字超出了所指定的范圍,則這個數字會被截斷。數字分組可以用來在每三個數字中插入一個逗號,groupingIsUsed屬性用來指定是否使用數字分組,當與minIntegerDigits屬性一同使用時,就必須要很小心地來獲取預期的結果了。

pattern屬性可以在對數字編碼時包含指定的字符。接下來的表格中列出了這些字符:

符號 描述
0 代表一位數字
E 使用指數格式
# 代表一位數字,若沒有則顯示 0,前導 0 和追尾 0 不顯示。
. 小數點
, 數字分組分隔符
; 分隔格式
- 使用默認負數前綴
% 百分數
? 千分數
¤ 貨幣符號,使用實際的貨幣符號代替
X 指定可以作為前綴或后綴的字符
' 在前綴或后綴中引用特殊字符

formatNumber標簽的用法見下表:

    <!-- formatNumber標簽 -->
    <fmt:formatNumber value="12" type="number"/><br/>
    <fmt:formatNumber value="12" type="number" minIntegerDigits="3"/><br/>
    <fmt:formatNumber value="12" type="number" minFractionDigits="2"/><br/>
    <fmt:formatNumber value="123456.78" pattern=".000"/><br/>
    <fmt:formatNumber value="123456.78" pattern="#,#00.0#"/><br/>
    <fmt:formatNumber value="12" type="currency"/><br/>
    <fmt:formatNumber value="12" type="currency" currencyCode="GBP"/><br/>
    <fmt:formatNumber value="0.12" type="percent"/><br/>
    <fmt:formatNumber value="0.12" type="percent" minFractionDigits="2"/><br/>

輸出如下:

2、formatDate格式

formatDate便簽用於格式化日期,其語法格式如下:

<fmt:formatDate  value="date"
  [type="{time|date|both}"]
  [dateStyle="{default|short|medium|long|full}"]
  [timeStyle="{default|short|medium|long|full}"]
  [pattern="customPattern"]
  [timeZone="timeZone"]
  [var="varName"]
  [scope="{page|request|session|application}"]/>

body content是JSP,formatDate標簽的屬性見下表:

屬性 描述 類型 默認值
value 要格式化的日期、時間、日期和時間 java.util.Date
type 說明要格式化的是時間、日期、還是時間與日期部分都要格式化,屬性值:date, time, both 字符串 date
dateStyle 預定義日期的格式化樣式,遵循java.text.DateFormat中定義的語法。屬性值:full, long, medium, short, 或 default 字符串 default
timeStyle 預定義時間的格式化樣式,遵循java.text.DateFormat中定義的語法。屬性值:full, long, medium, short, 或 default 字符串 default
pattern 自定義格式化模式 字符串
timeZone 定義用於顯示時間的時區 字符串 默認時區
var 將輸出結果存儲為字符串的有界變量名稱 字符串或者java.util.TimeZone
scope var的作用域 字符串 page

formatDate標簽的格式話模式見下表:

代碼 描述 實例

G

時代標志

AD

y

不包含紀元的年份。如果不包含紀元的年份小於 10,則顯示不具有前導零的年份。

2002

M

月份數字。一位數的月份沒有前導零。

April & 04

d

月中的某一天。一位數的日期沒有前導零。

20

h

12 小時制的小時。一位數的小時數沒有前導零。

12

H

24 小時制的小時。一位數的小時數沒有前導零。

0

m

分鍾。一位數的分鍾數沒有前導零。

45

s

秒。一位數的秒數沒有前導零。

52

S

毫秒

970

E

周幾

Tuesday

D

一年中的第幾天

180

F

一個月中的第幾個周幾

2 (一個月中的第二個星期三)

w

一年中的第幾周r

27

W

一個月中的第幾周

2

a

a.m./p.m. 指示符

PM

k

小時(12 小時制的小時)

24

K

小時(24 小時制的小時)

0

z

時區

中部標准時間

'

 

轉義文本

''

 

單引號

下列代碼利用formatDate標簽格式化有界變量now引用的java.util.Date對象:

    <!-- dormatDate標簽 -->
    <%
        String str = "2008-08-08 20:08:08";
        String dateFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        /*
         * Date parse(String str)
         * 將給定的字符串按照SimpleDateFormat指定
         * 的日期格式解析並轉換為Date對象返回
         */
        Date now = (Date) sdf.parse(str);
        out.println(now+"<br/>");
        pageContext.setAttribute("now", now);
    %>          
    Default:<fmt:formatDate value="${now}"/><br/>
    Short:<fmt:formatDate value="${now}" dateStyle="short"/><br/>
    Medium:<fmt:formatDate value="${now}" dateStyle="medium"/><br/>
    Long:<fmt:formatDate value="${now}" dateStyle="Long"/><br/>
    Full:<fmt:formatDate value="${now}" dateStyle="Full"/><br/>

輸出如下:

下面的formatDate標簽用於格式化時間:

    Default:<fmt:formatDate type="time" value="${now}"/><br/>
    Short:<fmt:formatDate type="time" value="${now}" timeStyle="short"/><br/>
    Medium:<fmt:formatDate type="time" value="${now}" timeStyle="medium"/><br/>
    Long:<fmt:formatDate type="time" value="${now}" timeStyle="Long"/><br/>
    Full:<fmt:formatDate type="time" value="${now}" timeStyle="Full"/><br/>

下面的formatDate標簽用於格式化日期和時間:

    Default:<fmt:formatDate type="both" value="${now}"/><br/>
    Short:<fmt:formatDate type="both" value="${now}" dateStyle="short"  timeStyle="short"/><br/>
    Medium:<fmt:formatDate type="both" value="${now}" dateStyle="medium"  timeStyle="medium"/><br/>
    Long:<fmt:formatDate type="both" value="${now}" dateStyle="Long"  timeStyle="Long"/><br/>
    Full:<fmt:formatDate type="both" value="${now}" dateStyle="Full"  timeStyle="Full"/><br/>

下面的formatDate標簽用於格式化帶時區的時間:

    Time zone CT:<fmt:formatDate type="time" value="${now}" timeZone="CT"/><br/>
    Time zone HST:<fmt:formatDate type="time" value="${now}" timeZone="HST"/><br/>

下面的formatDate標簽利用定制模式來格式化日期和時間:

    <fmt:formatDate type="both" value="${now}" pattern="dd.MM.yy"/><br/>
    <fmt:formatDate type="both" value="${now}" pattern="dd.MM.yyyy"/><br/>

3、timeZone標簽

timeZone標簽用於定義時區,使其body content中的時間信息按指定時區進行格式化或者解析。其語法如下:

<fmt:timezone value="timeZone">
   body content
</fmt:timeZone>

body content是JSP,屬性值可以是類型為String或者java.util.TimeZone的動態值。

如果value屬性為null或者empty,則使用GMT時區。

下面的范例用timeZone標簽格式化帶時區的日期:

    <!-- timeZone標簽 -->
    <fmt:timeZone value="GMT+1:00">
        <fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"/><br/>    
    </fmt:timeZone>
    
    <fmt:timeZone value="HST">
        <fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"/><br/>    
    </fmt:timeZone>
    
    <fmt:timeZone value="CST">
        <fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"/><br/>    
    </fmt:timeZone>

美國和加拿大時區的值見下表:

縮寫 全名 時區
NST 紐芬蘭標准時間 UTC-3:30
NDT 紐芬蘭夏時制 UTC-2:30
AST 大西洋標准時間 UTC-4
ADT 大西洋夏時制 UTC-3
EST 東部標准時間 UTC-5
EDT 東部夏時制 UTC-4
ET 東部時間,如EST和EDT *
CST 中部標准時間 UTC-6
CDT 中部夏時制 UTC-5
CT 中部時間,如CST和CDT *
MST 山地標准時間 UTC-7
MDT 山地夏時制 UTC-6
MT 山地時間,如MST和MDT *
PST 太平洋標准時間 UTC-8
PDT 太平洋夏時制 UTC-7
PT 太平洋時間,如PST和PDT *
AKST 阿拉斯加標准時間 UTC-9
AKDT 阿拉斯加夏時制 UTC-8
HST 夏威夷標准時間 UTC-10

4、setTimeZone標簽

setTimeZone標簽用於將指定時區保存在一個有界變量或者時間配置變量中,setTimeZone的語法如下:

<fmt:setTimeZone value="timeZone" [var="varName"]  [scope="{page|request|session|application}"]/>

下表顯示了setTimeZone標簽的屬性:

屬性 描述 類型 默認值
value 時區 字符串或者java.util.TimeZone
var 保存類型為java.util.TimeZone的時區有界變量 字符串
scope 變量的作用與 字符串 page

下面演示一個具體的示例:

    <!-- setTimeZone標簽 -->
    <c:set var="now" value="<%=new java.util.Date()%>" />
    <p>當前時區時間: <fmt:formatDate value="${now}" 
             type="both" timeStyle="long" dateStyle="long" /></p>
    <p>修改為 GMT-8 時區:</p>
    <fmt:setTimeZone value="GMT-8" />
    <p>Date in Changed Zone: <fmt:formatDate value="${now}" 
             type="both" timeStyle="long" dateStyle="long" />
     </p>

5、parseNumber標簽

parseNumber標簽用於將以字符串表示的數字、貨幣或者百分百解析成數字。其語法有兩種形式,第一種沒有body content:

<fmt:parseNumber  value="numericValue"
  [type="{number|currency|percent}"]
  [pattern="customPattern"]
  [parseLocale="parseLocale"]
  [integerOnly="{true|false}"]
  [var="varName"]
  [scope="{page|request|session|application}"]
/>

第二種形式有body content:

<fmt:parseNumber  value="numericValue"
  [type="{number|currency|percent}"]
  [pattern="customPattern"]
  [parseLocale="parseLocale"]
  [integerOnly="{true|false}"]
  [var="varName"]
  [scope="{page|request|session|application}"]>
  body content
</fmt:parseNumber>

body content是JSP。parseNumber標簽的屬性見表:

屬性 描述 類型 默認值
value 要解析的字符串 字符串或數字
type 說明該字符串是要被解析成數字、貨幣還是百分比 字符串 number
parseLocale 定義locale,在解析操作期間將其默認格式化樣式,或將pattern屬性定義的樣式應用其中 字符串或者java.util.Locale 默認區域
integerOnly 是否只解析整型數(true)或浮點數(false) 布爾 false
pattern 自定義格式化模式 字符串
timeZone 定義用於顯示時間的時區 字符串或者java.util.TimeZone 默認時區
var 保存輸出結果的有界變量名稱 字符串
scope var變量的作用域 字符串 page

下面的parseNumber標簽就是解析有界變量balance的值,並將結果保存在有界變量i中:

     <!-- parseNumber標簽 -->
     <c:set var="balance" value="1250003.350" />
     <fmt:parseNumber var="i" type="number" value="${balance}" />
     <p>數字解析 (1) : <c:out value="${i}" /></p>
     <fmt:parseNumber var="i" integerOnly="true" type="number" value="${balance}" />
     <p>數字解析 (2) : <c:out value="${i}" /></p>

6、parseDate標簽

parseDate標簽以區分地域的格式解析以字符串表示的日期和時間。其語法有兩種形式,第一種沒有body content:

<fmt:parseDate  value="dateString"
  [type="{time|date|both}"]
  [dateStyle="{default|short|medium|long|full}"]
  [timeStyle="{default|short|medium|long|full}"]
  [pattern="customPattern"]
  [timeZone="timeZone"]
  [parseLocale="parseLocale"]
  [var="varName"]
  [scope="{page|request|session|application}"]/>

第二種形式有body content:

<fmt:parseDate  value="dateString"
  [type="{time|date|both}"]
  [dateStyle="{default|short|medium|long|full}"]
  [timeStyle="{default|short|medium|long|full}"]
  [pattern="customPattern"]
  [timeZone="timeZone"]
  [parseLocale="parseLocale"]
  [var="varName"]
  [scope="{page|request|session|application}"]>
 date value to be parsed
</fmt:parseDate>

body content是JSP,parseDate標簽的屬性見下表:

屬性 描述 類型 默認值
value 要解析的字符串 字符串
type 說明要被解析的字符串是否包含日期、時間或者二者均有。屬性值:date, time, 或 both 字符串 date
dateStyle 日期的格式化樣式。屬性值:full, long, medium, short, 或 default 字符串 default
timeStyle 時間的格式化樣式。屬性值:full, long, medium, short, 或 default 字符串 default
pattern 自定義格式化模式,決定要如何解析該字符串 字符串
timeZone 定義時區,是日期字符串中的時間信息均根據它來解析 字符串或者java.util.TimeZone 默認時區
parseLocale 定義locale,在解析操作期間將其默認格式化樣式,或將pattern屬性定義的樣式應用其中 字符串或者java.util.Locale 默認區域
var 保存輸出結果的有界變量名稱 字符串 顯示在頁面
scope var變量的作用域 字符串 頁面

下面的parseDate標簽用於解析有界變量now引用的日期字符串,並將得到的java.util.Date保存在一個頁面范圍的有界變量parsedEmpDate中:

     <!-- parseDate標簽 -->
     <c:set var="now" value="20-10-2015" />
     <fmt:parseDate value="${now}" var="parsedEmpDate" pattern="dd-MM-yyyy" />
     <p>解析后的日期為: <c:out value="${parsedEmpDate}" /></p>

五 函數

JSTL定義了一套可以再EL表達式中使用的標准函數。這些函數都集中放在functtion標簽庫中。要使用這些函數,必須在JSP的最前面使用以下的taglib指令:

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

調用函數時,要以下列各式使用一個EL:

${fn:functionName}

這里的functionName是函數名。

大部分都用於字符串操作。例如,length函數用於字符串和集合,並返回集合或者數組中的項數,或者返回一個字符串的字符數。

函數 描述
fn:contains() 測試輸入的字符串是否包含指定的子串
fn:containsIgnoreCase() 測試輸入的字符串是否包含指定的子串,大小寫不敏感
fn:endsWith() 測試輸入的字符串是否以指定的后綴結尾
fn:escapeXml() 跳過可以作為XML標記的字符
fn:indexOf() 返回指定字符串在輸入字符串中出現的位置
fn:join() 將數組中的元素合成一個字符串然后輸出
fn:length() 返回字符串長度
fn:replace() 將輸入字符串中指定的位置替換為指定的字符串然后返回
fn:split() 將字符串用指定的分隔符分隔然后組成一個子字符串數組並返回
fn:startsWith() 測試輸入字符串是否以指定的前綴開始
fn:substring() 返回字符串的子集
fn:substringAfter() 返回字符串在指定子串之后的子集
fn:substringBefore() 返回字符串在指定子串之前的子集
fn:toLowerCase() 將字符串中的字符轉為小寫
fn:toUpperCase() 將字符串中的字符轉為大寫
fn:trim() 移除首尾的空白符

1、contains()函數

contains()函數用於確定一個字符串是否包含指定的子字符串。如果字符串中包含了該子字符串,則返回true,否則返回false,其語法如下:

contains(string,substring)

例如,下面兩個EL表達式都返回true:

    <!-- contains()函數 -->
    <c:set var="myString" value="Hello World"/>
    ${fn:contains(myString,"Hello")}<br/>
    ${fn:contains("Stella Cadente","Cadente")}<br/>

2、containsIgnoreCase()函數

containsIgnoreCase()函數用於確定一個字符串是否包含指定的子字符串,忽略大小寫,該函數與contains()類似。,其語法如下:

containsIgnoreCase(string,substring)

例如,下面的EL表達式將返回true:

    <!-- containsIgnoreCase()函數 -->    
    ${fn:containsIgnoreCase("Stella Cadente","CADENTE")}<br/>

3、endsWith()函數

endsWith()函數用於確定一個字符串是否以指定后綴結尾。其返回值是一個Boolean,語法如下:

endsWith(string,suffix)

例如,下面的EL表達式將返回true:

    <!-- endsWith()函數 -->    
    ${fn:endsWith("Hello World","World")}<br/>

4、escapeXml()函數

escapeXml()函數忽略用於XML標記的字符。其語法如下:

escapeXml(string)

例如,下面的EL表達式:

    <!-- excapexml()函數 -->
    <c:set var="string1" value="This is first String."/>
    <c:set var="string2" value="This <abc>is second String.</abc>"/>

    <p>使用 escapeXml() 函數:</p>
    <p>string (1) : ${fn:escapeXml(string1)}</p>
    <p>string (2) : ${fn:escapeXml(string2)}</p>

    <p>不使用 escapeXml() 函數:</p>
    <p>string (1) : ${string1}</p>
    <p>string (2) : ${string2}</p>

5、indexOf()函數

indexOf()函數返回指定子字符串在某個字符串中第一次出現時的索引。如果沒有找到指定的子字符串,則返回-1。其語法如下:

indexOf(string,substring)

例如,下面的EL表達式返回7:

    <!-- indexOf()函數 -->
    ${fn:indexOf("Stella Cadente","Cadente")} 

6、join()函數

 join()函數將一個String數組中的所有元素合並成一個字符串,並用指定的分隔符分開,其語法如下:

join(array,separator)

如果這個數組為null,就會返回一個空字符串。

例如,下面的EL表達式:

    <!-- join()函數 -->
    <c:set var="string1" value="www runoob com"/>
    <c:set var="string2" value="${fn:split(string1, ' ')}" />
    <c:set var="string3" value="${fn:join(string2, '-')}" />

    <p>字符串為 : ${string3}</p>

7、length()函數

length()函數用於返回集合中的項數,或者字符串中的字符數,其語法如下:

length(input)

例如,下面的EL表達式:

    <!-- length()函數 -->
    <c:set var="string1" value="This is first String."/>
    <c:set var="string2" value="This is second String." />

    <p>字符串長度 (1) : ${fn:length(string1)}</p>
    <p>字符串長度 (2) : ${fn:length(string2)}</p>

8、replace()函數

replace()函數將字符串string中出現的所有beforeSubstring都用afterSubstring轉換,並將結果返回,其語法如下:

replace(string,beforeSubstring,afterSubstring)

例如,下面的EL表達式:

    <!-- replace()函數 -->
    <c:set var="string1" value="I am from google"/>
    <c:set var="string2" value="${fn:replace(string1, 'google', 'runoob')}" />
    <p>替換后的字符串 : ${string2}</p>

9、split()函數

split()函數用於將一個字符串分割成一個子字符串數組。它的作用與join()相反。例如下列代碼分割字符串“my,world”,並將結果保存在有界變量split中,隨后,利用forEach標簽將split格式化成一個HTML表格中:

    <!-- split()函數 -->
    <c:set var="split" value="${fn:split('my,world',',')}"/>
    <table>
        <c:forEach var="sub" items="${split}">
            <tr>
                <td>
                    ${sub}
                </td>
            </tr>
        </c:forEach>
    </table>

10、startsWith()函數

startsWith()函數用於測試一個字符串是否以指定的前綴開頭,如果是,返回true,否則返回false。其語法如下:

startsWith(string,prefix)

例如,下面的EL表達式:

    <!-- startsWith()函數 -->
    <c:set var="string" value="Runoob: I am from Runoob."/>
    <c:if test="${fn:startsWith(string, 'Google')}">
           <p>字符串以 Google 開頭</p><br/>
    </c:if>        
    <c:if test="${fn:startsWith(string, 'Runoob')}">
           <p>字符串以 Runoob 開頭</p>
    </c:if>

11、substring()函數

substring()函數用於返回一個從指定基於0的起始索引到指定基於0的終止索引的子字符串,其語法如下:

substring(string,beginIndex,endIndex)

例如,下面的EL表達式:

    <!-- substring()函數 -->
    <c:set var="string1" value="This is first String."/>
    <c:set var="string2" value="${fn:substring(string1, 5, 15)}" />
    <p>生成的子字符串為 : ${string2}</p>

12、substringAfter()函數

 substringAfter()函數用於返回指定子字符串第一次出現后的字符串部分,其語法如下:

substringAfter(string,substring)

例如,下面的EL表達式:

    <!-- substringAfter()函數 -->
    <c:set var="string1" value="This is first String."/>
    <c:set var="string2" value="${fn:substringAfter(string1, 'is')}" />
    <p>生成的子字符串 : ${string2}</p>

13、substringBefore()函數

  substringAfter()函數用於返回指定子字符串第一次出現前的字符串部分,其語法如下:

substringBefore(string,substring)

例如,下面的EL表達式:

    <!-- substringBefore()函數 -->
    <c:set var="string1" value="This is first String."/>
    <c:set var="string2" value="${fn:substringBefore(string1,'first')}" />
    <p>生成的子字符串 : ${string2}</p>

14、toLowerCase()函數

toLowerCase()函數將一個字符串轉換成它的小寫版本,其語法如下:

toLowerCase(string)

例如,下面的EL表達式:

    <!-- toLowerCase()函數 -->
    <c:set var="string1" value="I am from RUNOOB"/>
    <c:set var="string2" value="${fn:toLowerCase(string1)}" />
    <p>字符串為 : ${string2}</p>

15、toUpperCase()函數

toUpperCase()函數將一個字符串轉換成它的大寫版本,其語法如下:

toUpperCase(string)

例如,下面的EL表達式:

    <!-- toUpperCase()函數 -->
    <c:set var="string1" value="I am from RUNOOB"/>
    <c:set var="string2" value="${fn:toUpperCase(string1)}" />
    <p>字符串為 : ${string2}</p>

16、trim()函數

trim()函數用於刪除一個字符串開頭和結束的空白,其語法如下:

trim(string)

例如,下面的EL表達式:

    <!-- trim()函數 -->
    <c:set var="string1" value="I am from runoob         "/>
    <p>string1 長度 : ${fn:length(string1)}</p>

    <c:set var="string2" value="${fn:trim(string1)}" />
    <p>string2 長度 : ${fn:length(string2)}</p>
    <p>字符串為 : ${string2}</p>

六 XML標簽

JSTL XML標簽庫提供了創建和操作XML文檔的標簽。引用XML標簽庫的語法如下:

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

在使用xml標簽前,你必須將XML 和 XPath 的相關包拷貝至你的<Tomcat 安裝目錄>\lib下:

標簽 描述
<x:out> 與<%= ... >,類似,不過只用於XPath表達式
<x:parse> 解析 XML 數據
<x:set> 設置XPath表達式
<x:if> 判斷XPath表達式,若為真,則執行本體中的內容,否則跳過本體
<x:forEach> 迭代XML文檔中的節點
<x:choose> <x:when>和<x:otherwise>的父標簽
<x:when> <x:choose>的子標簽,用來進行條件判斷
<x:otherwise> <x:choose>的子標簽,當<x:when>判斷為false時被執行
<x:transform> 將XSL轉換應用在XML文檔中
<x:param> 與<x:transform>共同使用,用於設置XSL樣式表

七 SQL標簽

JSTL SQL標簽庫提供了與關系型數據庫(Oracle,MySQL,SQL Server等等)進行交互的標簽。引用SQL標簽庫的語法如下:

<%@ taglib prefix="sql"  uri="http://java.sun.com/jsp/jstl/sql" %>
標簽 描述
<sql:setDataSource> 指定數據源
<sql:query> 運行SQL查詢語句
<sql:update> 運行SQL更新語句
<sql:param> 將SQL語句中的參數設為指定值
<sql:dateParam> 將SQL語句中的日期參數設為指定的java.util.Date 對象值
<sql:transaction> 在共享數據庫連接中提供嵌套的數據庫行為元素,將所有語句以一個事務的形式來運行

參考文章

[1]JSP 標准標簽庫(JSTL)(推薦)

[2]jsp引用JSTL核心標簽庫

[3]Spring MVC學習指南


免責聲明!

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



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