WEB-11-JSP-cookie session 作用域 標籤技術

一、JSP01
1.概述
jsp其實是java的動態頁面技術
HTML可以用來組織頁面但是HTML是一種靜態web資源技術 無法嵌入動態數據。
Servlet是動態web資源技術 但是本質上是一段java代碼 不方便在其中組織頁面結構。
於是jsp技術被提出來 寫起來就像在寫一個html,但是內部可以嵌入java代碼,本質上是一種動態web資源 但是可以直接寫html標籤 非常便於組織頁面結構。
jsp解決了 動態頁面開發的問題。
真正的開發中 往往使用Servlet來處理業務邏輯 將處理好的結構 帶到jsp頁面 由jsp頁面負責展示。


2.原理
jsp會在第一次被訪問的時候 被翻譯成一個Servlet 之後對這個jsp的訪問 本質上都是這個Servlet在執行。
所以眼睛裏看的是個jsp 心裏要明白其實是個Servlet在執行。


3.JSP基本組成結構
(1)模版元素
在jsp頁面中直接編寫的HTML內容 組成了jsp的結構 這些html內容稱之爲jsp的模版元素
在被翻譯成Servlet的過程中 被 直接 out.write 原樣輸出到瀏覽器頁面


(2)腳本表達式 <%= java表達式 %>
在jsp頁面中可以通過腳本表達式 來將一個java表達式計算的結果輸出到中
在被翻譯成Servlet的過程中 直接被out.print()輸出 表達式計算完的結果


(3)腳本片段 <% 若干java語句 %>
在jsp頁面中可以通過腳本片段直接寫入一段java代碼
在被翻譯成Servlet的過程中 腳本片段原樣 被複制粘貼到對應位置 直接執行


注意:同一個頁面中 多個腳本片段 後面的可以看到前面定義的變量
注意:一個腳本片段可以不完整 但是要保證整個頁面 翻譯過來的Servlet中 語法要完整


(4)JSP聲明 <%! %>
可以通過JSP聲明爲翻譯過來的Servlet增加類的成員。
在jsp聲明中聲明的內容 會在被翻譯成Servlet的過程中 被放置到和Service方法同級的位置 成爲類的成員。




(5)JSP註釋 <%-- --%>
可以通過JSP註釋將jsp中的部分內容註釋掉 
被註釋的內容不會被翻譯到Servlet中


注意:在jsp頁面中可能出現如下三種註釋
jsp註釋  <%-- --%>  不會被翻譯到Servlet
java註釋 <% //String str = "abc"; %> 被翻譯到Servlet中 但是java代碼被註釋 不會被執行
html註釋 <!-- --> 被翻譯到Servlet中當作模版元素直接輸出到瀏覽器


Servlet擅長寫java代碼處理業務邏輯但是不擅長輸出頁面 Jsp擅長輸出頁面但是不擅長處理業務邏輯
所以在真正的開發中 往往 將請求提交到Servlet中 進行業務處理 通過請求轉發利用request域將結果發給 JSP ,JSP負責展示。




一、會話技術
1.會話概述
一個瀏覽器 爲了實現某一個功能  對服務器產生了多次請求響應。從第一個請求開始訪問服務器,會話開始,到最後一個頁面訪問結束 關閉所有頁面,這個過程中的所有的請求響應加在一起稱之爲 瀏覽器和服務器之間產生了一次會話。


會話技術中 最重要的問題就是會話產生的數據 如何保存。


request域 - 不行 - 太小了 - 每次請求響應都是一個新的request 後續的請求中無法看到之前請求request裏存放的數據
servletContext域 - 不行 - 太大了 - 所有的會話 看到的都是同一個ServletContext域 所有會話的數據混雜在一起 必然混亂


cookie - 將會話產生的數據存放在客戶端


session - 將會話產生的數據存放在服務器端



2.Cookie
Cookie是客戶端技術 將會話產生的數據保存在客戶端中
當瀏覽器訪問服務器 服務器可以通過在響應中增加set-Cookie的響應頭 命令瀏覽器保存一段cookie信息
瀏覽器會將cookie信息保存在本地 之後再去訪問服務器時 會自動在請求中 通過cookie請求頭 帶着cookie信息
服務器可以通過解析請求中的cookie請求頭 獲取信息 從而獲取到了之前保存的會話相關的數據


案例:
展示上一次訪問時間




爲了方便cookie的開發,java專門提供了一套和cookie相關的api


Cookie類的基本方法
//Cookie沒有無參的構造 cookie創建時就必須指定好cookie的名字和cookie的值
Cookie cookie = new Cookie(String name,String value);


//Cookie的名字只能獲取 不能修改
String getName()
String getValue(String name)
String setValue(String name ,String value)


//向響應中加入cookie
response.setCookie(Cookie c);


//從請求中獲取cookie
Cookie [] request.getCookies();

Cookie保存的時長
如果不設置 默認Cookie會被保存在瀏覽器的內存中 瀏覽器什麼時候關 Cookie什麼時候消失 這種cookie稱之爲會話級別的cookie
也可以通過代碼來設置cookie的保存時長


//指定瀏覽器 將cookie保存到什麼時候 瀏覽器收到的cookie信息中如果包含了 指定的超時時間 瀏覽器就會cookie信息以文件的形式保存到瀏覽器的臨時文件夾中 保存到指定的時間 這段時間內該文件一直存在 即使多次開關瀏覽器 仍然能夠看到此cookie
setMaxAge(int time)
int getMaxAge()


Cookie在訪問哪些路徑時攜帶cookie
如果不設置 則在訪問發送cookie給瀏覽器的Servlet的父一級目錄及其子孫目錄時 會攜帶這個cookie
http://localhost/Day12/servlet/LastTimeServlet2
-->
http://localhost/Day12/servlet/




//可以通過方法設置瀏覽器在訪問哪些路徑時攜帶此cookie
setPath(String path)
String getPath()



刪除cookie
如果想要刪除cookie 需要發送一個 和要刪除的cookie的名字相同 path相同 但是maxAge被設置爲0的 cookie
這樣一來 名字相同 path也相同 瀏覽器收到cookie後 覆蓋原來的cookie 只有 立即超時 自動被瀏覽器刪除掉
從而間接的實現了刪除cookie的操作




cookie其他
一個Cookie只能標識一種信息,它至少含有一個標識該信息的名稱(NAME)和設置值(VALUE)。
一個WEB站點可以給一個WEB瀏覽器發送多個Cookie,一個WEB瀏覽器也可以存儲多個WEB站點提供的Cookie。
瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制爲4KB。
如果創建了一個cookie,並將他發送到瀏覽器,默認情況下它是一個會話級別的cookie(即存儲在瀏覽器的內存中),用戶退出瀏覽器之後即被刪除。若希望瀏覽器將該cookie存儲在磁盤上,則需要使用maxAge,並給出一個以秒爲單位的時間。將最大時效設爲0則是命令瀏覽器刪除該cookie。
注意,刪除cookie時,path必須一致,否則不會刪除(瀏覽器通過cookie的name+path來標識一個cookie)


案例:EasyMall登陸功能記住用戶名



3.Session
Session是服務器端會話數據保存技術
服務器在需要時 可以爲每個用戶創建獨一無二專爲該用戶服務的session對象 在其中保存該用戶會話相關的數據
之後該用戶再來訪問服務器時 可以找到之前創建的屬於他的session 從中找到之前存入的數據 從而實現會話數據的保存
由於每個用戶各自有各自的session 每個session只爲對應的用戶服務 數據不會混亂。


Session是一個域對象
生命週期
當第一次調用request.getSession()方法時表明 會話中需要用到session了,此時服務器創建session對象,一直駐留在內存中爲當前會話服務。


自殺 - 可以明確的調用session.invalidate()立即殺死session。
超時 - 如果一個session超過30分鐘 沒人用 則 服務器認爲會話超時 殺死會話對應的session
意外身亡 - 當前web應用銷燬時,session跟着被銷燬。
作用範圍
整個會話
主要功能
在會話範圍內共享數據


創建、獲取Session
request.getSession()
操作域
session.setAttribute()
session.getAttribute()
session.removeAttribute()
殺死session
session.invalidate()






案例:利用session實現登錄 註銷
所謂的登錄,其實就是根據用戶提交 的用戶名和密碼 檢查數據庫 
如果不正確就提示 如果正確 就創建session 保存該用戶的登錄標記
之後的訪問中可以通過檢查登錄標記 獲知當前用戶是否登錄 如果登錄過 該用用戶是誰


所謂的註銷其實就是殺死session 使session中的登錄標記失效

案例:驗證碼校驗 數據的回顯
ValiImgServlet --> 生成驗證碼時 將驗證碼的內容 存入 session中備用
regist.jsp --> 註冊時填寫了註冊表單 其中有驗證碼 跟着被提交
RegistServlet -> 從請求參數中獲取用戶提交的驗證碼 從session中獲取當初發給他的驗證碼 兩個進行比較 如果不一致 中止註冊過程 提示用戶 驗證碼不正確 如果兩個一致 驗證碼正確 繼續註冊流程
regist.jsp --> 如果驗證碼校驗不通過 回到註冊頁面 要從request域中獲取錯誤消息 進行提示
如果驗證碼校驗不通過 回到註冊頁面 進行數據的回顯 -- 將之前提交的表單的數據 顯示回來 


原理
session是基於一個叫做jsessionid的cookie工作的


當瀏覽器訪問服務器 調用到 request.getSession時 此方法會檢查請求中是否 有叫做jsessionid的cookie
如果沒有 則說明這時這是第一次用到session 創建session使用 並將session id 作爲jsessionid cookie 發送給瀏覽器保存
瀏覽器在後續的訪問中 就會帶着這個jsessionid 來訪問
後續再調用到 request.getSession 時 此方法檢查請求中 是否有叫做jsessionid的cookie 發現有 則在內存中倒找id對應的session使用
如果找不到 說明session 已經被銷燬 則創建新的session使用個 並在響應中再通過cookie發送新的jsessionid

**瞭解即可**如果禁用了cookie session也就用不了了 - 可以通過URL重寫來解決
如果禁用了cookie 瀏覽器不再基於cookie來保存jsessionid 在服務器無法獲取到jsessionid 也就無法找對應的session 
所以想解決這個問題 就需要想辦法 將jsessionid的值 帶給服務器
此時可以使用URL重寫的技術來實現
所謂的URL的重寫 就是 將地址 改寫 在地址後使用特殊的參數 攜帶jsessionid的技術 
雖然cookie用不了了 但是 通過地址 仍然可以攜帶jsessionid的信息 從而使用session


這個技術 需要將應用中所有的地址都要進行URL重寫 相對來說非常麻煩
而這麼麻煩帶來的唯一的好處是 禁用cookie後仍然可以使用session 似乎並不值得這麼麻煩
所以 現在很多網站 都不會去做URL重寫 對於禁用cookie的情況 不處理 或者 檢測到用過戶禁用cookie就引導用戶 打開瀏覽器的cookie 再來使用網站


response.encodeURL(String url);
//--如果是普通的地址用這個方法
response.encodeRedirectURL(String url);
//--如果地址是用來進行重定向的,用這個方法


4.cookie和session的區別
cookie將會話相關數據保存在客戶端 session將會話相關的數據保存在服務器端
cookie可以保存的時間比較長 session超過30分種沒人用就銷燬
cookie有可能隨着用戶的操作被清除 session只要不手動刪除 在存活期間可以可靠的訪問
cookie將信息保存在瀏覽器中 可以通過翻臨時文件夾 查看cookie中的數據 不安全 session將會話相關的數據保存在服務器內存中 安全性高很高。


如果需要將會話數據保存的很久 -- cookie
如果希望會話數據不會因爲用戶的操作丟失 -- session

如果會話數據比較在意安全性 -- session


========================================================================================================================================
路徑專題:
相對路徑:不以/開頭的路徑稱爲相對路徑,相對路徑是基於當前路徑進行計算得到的一個路徑。其中可以通過../表示上一級目錄。
絕對路徑:以/開頭的路徑稱爲絕對路徑,絕對路徑是在一個參考路徑上直接拼接而得到的路徑。
盤符開始的絕對路徑(硬盤路徑):直接從盤符開始,說是哪就是哪。


WEB階段路徑編寫:
虛擬路徑:
寫絕對路徑,不到萬不得已不要用相對路徑。
寫絕對路徑的情況下,如果路徑是個瀏覽器用的則參考路徑是當前虛擬主機,一定要寫應用名。如果路徑是給服務器用的則參考路徑是當前web應用,應用名層一定不要寫。
request.getRequestDispatcher("/index.jsp").forward();
request.getRequestDispatcher("/index.jsp").include();
response.setHeader("refresh","1;url=/Day08/index.jsp");
response.setHeader("Location","/Day08/index.jsp");
response.sendRedirect("/Day08/index.jsp");
<a href="/Day08/index.jsp">
<img src="/Day08/index.jsp">
<form action="/Day08/index.jsp">
<link href="/Day08/index.jsp">
<script srce="/Day08/index.jsp">




真實路徑:
具體問題具體分析

File file = new File("");//如果寫相對路徑到程序的啓動目錄下找資源(tomcat/bin),如果寫覺對路徑就到程序啓動目錄的根目錄下找資源。如果寫硬盤路徑,可以找到資源,但是通常一旦換了一個環境,路徑很可能需要修改。
servletContext.getRealPath("");//此方法在傳入的路徑前拼接當前web應用的硬盤路徑,拼接出當前資源的硬盤路徑,所以給一個相對於當前web應用根目錄的路徑即可。
classLoader.getResource("");//類加載器在哪裏加載類就在哪裏加載資源,所以要給一個相對於類加載位置的路徑。







*------------------------------------------------------------------------------------------------------------------------------------------------------------------------***

一、jsp
1.jsp概述
sun公司提供的動態web資源開發技術。
Servlet本質上是一段java程序,非常適合於編寫邏輯處理,但是不便於對外輸出html格式的頁面。
爲了解決這樣的問題,sun提供了jsp這樣的技術,改變了原來Servlet在java中編寫html的過程,變爲了jsp在html中編寫java的過程。
jsp看起來就像一個html頁面一樣,但是其中可以嵌入java代碼,本質上是一種動態web資源開發技術。
jsp在第一次被訪問到時被翻譯成一個Servlet,對這個jsp的訪問其實是翻譯過來的Servlet在執行

2.jsp語法
模板元素:直接寫在jsp中的html內容稱爲模版元素。模版元素組成了jsp頁面的基本骨架。
在翻譯過來的Servlet中直接被out.write輸出到了頁面


腳本表達式:<%= java表達式%> 其中可以編寫java表達式,注意是表達式而不是語句,所以後面不能有分號
在翻譯過來的Servlet中,計算了表達式的值後被輸出到瀏覽器頁面。


腳本片段:<% 若干java語句 %> 其中可以編寫若干java語句,注意是語句,必須有分號。
在翻譯過來的Servlet中被複制粘貼到了對應位置執行。
一個jsp頁面中可以有多個腳本片段,多個腳本片段之間可以互相訪問。
某個腳本片段中的代碼可以不完整,但是要保證在翻譯過來的Servlet中java代碼要完整。


jsp聲明:<%! 若干java語句%> 可以爲翻譯過來的Servlet來增加類的成員
寫在其中的代碼將會在翻譯過來的Servlet中被放置到和service方法同級的位置成位類的一個成員。


jsp註釋:
<%-- 註釋的內容 --%>  被jsp註釋註釋的內容,不會被翻譯到Servlet中,在翻譯過程中就被丟棄了。
// /**/ /** */ 被java註釋註釋的內容,在翻譯時當做java代碼原樣複製粘貼到對應位置,但是被註釋了,不會執行,在被編譯爲class時被丟棄
<!-- --> 被html註釋註釋的內容,被當做模版元素,原樣輸出給了瀏覽器,瀏覽器認識該標籤,當做html註釋不予顯示。
jsp指令:<%@ 指令名 若干屬性 %> 不直接產生任何的輸出,是用來只會解析引擎工作的標籤
page指令
聲明當前jsp的基本屬性,指揮解析引擎如何翻譯jsp頁面中的其他部分內容。
可以寫在jsp頁面的任意位置,但是通常爲了提高可閱讀性,通常會寫在jsp頁面的第一行。


[ language="java" ] 當前JSP使用的開發語言
[ extends="package.class" ] 當前jsp翻譯成servlet後要繼承的類,注意此值必須是一個servlet的子類,一般情況下不要改
!![ import="{package.class | package.*}, ..." ] 導入需要使用到的包 java.lang.*;javax.servlet.*;javax.servlet.jsp.*;javax.servlet.http.*;
!![ session="true | false" ] 用來指定當前頁面是否使用session,如果設置爲true,則翻譯過來的servlet中將會有對session對象的引用,於是可以直接在jsp中使用session隱式對象。但是這將導致一旦訪問jsp就會調用request.getSession()方法,可能導致不必要的空間浪費。如果確定jsp中不需要session可以設爲false
[ buffer="none | 8kb | sizekb" ] out隱式對象所使用的緩衝區的大小
[ autoFlush="true | false" ] out隱式對象是否自動刷新緩衝區,默認爲true,不需要更改
!![ errorPage="relative_url" ] 如果頁面出錯,將要跳轉到的頁面,除了在jsp中使用此屬性指定錯誤頁面外也可以在web.xml中配置整個web應用的錯誤頁面,如果兩個都設置則jsp中的此屬性起作用
!![ isErrorPage="true | false" ] 如果設置此屬性爲true,翻譯過來的servlet中將含有Exception隱式對象,其中封裝的就是上一個頁面中拋出的異常對象
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 和jsp亂碼相關的指令,用來指定jsp輸出時,設置的Content-Type響應頭用來指定瀏覽器打開的編碼
!![ pageEncoding="characterSet | ISO-8859-1" ] 服務器翻譯jsp時使用的編碼集.如果向防止jsp亂碼,應該保證文件的保存編碼和jsp翻譯成servlet用的編碼以及輸出到瀏覽器後瀏覽器打開的編碼一致.此屬性一旦設置好,翻譯引擎會間接幫我們設置content-type屬性.
[ isELIgnored="true | false" ] 當前頁面是否使用el表達式,設置爲false時表示啓用el,j2ee4.0開始默認支持,j2ee4.0一下做開發時,如果要使用el表達式,需將此屬性設置爲false
include指令
實現頁面包含的指令


靜態包含:多個組件被翻譯到一個Servlet中,時源文件級別的合併。
<%@inlucde file="" %>
動態包含:多個組件各自翻譯成各自的Serlvet,被訪問時各自執行,最終輸出時再輸出流上進行合併。
request.getReqeustDispatcher("").include();
只有page指令實現的包含是靜態包含,其他方式實現的包含都是動態包含。
靜態包含的效率略高於動態包含,所以推薦使用靜態包含。


taglib指令
引入標籤描述庫文件
3.jsp中的九大隱式對象:jsp翻譯引擎在將jsp翻譯成Servlet的過程中,自動創建出來的九個對象,由於翻譯過來的Servlet中自動就有,所以在jsp頁面的java代碼中可以直接使用。
page
request
response
config
application
session
out
exception
pageContext


4.PageContext -- 代表當前jsp頁面的運行環境
做爲入口對象,獲取其他八大隱士對象
getException方法返回exception隱式對象 
getPage方法返回page隱式對象
getRequest方法返回request隱式對象 
getResponse方法返回response隱式對象 
getServletConfig方法返回config隱式對象
getServletContext方法返回application隱式對象
getSession方法返回session隱式對象 
getOut方法返回out隱式對象


是一個域對象,還可以作爲入口對象操作四大作用域

作用範圍:當前jsp頁面
生命週期:訪問jsp頁面開始時創建,訪問jsp結束後銷燬
主要功能:在當前jsp頁面中共享數據


setAttribute(String,Object)
getAttribute(String)
removeAttribute(String)
getAttributeNames()




setAttribute(String name, Object value,int scope)
getAttribute(String name,int scope)
removeAttribute(String name,int scope)
findAttribute(String name)//可以在四大作用域中按照由小到大的順序搜尋指定名稱屬性的值,找到就返回,找不到就返回null


其中pageContext中代表域的常量:
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE 


可以實現便捷的轉發和包含
request.getRequestDispatcher("xxxx").forward(request,response);
request.getRequestDispatcher("xxxx").include(request,response);


pageContext.forward("xxxx");
pageContext.include("xxxx");


=========================================================================================================================
二、JSP標籤技術 -- 利用jsp中的標籤技術,將jsp頁面中的java代碼替換爲具體功能的標籤。sun在jsp2.0開始已經不再推薦在jsp中出現任何一行java代碼了。


1.jsp標籤:sun提供的jsp2.0中原生的標籤,不需要導入任何開發包就可以直接使用。
<jsp:inclue>用來替代request.getRequestDispatcher().include()
<jsp:forward>用來替代request.getRequestDispatcher().forward()
<jsp:param>配合前兩個標籤使用,可以在包含或轉發時,帶一些參數過去

2.el表達式:表達式語言,可以替換掉jsp中的腳本表達式


${el表達式}
el只能獲取不能遍歷
el只能獲取不能設置
使用中括號的地方都可以通過點號進行替換。除了中括號中是數字或包含特殊字符.-的情況除外。
~1.獲取數據
獲取常量數據
獲取變量數據
獲取數組中的數據
獲取集合中的數據
獲取Map中的數據
獲取javabean的屬性

~2.執行運算
算數運算
el在進行算數運算時,會將參與運算的非數組試圖轉換爲數字參與運算。如果轉換不成功,報錯。
關係運算

邏輯運算


三元運算符
3>2? "yes" : "no"
empty運算符
判斷對象是否爲空,判斷字符串是否是一個空串,判斷集合數組是否沒有任何內容,判斷作用域中是否沒有任何域屬性
~3.獲取常用開發對象
el中的預先定義了11個常用對象,這11個對象不需要預先存入域中就可以直接在el中使用


!!!!pageContext -- 有了它意味着就有了9大隱式對象


!!pageScope -- 代表四大作用域的對象,要注意的是不是代表對象,而是代表作用域
!!requestScope
!!sessionScope
!!applicationScope


!!param -- 所有請求參數組成的Map<String,String> 
paramValues -- 所有請求參數組成的Map<String,String[]>


header -- 所有請求頭組成的Map<String,String>
headerValues -- 所有請求頭組成的Map<String,String[]>


!!cookie -- 所有cookie信息組成的Map<String,Cookie>
initParam -- 所有當前應用初始化參數組成的Map<String,String>


~4.調用java方法 僅作了解
寫一個類包含被調用的方法,方法必須是靜態公有方法


寫一個tld文件(標籤描述庫文件),描述被調用的方法,注意tld文件必須放置在WEB-INF目錄下除了classes和lib以外的目錄中


在jsp頁面中引入tld,使用該方法




jstl標籤庫:提供給開發人員使用的標準的標籤庫,利用它配合el可以將jsp頁面中的絕大部分java代碼替代掉。
javaee4及之前的版本如果需要使用jstl要導入開發包。
而javaee5以後內置了jstl開發包,不需導入可以直接使用。


核心標籤庫 (core)  --- c
國際化標籤 fmt
數據庫標籤 sql 
XML標籤  xml
JSTL函數(EL函數) el
fn函數庫:提供了很多操作字符串的方法,可以按照el調用方法的方式直接使用

c:out
!!!c:set
!c:remove
c:catch
!!!!!c:if
!!!!c:choose c:when c:otherwise
!!!!!c:foreach
c:fortokens
c:import
c:redirect
c:param
c:url




4.自定義標籤技術:可以是開發人員開發特定功能的標籤
自定義標籤的繼承結構:
SimpleTag
|
|--SimpleTagSupport
在開發自定義標籤時可以自己實現SimpleTag接口,也可以繼承默認實現類SimpleTagSupport類

想要開發一個自定義標籤:
~1.寫一個類實現SimpleTag接口(繼承SimpleTagSupport類),在類中編寫自定義標籤要實現的功能
當jsp被訪問遇到自定義標籤時,每次都會創建出自定義標籤的處理類對象。
創建出來後,立即調用setJspContext()將當前頁面的PageContext對象傳入。
如果當前標籤具有父標籤,將會調用setParent方法將父標籤對象傳入,如果沒有父標籤則這個方法不會被調用。
如果當前標籤具有標籤體,則將標籤體封裝到JspFragment對象中,通過調用setJspBody()方法將標籤體傳入,如果當前自定義標籤沒有標籤體,則該方法不會被調用。
如果當前標籤具有屬性,則調用屬性的setXxx方法將屬性傳入。
最後調用doTag()方法,執行自定義標籤要處理的邏輯。


~2.寫一個tld文件(必須放置在WEB-INF目錄下除classes和lib以外的其他目錄中),描述自定義標籤類
<tag>
<name>TagDemo1</name> -- 標籤的名字
<tag-class>com.tarena.tag.TagDemo1</tag-class> -- 標籤的處理類
<body-content>scriptless</body-content> -- 標籤體的類型
empty 沒有標籤體
scriptless 當前標籤的標籤體可以是任意內容,處理java源代碼
JSP 當前標籤的標籤體可以是任意內容,包括java源代碼,但是從jsp2.0開始sun已經不再推薦在jsp頁面中包含java代碼了,所以在簡單標籤開發技術中,這個值已經無法使用了。
tagdependent 當前標籤的標籤體不對外產生任何輸出,該標籤體是爲後臺使用的。
<attribute> -- 聲明一個屬性
<name>attr</name> -- 屬性名
<required>true</required> -- 是否是一個必須存在的屬性
<rtexprvalue>true</rtexprvalue> -- 該屬性是否支持el表達式
<type>java.lang.String</type> -- 屬性的java類型
</attribute>
</tag>
~3.在jsp頁面中引入tld文件,再使用其中定義好的標籤


自定義標籤的基本功能實現:
控制標籤體是否執行 c:if
//--不執行:什麼都不做,默認標籤體就不執行
//--執行:通過調用JspFragment對象的invoke方法可以將標籤體進行輸出

控制標籤體之後的內容是否執行 c:redirect
//--執行:什麼都不做默認標籤之後的內容執行
//--不執行:拋出一個特殊的異常SkipPageException就可以阻止標籤之後的內容執行了

控制標籤體重複執行 c:foreach
//for(int i = 0;i<5;i++){
// getJspBody().invoke(null);
//}

修改標籤體後輸出 ...
//StringWriter writer = new StringWriter();
//getJspBody().invoke(writer);
//String str = writer.toString();
//str = str.toUpperCase();
//getJspContext().getOut().write(str);


開發帶有屬性的標籤
在類中定義一個javabean屬性,並對外提供setXxx方法
在tld文件中描述改屬性


打包標籤庫:





案例:開發一個輸出來訪者ip的標籤
案例:pTag:if
案例:pTag:for
案例:pTag:choose pTag:when pTag:otherwise


<c:choose>
<c:when test="">
</c:when>
<c:when test="">
</c:when>
<c:when test="">
</c:when>
<c:when test="">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>







=====四大作用域總結================================


pageContext域 --- pageScope -- page域
生命週期:訪問jsp開始創建,結束時銷燬
作用範圍:當前jsp頁面
主要功能:在當前jsp頁面中共享數據
request域 --- requestScope 
生命週期:請求開始時創建,請求結束後銷燬
作用範圍:整個請求鏈
主要功能:在整個請求鏈中共享數據
session域 -- sessionScope
生命週期:第一次調用request.getSession()時創建。超時、自殺、意外身亡
作用範圍:整個會話
主要功能:在整個會話範圍內共享數據
ServletContext域 -- applicationScope -- application域
生命週期:服務器啓動應用加載後立即創建,服務器關閉或web應用移除出容器時銷燬
作用範圍:整個web應用
主要功能:在整個應用範圍內共享數據




什麼時候用什麼域?
如果數據只在jsp頁面中使用,用page域
如果數據需要在轉發包含時傳遞,用request域
如果數據現在我需要用,過一會我還需要用,用session域
如果數據現在我需要用,過一會別人也需要用,存ServletContext域中


=============================================

==============================================================================================
EasyMall重構:
jsp中的java代碼用標籤技術替代
配置虛擬主機,實現www.easymall.com訪問
在[tomcat]/conf/server.xml配置虛擬主機<Host name="www.easymall.com" />
修改Hosts文件增加 127.0.0.1 www.easymall.com
在[tomcat]/conf/www.easymall.com/ROOT.xml 中編寫<Context docBase="工程的WebRoot目錄"/>直接讓tomcat中的www.easymall.com虛擬主機管理工程目錄下的WebRoot,好處是不用發佈,直接修改工程中的文件立即可以起作用。
**此種方式下沒有了發佈過程,myeclipse就不會自動幫我們加入jstl開發包了,需要自己導入。


用javabean保存信息


整理代碼結構,實現軟件分層


註冊用戶:
RegistServlet
解決請求響應亂碼
驗證驗證碼
獲取用戶提交的數據
校驗數據
將數據封裝到bean中,調用Service的方法註冊用戶
註冊成功後回到主頁
UserService
註冊用戶的方法:
檢查用戶名是否存在
註冊用戶到數據庫
UserDao
根據用戶名查找用戶
加入用戶數據到數據庫中
登錄用戶:
LoginServlet
處理亂碼
獲取用戶名密碼
記住用戶名的處理
調用Service根據用戶名密碼查找用戶
找不到就提示用戶名密碼不正確
找到就登錄用戶回到主頁
UserService
登錄用戶的方法
調用到根據用戶名密碼查找用戶
UserDao
根據用戶名密碼查找用戶的方法


AJAX校驗用戶名:
解決亂碼
獲取用戶名
檢查用戶名是否已經存在





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章