我的servlet學習過程(四):JSP部分

JSP部分

這部分主要是關於jsp各個知識點的介紹與使用方法,包括jsp概念元素、域對象、jsp標籤、EL表達式等等的介紹與使用

什麼是jsp?

jsp其實就是一個servlet,該servlet包含很多個對象,當瀏覽器請求一個jsp文件時,服務器會將該jsp文件翻譯成servlet後使用out對象向瀏覽器輸出

 JSP模板元素:

JSP頁面中的HTML內容稱之爲JSP模版元素;JSP模版元素定義了網頁的基本骨 架,即定義了頁面的結構和外觀

JSP腳本表達式:

用於將程序數據輸出到客戶端,語法:<%= 變量或表達式%>

JSP引擎在翻譯腳本表達式時,會將程序數據轉成字符串,然後在相應位置用 out.print(將數據輸給客戶端;JSP腳本表達式中的變量或表達式後面不能有分 號“;”

JSP腳本片段:

JSP腳本片斷(scriptlet)用於在JSP頁面中編寫多行Java代碼

語法:<%   多行java代碼%>

在一個JSP頁面中可以有多個腳本片斷,在兩個或多個腳本片斷之間可以嵌入文 本、HTML標記和其他JSP元素

多個腳本片斷中的代碼可以相互訪問,猶如將所有的代碼放在一對<%  %>之中的 情況

單個腳本片斷中的Java語句可以是不完整的,但是,多個腳本片斷組合後的結果 必須是完整的Java語句

如:<%

for (int i=1; i<5; i++) {

%>

<H1>www.it315.org</H1>

<%

}

%> 

PSJSP腳本片斷中只能出現java代碼,不能出現其它模板元素, JSP引擎在翻JSP頁面中,會將JSP腳本片斷中的Java代碼將被原封不動地放到Servlet _jspService方法中;JSP腳本片斷中的Java代碼必須嚴格遵循Java語法

JSP聲明:

JSP頁面中編寫的所有代碼,默認會翻譯到servletservice方法中, 而Jsp註釋 中的java代碼被翻譯到_jspService方法的外面

JSP聲明可用於定義JSP頁面轉換成的Servlet程序的靜態代碼塊、成員變量和方

多個靜態代碼塊、變量和函數可以定義在一個JSP聲明中,也可以分別單獨定義在 多個JSP聲明中

JSP隱式對象的作用範圍僅限於Servlet_jspService方法,所以在JSP聲明中不能 使用這些隱式對象

語法:<%!  java代碼  %>

JSP註釋:

JSP引擎在將JSP頁面翻譯成Servlet程序時,忽略JSP頁面中被註釋的內容

語法:<%--  註釋內容  --%>

JSP指令:

JSP指令(directive)是爲JSP引擎而設計的,它們並不直接產生任何可見輸出, 而只是告訴引擎如何處理JSP頁面中的其餘部分

三大指令:page指令、include指令、taglib指令

基本語法:

<%@ 指令 屬性名="" %>

如:<%@ page contentType="text/html;charset=gb2312"%>

如果一個指令有多個屬性,這多個屬性可以寫在一個指令中,也可以分開寫

如:<%@ page contentType="text/html;charset=gb2312"%>

<%@ page import="java.util.Date"%>

或<%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%> 

page指令:

page指令用於定義JSP頁面的各種屬性,無論page指令出現在JSP頁面中的 什麼地方,它作用的都是整個JSP頁面,page指令最好是放在整個JSP頁面 的起始位置

page指令的完整語法:

<%@ page 

[ language="java" ] 

[ extends="package.class" ] 

[ import="{package.class | package.*}, ..." ] 

JSP引擎將自動導入java.lang.*  javax.servlet.* 

 javax.servlet.jsp.*  javax.servlet.http.*

可以在一條page指令的import屬性中引入多個類和包,其中每個包 或類之間使用逗號分隔,也可以使用多條page指令的import屬性來 分別引入各個包或類

<%@ page import=”java.util.Date,java.sql.*,java.io.*” %>

或 <%@ page import=”java.util.Date” %>

<%@ page import=”java.sql.*”%>

<%@ page import=”java.io.*” %>

[ session="true | false" ] 

[ buffer="none | 8kb | sizekb" ] 

[ autoFlush="true | false" ] 

[ isThreadSafe="true | false" ] 

[ info="text" ] 

[ errorPage="relative_url" ] 

errorPage屬性的設置值必須使用相對路徑,如果以“/”開頭,表示 相對於當前web應用程序的根目錄(不是站點目錄),否則,表示相 對於當前頁面

可以載web.xml文件中使用<error-page>元素爲整個web應用程序設 置錯誤處理頁面,其中<exception-type>子元素指定異常類的完整 限定名,<location>元素指定以“/”開頭的錯誤處理頁面的路徑

如果設置了某個JSP頁面的errorPage屬性,那麼在web.xml文件中 設置的錯誤處理不對該頁面起作用

[ isErrorPage="true | false" ] 

[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ;  charset=ISO-8859-1" ] 

JSP引擎會根據page指令的contentType屬性生成響應的調用 ServletResponse.setContentType方法語句

page指令的contentType屬性還具有說明JSP源文件的字符編碼作用

[ pageEncoding="characterSet | ISO-8859-1" ] 

[ isELIgnored="true | false" ] 

%>

使用page指令處理中文亂碼問題:

問題:

輸出響應正文時出現的中文亂碼問題 

讀取瀏覽器傳遞的參數信息時出現的中文亂碼問題

問題的產生:

JSP引擎將JSP源文件翻譯成的Servlet源文件默認採用UTF-8編碼,JSP開發人員可以採用各種字符集編碼來編寫JSP源文件,因此, JSP引擎將JSP源文件翻譯成Servlet源文件時,需要進行字符編碼 轉換

如果JSP文件中沒有說明它採用的字符集編碼,JSP引擎將把它當作 默認的ISO8859-1字符集編碼處理

問題的解決:

通過page指令的contentType屬性說明JSP源文件的字符集編碼

page指令的pageEncoding屬性說明JSP源文件的字符集編碼

include指令:

include指令用於引入其它JSP頁面,如果使用include指令引入了其它JSP 面,那麼JSP引擎將把這兩個JSP翻譯成一個servlet。所以include指令引入 通常也稱之爲靜態引入

語法:<%@ include file="相對的URL"%>

其中的file屬性用於指定被引入文件的相對路徑。  file屬性的設置值必 須使用相對路徑,如果以“/”開頭,表示相對於當前WEB應用程序的根 目錄(注意不是站點根目錄),否則,表示相對於當前文件

細節:

被引入的文件必須遵循JSP語法

被引入的文件可以使用任意的擴展名,即使其擴展名是htmlJSP引擎也 會按照處理jsp頁面的方式處理它裏面的內容,爲了見明知意,JSP規範 建議使用.jspfJSP fragments)作爲靜態引入文件的擴展名 

由於使用include指令將會涉及到2JSP頁面,並會把2JSP翻譯成 一個servlet,所以這2JSP頁面的指令不能衝突(除了pageEncoding 和導包除外)

taglib指令:

taglib指令用於在JSP頁面中導入標籤庫

語法:<%@ taglib url=”標籤庫URL”  prefix=”標籤前綴”%>

JSP運行原理:

每個JSP 頁面在第一次被訪問時,WEB容器都會把請求交給JSP引擎(即一個Java 程序)去處理。JSP引擎先將JSP翻譯成一個_jspServlet(實質上也是一個servlet)  然後按照servlet的調用方式進行調用;由於JSP第一次訪問時會翻譯成servlet 所以第一次訪問通常會比較慢,但第二次訪問,JSP引擎如果發現JSP沒有變化, 就不再翻譯,而是直接調用,所以程序的執行效率不會受到影響;JSP引擎在調用 JSP對應的_jspServlet時,會傳遞或創建9個與web開發相關的對象供_jspServlet 使用。JSP技術的設計者爲便於開發人員在編寫JSP頁面時獲得這些web對象的引 用,特意定義了9個相應的變量,開發人員在JSP頁面中通過這些變量就可以快速 獲得這9大對象的引用

JSP九大隱式對象:

request  ------>  HttpServletRequest

response  -------->  HttpServletResponse

session -------->  HttpSession

application -------->  servletContext

config  ------->  servletConfig

out   -------->   JspWriter  PrintWriter

exception

page  -------->   this

pageContext

out隱式對象:

out隱式對象用於向客戶端發送文本數據 

out對象是通過調用pageContext對象的getOut方法返回的,其作用和用法與 ServletResponse.getWriter方法返回的PrintWriter對象非常相似 

JSP頁面中的out隱式對象的類型爲JspWriterJspWriter相當於一種帶緩存功能的 PrintWriter,設置JSP頁面的page指令的buffer屬性可以調整它的緩存大小,甚至 關閉它的緩存 

只有向out對象中寫入了內容,且滿足如下任何一個條件時,out對象纔去調用 ServletResponse.getWriter方法,並通過該方法返回的PrintWriter對象將out對象的 緩衝區中的內容真正寫入到Servlet引擎提供的緩衝區中:

設置page指令的buffer屬性關閉了out對象的緩存功能

out對象的緩衝區已滿

整個JSP頁面結束

out隱式對象工作原理圖:

 

pageContext對象:

pageContext對象是JSP技術中最重要的一個對象,它代表JSP頁面的運行環境, 這個對象不僅封裝了對其它8大隱式對象的引用,它自身還是一個域對象,可以用 來保存數據。並且,這個對象還封裝了web開發中經常涉及到的一些常用操作, 例如引入和跳轉其它資源、檢索其它域對象中的屬性等

通過pageContext獲得其他對象:

getException方法返回exception隱式對象 

getPage方法返回page隱式對象

getRequest方法返回request隱式對象 

getResponse方法返回response隱式對象 

getServletConfig方法返回config隱式對象

getServletContext方法返回application隱式對象

getSession方法返回session隱式對象 

getOut方法返回out隱式對象

pageContext封裝其它8大內置對象的意義,思考:如果在編程過程中,把 pageContext對象傳遞給一個普通java對象,那麼這個java對象將具有什麼功 能?

pageContext作爲域對象:

pageContext對象的方法 

public void setAttribute(java.lang.String name,java.lang.Object value)

public java.lang.Object getAttribute(java.lang.String name)

public void removeAttribute(java.lang.String name)

pageContext對象中還封裝了訪問其它域的方法

public java.lang.Object getAttribute(java.lang.String name,int scope)

public void setAttribute(java.lang.String name,  java.lang.Object value,int scope)

public void removeAttribute(java.lang.String name,int scope)

代表各個域的常量

PageContext.APPLICATION_SCOPE

PageContext.SESSION_SCOPE

PageContext.REQUEST_SCOPE

PageContext.PAGE_SCOPE 

findAttribute方法

用標識符爲關鍵字,分別從pagerequestsessionapplication四個 域中查找相應的對象,找到則返回相應對象,找不到則返回”” (注 意,不是null,而是空字符串)

引入和跳轉到其他資源:

PageContext類中定義了一個forward方法和兩個include方法來分別簡化和替RequestDispatcher.forward方法和include方法

傳遞給這些方法的資源路徑都只能是相對路徑,如果路徑以“/”開頭,表示 相對於當前WEB應用程序的根目錄,否則,表示相對於當前JSP所映射到的 訪問路徑

JSP常用標籤:

<jsp:include>標籤:

<jsp:include>標籤用於把另外一個資源的輸出內容插入進當前JSP頁面的輸出 內容之中,這種在JSP頁面執行時的引入方式稱之爲動態引入

語法:<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />

page屬性用於指定被引入資源的相對路徑,它也可以通過執行一個表達式來 獲得

flush屬性指定在插入其他資源的輸出內容時,是否先將當前JSP頁面的已輸 出的內容刷新到客戶端

<jsp:include>include的區別:

<jsp:include>標籤是動態引入, <jsp:include>標籤涉及到的2JSP頁面 會被翻譯成2servlet,這2servlet的內容在執行時進行合併 

include指令是靜態引入,涉及到的2JSP頁面會被翻譯成一個servlet 其內容是在源文件級別進行合併

不管是<jsp:include>標籤,還是include指令,它們都會把兩個JSP頁面內 容合併輸出,所以這兩個頁面不要出現重複的HTML全局架構標籤,否 則輸出給客戶端的內容將會是一個格式混亂的HTML文檔

<jsp:forward>標籤:

<jsp:forward>標籤用於把請求轉發給另外一個資源

語法:<jsp:forward page="relativeURL | <%=expression%>" /> 

page屬性用於指定請求轉發到的資源的相對路徑,它也可以通過執行一個表 達式來獲得

<jsp:param標籤>

當使用<jsp:include><jsp:forward>標籤引入或將請求轉發給其它資源時,可 以使用<jsp:param>標籤向這個資源傳遞參數

語法1:

<jsp:include page="relativeURL | <%=expression%>">

<jsp:param name="parameterName"  value="parameterValue|<%=  expression %>" />

</jsp:include>

語法2

<jsp:forward page="relativeURL | <%=expression%>">

<jsp:param name="parameterName" value="parameterValue|<%=  expression %>" />

</jsp:include>

<jsp:param>標籤的name屬性用於指定參數名,value屬性用於指定參數值。<jsp:include><jsp:forward>標籤中可以使用多個<jsp:param>標籤來傳遞多 個參數

映射JSP

<servlet>

<servlet-name>SimpleJspServlet</servlet-name>

<jsp-file>/jsp/simple.jsp</jsp-file>

<load-on-startup>1</load-on-startup >

</servlet>

……

<servlet-mapping>

<servlet-name>SimpleJspServlet</servlet-name>

<url-pattern>/xxx/yyy.html</url-pattern>

</servlet-mapping>

標籤與簡單標籤:

使用自定義標籤移除jsp頁面中的java代碼,只需要完成以下兩個步驟:

編寫一個實現Tag接口的Java(標籤處理器類)

編寫標籤庫描述符(tld)文件,在tld文件中對標籤處理器類進行描述

Tag接口執行流程:

JSP引擎將遇到自定義標籤時,首先創建標籤處理器類的實例對象,然後按照JSP 規範定義的通信規則依次調用它的方法

1public void setPageContext(PageContext pc), JSP引擎實例化標籤處理器後, 將調用setPageContext方法將JSP頁面的pageContext對象傳遞給標籤處理器, 標籤處理器以後可以通過這個pageContext對象與JSP頁面進行通信

2public void setParent(Tag t)setPageContext方法執行完後,WEB容器接着 調用的setParent方法將當前標籤的父標籤傳遞給當前標籤處理器,如果當前 標籤沒有父標籤,則傳遞給setParent方法的參數值爲null

3public int doStartTag(),調用了setPageContext方法和setParent方法之後, WEB容器執行到自定義標籤的開始標記時,就會調用標籤處理器的doStartTag 方法

4public int doEndTag()WEB容器執行完自定義標籤的標籤體後,就會接着 去執行自定義標籤的結束標記,此時,WEB容器會去調用標籤處理器的 doEndTag方法

5public void release(),通常WEB容器執行完自定義標籤後,標籤處理器會 駐留在內存中,爲其它請求服務器,直至停止web應用時,web容器纔會調release方法

簡單標籤:

簡單標籤共定義了5個方法:

setJspContext方法:用於把JSP頁面的pageContext對象傳遞給標籤處理器對

setParent方法:用於把父標籤處理器對象傳遞給當前標籤處理器對象

getParent方法:用於獲得當前標籤的父標籤處理器對象 

setJspBody方法:用於把代表標籤體的JspFragment對象傳遞給標籤處理器對

doTag方法:用於完成所有的標籤邏輯,包括輸出、迭代、修改標籤體內容等。 在doTag方法中可以拋出javax.servlet.jsp.SkipPageException異常,用於通知 WEB容器不再執行JSP頁面中位於結束標記後面的內容,這等效於在傳統標 籤的doEndTag方法中返回Tag.SKIP_PAGE常量的情況

簡單標籤方法執行順序:

web容器開始執行標籤時,會調用如下方法完成標籤的初始化

WEB容器調用標籤處理器對象的setJspContext方法,將代表JSP頁面的 pageContext對象傳遞給標籤處理器對象

WEB容器調用標籤處理器對象的setParent方法,將父標籤處理器對象傳遞給 這個標籤處理器對象

PS只有在標籤存在父標籤的情況下,WEB容器纔會調用這個方法

如果調用標籤時設置了屬性,容器將調用每個屬性對應的setter方法把屬性值 傳遞給標籤處理器對象。如果標籤的屬性值是EL表達式或腳本表達式,則 WEB容器首先計算表達式的值,然後把值傳遞給標籤處理器對象

如果簡單標籤有標籤體,容器將調用setJspBody方法把代表標籤體的 JspFragment對象傳遞進來

執行標籤時:

容器調用標籤處理器的doTag()方法,開發人員在方法體內通過操作 JspFragment對象,就可以實現是否執行、迭代、修改標籤體的目的

JspFragment類:

WEB容器在處理簡單標籤的標籤體時,會把標籤體內容用一個JspFragment 對象表示,並調用標籤處理器對象的setJspBody方法把JspFragment對象傳遞 給標籤處理器對象。JspFragment類中只定義了兩個方法,如下所示:

getJspContext方法:用於返回代表調用頁面的JspContext對象

public abstract void invoke(java.io.Writer out) 

用於執行JspFragment對象所代表的JSP代碼片段

參數out用於指定將JspFragment對象的執行結果寫入到哪個輸出流對象中, 如果傳遞給參數out的值爲null,則將執行結果寫入到JspContext.getOut()方法 返回的輸出流對象中(簡而言之,可以理解爲寫給瀏覽器)

invoke方法:

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

在標籤處理器中如果沒有調用JspFragment.invoke方法,其結果就相當於 忽略標籤體內容

在標籤處理器中重複調用JspFragment.invoke方法,則標籤體內容將會被 重複執行

若想在標籤處理器中修改標籤體內容,只需在調用invoke方法時指定一 個可取出結果數據的輸出流對象(例如StringWriter),讓標籤體的執行結 果輸出到該輸出流對象中,然後從該輸出流對象中取出數據進行修改後再 輸出到目標設備,即可達到修改標籤體的目的

開發帶屬性的標籤:

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

在標籤處理器中編寫每個屬性對應的setter方法

TLD文件中描術標籤的屬性

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

eg:屬性url,在標籤處理器類中就要定義相應的 setUrl(String url)方法

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

tld文件中描述標籤屬性:


一個完整的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">

    <tag>

        <name>demo6</name>  <!-- 爲標籤處理器類配一個標籤名 -->

<tag-class>cn.itcast.web.simpletag.SimpleTagDemo6</tag-class>

<body-content>scriptless</body-content>

<attribute>

<name>date</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>  <!-- 指示屬性的值是否可以爲一個表達式 -->

</attribute>

    </tag>

</taglib>

JSTL標籤庫:

<c:out>標籤:

<c:out> 標籤用於輸出一段文本內容到pageContext對象當前保存的“out”對 象中


如:<% 

   request.setAttribute("data",null);

   %>

<c:out value="${data}" escapeXml="true" default="對不起,您要的數據找 不着喲!!!"></c:out>

<c:set>標籤:

<c:set>標籤用於把某一個對象存在指定的域範圍內,或者設置Web域中的 java.util.Map類型的屬性對象或JavaBean類型的屬性對象的屬性


如:<c:set var="data" value="xxx" scope="page"/>

    ${pageScope.data }

    <% 

     Map map = new HashMap();

     request.setAttribute("map",map);

    %>

    <c:set property="data" value="yyyyy" target="${map}"/>

    ${map.data }

    <%--<c:set property="name" value="flx" target="${person}"></c:set>--%>

<c:remove>標籤:

<c:remove>標籤用於刪除各種Web域中的屬性

語法:<c:remove var="varName" 

[scope="{page|request|session|application}"] />

<c:catch>標籤:

<c:catch>標籤用於捕獲嵌套在標籤體中的內容拋出的異常

語法:<c:catch [var="varName"]>nested actions</c:catch>

<c:if>標籤:

<c:if test=” ”>標籤可以構造簡單的“if-then”結構的條件表達式

如: <c:if test="${user==null}" var="b" scope="page"></c:if>

<c:choose>標籤:

<c:choose>標籤用於指定多個條件選擇的組合邊界,它必須與<c:when> <c:otherwise>標籤一起使用。使用<c:choose><c:when><c:otherwise>三個 標籤,可以構造類似 “if-else if-else”的複雜條件判斷結構

<c:forEach>標籤:

<c:forEach>標籤用於對一個集合對象中的元素進行循環迭代操作,或者按指定的次數重複迭代執行標籤體中的內容

如:<c:forEach var="num" begin="1" end="10" step="1">

     ${num }

    </c:forEach>

    <% 

     List list = Arrays.asList("1","2");

     request.setAttribute("list",list);

    %>

    <c:forEach var="index"  begin="0" end="${fn:length(list)}">

     ${list[index] }

    </c:forEach>

<c:forEach>標籤的使用

在JSP的開發中,迭代是經常要使用到的操作。例如,逐行的顯示查詢的結果等。在早期的JSP中,通常使用Scriptlets來實現Iterator或者Enumeration對象的迭代輸出。現在,通過JSTL的迭代標籤可以在很大的程度上簡化迭代操作。

         JSTL所支持的迭代標籤有兩個,分別是<c:forEach>和<c:forTokens>。在這裏介紹的是<c:forEach>標籤。

         簡單點說,<c:forEach>標籤的作用就是迭代輸出標籤內部的內容。它既可以進行固定次數的迭代輸出,也可以依據集合中對象的個數來決定迭代的次數。

      <c:forEach>標籤的語法定義如下所示。

        <c:forEach var="name" items="expression" varStatus="name"                            begin="expression" end="expression" step="expression">

                           body content

                  </c:forEach>

        <c:forEach>標籤具有以下一些屬性:

var:迭代參數的名稱。在迭代體中可以使用的變量的名稱,用來表示每一個迭代變量。類型爲String。

items:要進行迭代的集合。對於它所支持的類型將在下面進行講解。

varStatus:迭代變量的名稱,用來表示迭代的狀態,可以訪問到迭代自身的信息。

begin:如果指定了items,那麼迭代就從items[begin]開始進行迭代;如果沒有指定items,那麼就從begin開始迭代。它的類型爲整數。

end:如果指定了items,那麼就在items[end]結束迭代;如果沒有指定items,那麼就在end結束迭代。它的類型也爲整數。

step:迭代的步長。

         <c:forEach>標籤的items屬性支持Java平臺所提供的所有標準集合類型。此外,您可以使用該操作來迭代數組(包括基本類型數組)中的元素。它所支持的集合類型以及迭代的元素如下所示:

java.util.Collection:調用iterator()來獲得的元素。

java.util.Map:通過java.util.Map.Entry所獲得的實例。

java.util.Iterator:迭代器元素。

java.util.Enumeration:枚舉元素。

Object實例數組:數組元素。

基本類型值數組:經過包裝的數組元素。

用逗號定界的String:分割後的子字符串。

javax.servlet.jsp.jstl.sql.Result:SQL查詢所獲得的行。

         不論是對整數還是對集合進行迭代,<c:forEach>的varStatus屬性所起的作用相同。和var屬性一樣,varStatus 用於創建限定了作用域的變量(改變量只在當前標籤體內起作用)。不過,由varStatus屬性命名的變量並不存儲當前索引值或當前元素,而是賦予 javax.servlet.jsp.jstl.core.LoopTagStatus類的實例。該類包含了一系列的特性,它們描述了迭代的當前狀態,如 下這些屬性的含義如下所示:

current:當前這次迭代的(集合中的)項。

index:當前這次迭代從0開始的迭代索引。

count:當前這次迭代從1開始的迭代計數。

first:用來表明當前這輪迭代是否爲第一次迭代,該屬性爲boolean類型。

last:用來表明當前這輪迭代是否爲最後一次迭代,該屬性爲boolean類型。

begin:begin屬性的值。

end:end屬性的值

step:step屬性的值

<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>標籤的最大好處

eg:<c:param name="name" value="value" />

<c:url>標籤:

<c:url>標籤用於在JSP頁面中構造一個URL地址,其主要目的是實現URL 寫,URL重寫就是將會話標識號以參數形式附加在URL地址後面

如: <c:url value="/servlet/ServletDemo1" var="servletdemo1">

     <c:param name="name" value="中國"/>

     <c:param name="password" value="我是一個"/>

    </c:url>

    <a href="${servletdemo1 }">點點</a>

<c:redirect>標籤:

<c:redirect>標籤用於實現請求重定向


EL表達式:

主要作用:

獲取數據:

EL表達式主要用於替換JSP頁面中的腳本表達式,以從各種類型的web 域 中檢索java對象、獲取數據(某個web域 中的對象,訪問javabean 的屬性、訪問list集合、訪問map集合、訪問數組)

執行運算:

利用EL表達式可以在JSP頁面中執行一些基本的關係運算、邏輯運算和 算術運算,以在JSP頁面中完成一些簡單的邏輯運算,如${user==null}

獲取web開發常用對象

EL 表達式定義了一些隱式對象,利用這些隱式對象,web開發人員可以 很輕鬆獲得對web常用對象的引用,從而獲得這些對象中的數據。

調用Java方法

EL表達式允許用戶開發自定義EL函數,以在JSP頁面中通過EL表達式 調用Java類的方法

EL表達式獲取數據語法:${標識符}

執行原理:

EL表達式語句在執行時,會調用pageContext.findAttribute方法,用標識符爲 關鍵字,分別從pagerequestsessionapplication四個域中查找相應的對象, 找到則返回相應對象,找不到則返回” ”(注意,不是null,而是空字符串)

EL表達式也可以很輕鬆獲取JavaBean的屬性,或獲取數組、CollectionMap類型 集合的數據,例如:

${user.address.city} 訪問javabean中的屬性

${user.list[0]}:訪問有序集合某個位置的元素

${map.key}  : 獲得map集合中指定key的值

結合JSTLforeach標籤,使用EL表達式也可以很輕鬆迭代各種類型的數組 或 集合,如:

迭代數組

迭代collection類型集合

迭代map類型集合

獲取數據的例子:

  <% 

     request.setAttribute("name","aaa");

    %>

    ${name }  <%--pageContext.findAttribute("name") --%>

    <!-- jsp頁面中,使用el表達式可以獲取bean的屬性 -->

    <% 

     Person p = new Person();

     p.setAge(12);

     request.setAttribute("person",p);

    %>

    ${person.age }

    <!-- jsp頁面中,使用el表達式可以獲取bean中的。。。。。。。。。的屬性 -->

    <% 

     Person person = new Person();

     Address address = new Address();

     person.setAddress(address);

     request.setAttribute("person",person);

    %>

   ${person.address.name }

    <!-- jsp頁面中,使用el表達式獲取list集合中指定位置的數據 -->

    <% 

     Person p1 = new Person();

     p1.setName("aa111");

     Person p2 = new Person();

     p2.setName("bb");

     List list = new ArrayList();

     list.add(p1);

     list.add(p2);

     request.setAttribute("list",list);

    %>

    ${list[1].name }  <!-- list指定位置的數據 -->

    <!-- 迭代集合 -->

    <c:forEach var="person" items="${list}">

     ${person.name }

    </c:forEach>

    <!-- jsp頁面中,使用el表達式獲取map集合的數據 -->

    <% 

     Map map = new HashMap();

     map.put("a","aaaaxxx");

     map.put("b","bbbb");

     map.put("c","cccc");

     map.put("1","aaaa1111");

     request.setAttribute("map",map);

    %>

   ${map.c }  <!-- 根據關鍵字取map集合的數據 -->

   ${map["1"] }

   <c:forEach var="me" items="${map}">

   ${me.key }=${me.value }<br/>

   </c:forEach>

執行運算:

語法:${ 運算表達式 }

empty運算符:檢查對象是否爲null或“空”,很好用!!!

二元表達式:${user!=null?user.name : “  ”} ,很好用!!!

[ ] 和 號運算符

執行運算的例子:

${365*24 }

${user==null }

    <% 

     List list = null;

     //List list = new ArrayList();

     //list.add("a");

     //list.add("b");

     request.setAttribute("list",list);

    %>

    <c:if test="${!empty(list)}">

     <c:forEach var="str" items="${list}">

     ${str }

     </c:forEach>

    </c:if>

    <c:if test="${empty(list)}">

     對不起,沒有您想看的數據

    </c:if>

    <% 

     session.setAttribute("user",new User("vvvv"));

    %>

    ${user==null? "對不起,您沒有登陸 " : user.username }

    <% 

     User user = new User();

     user.setGender("male");

     //數據回顯

     request.setAttribute("user",user);

    %>

    <input type="radio" name="gender" value="male"                                                   ${user.gender=='male'?'checked':'' }>

    <input type="radio" name="gender" value="female"     ${user.gender=='female'?'checked':'' }>

    <% 

     user = new User();

     String likes[] = {"sing","dance","football"};

     user.setLikes(likes);

     //數據回顯

     request.setAttribute("user",user);

    %>

獲得web開發常用隱式對象:

EL表達式語言中定義了11個隱含對象,使用這些隱含對象可以很方便地獲取 web開發中的一些常見對象,並讀取這些對象的數據

語法:${ 隱式對象名稱 }  獲得對象的引用


PS測試headerValues時,如果頭裏面有“-” ,例Accept-Encoding,則要 headerValues[Accept-Encoding]

測試cookie時,例${cookie.key}取的是cookie對象,如訪問cookie的名稱和 值,須${cookie.key.name}${cookie.key.value}

獲得隱式對象例子:

  <br/>---------------從指定的page域中查找數據------------------------<br/>

    <% 

     pageContext.setAttribute("name","aaa");  //map

    %>

    ${pageScope.name }

    <br/>---------------request域中獲取數據------------------------<br/>

    <% 

    request.setAttribute("name","bbb");  //map

    %>

    ${requestScope.name }

    <br/>---------------session域中獲取數據------------------------<br/>

    ${sessionScope.user }

    <br/>--------------獲得用於保存請求參數map,並從map中獲取數據 ------------------------<br/>

    <!-- http://localhost:8080/day12/3.jsp?name=aaa  -->

    ${param.name }     <!-- 此表達式會經常用在數據回顯上 -->

    <form action="${pageContext.request.contextPath }/servlet/RegisterServlet"  method="post">

    <input type="text" name="username" value="${param.username }">

    <input type="submit" value="註冊">

    </form>

    <br/>--------------paramValues獲得請求參數    //map{"",String[]}------------------------<br/>

    <!-- http://localhost:8080/day12/3.jsp?like=aaa&like=bbb -->

    ${paramValues.like[0] }  

    ${paramValues.like[1] } 

    <br/>--------------header獲得請求頭------------------------<br/>

    ${header.Accept } 

    ${header["Accept-Encoding"] }

    <br/>--------------獲取客戶機提交的cookie------------------------<br/>

    <!-- cookie隱式對象中根據名稱獲取到的是cookie對象,要想獲取值, 還需要.value -->

    ${cookie.JSESSIONID.value }  //保存所有cookiemap

    <br/>--------------獲取web應用初始化參數------------------------<br/>

    ${initParam.xxx }  //servletContext中用於保存初始化參數的map

    ${initParam.root }

使用EL調用java方法:

EL表達式語法允許開發人員開發自定義函數,以調用Java類的方法

語法:${  prefix:method(params)  }

EL表達式中調用的只能是Java類的靜態方法

這個Java類的靜態方法需要在TLD文件中描述,纔可以被EL表達式調用

EL自定義函數用於擴展EL表達式的功能,可以讓EL表達式完成普通Java 程序代碼所能完成的功能

EL function 的開發步驟:

a.編寫一個Java類的靜態方法

b.WEB-INF編寫標籤庫描述符(tld)文件,在tld文件中描述自定 義函數

c.在JSP頁面中導入和使用自定義函數

示例:開發對html進行轉義EL方法

帶靜態方法的java

package cn.itcast;

public class HtmlFilter {

 public static String filter(String message) {

        if (message == null)

            return (null);

        char content[] = new char[message.length()];

        message.getChars(0, message.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {

            switch (content[i]) {

            case '<':

                result.append("<");

                break;

            case '>':

                result.append(">");

                break;

            case '&':

                result.append("&");

                break;

            case '"':

                result.append(""");

                break;

            default:

                result.append(content[i]);

            }

        }

        return (result.toString());

    }

}

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>A tag library exercising SimpleTag handlers.</description>

    <tlib-version>1.0</tlib-version>

    <short-name>SimpleTagLibrary</short-name>

    <uri>/itcast</uri>

    <function>

        <name>filter</name>

<function-class>cn.itcast.HtmlFilter</function-class>

<function-signature>

java.lang.String filter(java.lang.String)

</function-signature>

    </function>

</taglib>

在jsp頁面使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@taglib uri="/WEB-INF/itcast.tld" prefix="fn" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01  Transitional//EN">

<html>

  <head>

    <title>user EL function</title>

  </head>

  <body>

   ${fn:filter("<a href=''>點點</a>") }

  </body>

</html>

注意事項:

編寫完標籤庫描述文件後,需要將它放置到<web應用>\WEB-INF目錄中WEB-INF目錄下的除了classeslib目錄之外的任意子目錄中 

TLD文件中的<uri> 元素用指定該TLD文件的URI,在JSP文件中需要 通過這個URI來引入該標籤庫描述文件

<function>元素用於描述一個EL自定義函數,其中:

<name>子元素用於指定EL自定義函數的名稱

<function-class>子元素用於指定完整的Java類名

<function-signature>子元素用於指定Java類中的靜態方法的簽名,方法籤 名必須指明方法的返回值類型及各個參數的類型,各個參數之間用逗號分 隔

有些Tomcat服務器如不能使用EL表達式

1)升級成tomcat6

2)在JSP中加入<%@ page isELIgnored="false" %>

EL函數庫:

要使用EL函數,需要在頁面導入:

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

常用的EL函數:

fn:toLowerCase

fn:toLowerCase函數將一個字符串中包含的所有字符轉換爲小寫形 式,並返回轉換後的字符串,它接收一個字符串類型的參數

如:fn:toLowerCase("Www.IT315.org") 的返回值爲字符串www.it315.org,方法參數爲空則返回空

fn:toUpperCase:

fn:toUpperCase函數將一個字符串中包含的所有字符轉換爲大寫形 式,並返回轉換後的字符串,它接收一個字符串類型的參數

如:fn:toUpperCase("Www.IT315.org") 的返回值爲字符串WWW.IT315.ORG,方法參數爲空則返回空

fn:trim:

fn:trim函數刪除一個字符串的首尾的空格,並返回刪除空格後的結果 字符串,它接收一個字符串類型的參數。需要注意的是,fn:trim函數 不能刪除字符串中間位置的空格

如:fn:trim("   www.it315.org  ") 的返回值爲字符串“www.it  315.org

fn:length:

fn:length函數返回一個集合或數組大小,或返回一個字符串中包含的 字符的個數,返回值爲int類型。fn:length函數接收一個參數,這個 參數可以是<c:forEach>標籤的items屬性支持的任何類型,包括任意 類型的數組、java.util.Collectionjava.util.Iterator java.util.Enumerationjava.util.Map等類的實例對象和字符串

如果fn:length函數的參數爲null或者是元素個數爲0的集合或數組 對象,則函數返回0;如果參數是空字符串,則函數返回0

fn:split:

fn:split函數以指定字符串作爲分隔符,將一個字符串分割成字符串 數組並返回這個字符串數組

fn:split函數接收兩個字符串類型的參數,第一個參數表示要分割的 字符串,第二個參數表示作爲分隔符的字符串

如:fn:split("www.it315.org", ".")[1]的返回值爲字符串“it315

fn:join:

fn:join函數以一個字符串作爲分隔符,將一個字符串數組中的所有元 素合併爲一個字符串並返回合併後的結果字符串。fn:join函數接收兩 個參數,第一個參數是要操作的字符串數組,第二個參數是作爲分隔 符的字符串

如果fn:join函數的第二個參數是空字符串,則fn:join函數的返回值 直接將元素連接起來

如:假設stringArray是保存在Web域中的一個屬性,它表示一個值{"www","it315","org"}的字符串數組,則fn:join(stringArray, .") 返回字符串“www.it315.org

fn:join(fn:split("www,it315,org", ","), ".") 的返回值爲字符串www.it315.org

fn:indexOf:

fn:indexOf函數返回指定字符串在一個字符串中第一次出現的索引 值,返回值爲int類型。fn:indexOf函數接收兩個字符串類型的參數, 如果第一個參數字符串中包含第二個參數字符串,那麼,不管第二個 參數字符串在第一個參數字符串中出現幾次,fn:indexOf函數總是返 回第一次出現的索引值;如果第一個參數中不包含第二個參數,則 fn:indexOf函數返回-1。如果第二個參數爲空字符串,則fn:indexOf 函數總是返回0

如:fn:indexOf("www.it315.org","t3") 的返回值爲5

fn:contains:

fn:contains函數檢測一個字符串中是否包含指定的字符串,返回值爲 布爾類型。fn:contains函數在比較兩個字符串是否相等時是大小寫敏 感的

fn:contains函數接收兩個字符串類型的參數,如果第一個參數字符串 中包含第二個參數字符串,則fn:contains函數返回true,否則返回 false。如果第二個參數的值爲空字符串,則fn:contains函數總是返回 true。實際上,fn:contains(string, substring)等價於fn:indexOf(string,  substring) != -1

忽略大小的EL函數:fn:containsIgnoreCase 

fn:startsWith:

fn:startsWith函數用於檢測一個字符串是否是以指定字符串開始的, 返回值爲布爾類型

fn:startsWith函數接收兩個字符串類型的參數,如果第一個參數字符 串以第二個參數字符串開始,則函數返回true,否則函數返回false 如果第二個參數爲空字符串,則fn:startsWith函數總是返回true

如:fn:startsWith("www.it315.org","it315")的返回值爲false

與之對應的EL函數:fn:endsWith 

fn:replace:

fn:replace函數將一個字符串中包含的指定子字符串替換爲其它的指 定字符串,並返回替換後的結果字符串。fn:replace方法接收三個字 符串類型的參數,第一個參數表示要操作的源字符串,第二個參數表 示源字符串中要被替換的子字符串,第三個參數表示要被替換成的字 符串

如:fn:replace("www it315 org", " ", ".")的返回值爲字符串www.it315.org

fn:substring:

fn:substring函數用於截取一個字符串的子字符串並返回截取到的子 字符串。fn:substring函數接收三個參數,第一個參數是用於指定要操 作的源字符串,第二個參數是用於指定截取子字符串開始的索引值, 第三個參數是用於指定截取子字符串結束的索引值,第二個參數和第 三個參數都是int類型,其值都從0開始

如:fn:substring("www.it315.org", 4, 9) 的返回值爲字符串“it315

fn:substringAfter:

fn:substringAfter函數用於截取並返回一個字符串中的指定子字符串 第一次出現之後的子字符串。fn:substringAfter函數接收兩個字符串 類型的參數,第一個參數表示要操作的源字符串,第二個參數表示指 定的子字符串

如:fn:substringAfter(www.it315.org.)的返回值爲字符串it315.org

與之對應的EL函數爲:fn:substringBefore 

文件上傳:

package cn.itcast.web.contorller;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet3 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

try{

//1.得到解析器工廠

DiskFileItemFactory factory = new DiskFileItemFactory();

//2.得到解析器

ServletFileUpload upload = new ServletFileUpload(factory);

//3.判斷上傳表單的類型

if(!upload.isMultipartContent(request)){

//上傳表單爲普通表單,則按照傳統方式獲取數據即可

return;

}

//爲上傳表單,則調用解析器解析上傳數據

List<FileItem> list = upload.parseRequest(request);  //FileItem

//遍歷list,得到用於封裝第一個上傳輸入項數據fileItem對象

for(FileItem item : list){

if(item.isFormField()){

//得到的是普通輸入項

String name = item.getFieldName();  //得到輸入項的名稱

String value = item.getString();

System.out.println(name + "=" + value);

}else{

//得到上傳輸入項

String filename = item.getName();  //得到上傳文件名   C:\Documents and Settings\ThinkPad\桌面\1.txt

filename = filename.substring(filename.lastIndexOf("\\")+1);

InputStream in = item.getInputStream();   //得到上傳數據

int len = 0;

byte buffer[]= new byte[1024];

//用於保存上傳文件的目錄應該禁止外界直接訪問

String savepath =  this.getServletContext().getRealPath("/WEB-INF/upload");

System.out.println(savepath);

FileOutputStream out = new FileOutputStream(savepath + "\\"  + filename);  //upload目錄中寫入文件

while((len=in.read(buffer))>0){

out.write(buffer, 0, len);

}

in.close();

out.close();

}

}

}catch (Exception e) {

e.printStackTrace();

}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}


好啦   jsp部分到此爲止

發佈了32 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章