JSP知識點總結
JSP(Java Server Page)
JSP是服務器端運行的頁面,JSP本就是一個文檔,他不僅可以包含靜態的HTML代碼,也可以包含動態的JAVA代碼,服務器容器可以將JSP轉換成Servlet發布,並接受請求。
Jsp文件只需放在應用文件下就可以了。
JSP例子:
<html>
<head><title>time</title></head>
<body>
<h1><%=new java.util.Date()%></h1>
</body>
</html>
JSP運行過程
1,JSP文件先要翻譯成Java文件(Servlet),在tomcat中翻譯後的java文件在tomcat下的work\Catalina\localhost中相應名字的應用目錄裡。
2,編譯Java文件
3,運行.class文件
Tomcat的全局配置文件
在Tomcat下的conf目錄中的web.xml是服務器全局的配置文件,其中要想關閉列表顯示叫要把
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
Tomcat的管理員設置
在tomcat下的conf目錄中的tomcat-use.xml文件中可以配置tomcat的用戶角色
<tomcat-users>
<role rolename="manager" description=""/>
<role rolename="admin"/><!--設定角色的名字,admin是管理員,manager是項目管理-->
<user username="manager" password="123"roles="manager"/><!--設定用戶名密碼,和角色-->
<user username="admin" password="123"roles="admin"/>
</tomcat-users>
JSP的特點
1,JSP不需要編譯
2,JSP不需要進行配置
3,JSP本質上就是一個Servlet
4,JSP是以靜態頁面為主的。
JSP的語法格式
<%=...%>表達式,寫表達式時不要加上分號,表達式,翻譯成Java代碼也就是直接使用流輸出,也就不能加分號了。
<%! int a=0; %>聲明,使用聲明的變量,所創建的變量是在service方法體外,也就是翻譯成實例變量,聲明也可以聲明內部類或者是方法的聲明。
<% if(a==0){ a=3;}%>代碼片斷,代碼段會原樣翻譯。在代碼段中聲明的變量,就會被翻譯的service的方法體中,也就是被翻譯成局部變量。
前三種JSP的語法也叫做JSP代碼,以上的表示方法,都有與之相對應的xml表達形式,因為可讀性較差,所以較少使用。
<%@ ... %>JSP指令
<%@page import="...,..."%>引入包
<%include file="...."%>直接引入內容,這些內容會直接嵌入到頁面中。
JSP的注釋
<%--........--%>
JSP指令和JSP動作(標准的JSP標簽)
JSP指令的語法
<%@... ....%>
<%@include file="...."%> 包含指令,包含指令會將要包含的文件代碼原樣輸出到本頁面(在翻譯時把包含文件的內容引入並合並),不進行翻譯,file屬性制定要包含的文件的名字(注意要包含的文件的路徑),這個指令可以實現頁面的復用。
注意:<%@include file=" "%>要包含的JSP文件中不能定義重名的變量,如果不使用包含指令,那麼JSP中的最小轉換單元就是JSP文件,使用了包含指令就會將多個jsp的結果合並到一起。
<%@page ..%>頁面指令
<%@page import="..."%> 引入包 例:<%@pageimport="java.util.*,ent.*"%>(可出現多次)
<%@page pageEncoding="GBK"%>設定頁面顯示的字符集
<%@page contentType="text/html;charset=GBK"%>設置輸出流的編碼方式和文件格式。
注意:輸出的字符集編碼方式要和頁面顯示的字符集相同,一般定義輸出流的編碼方式,注意以上兩個頁面指令在JSP中最好只出現一次。注意在請求中傳送的參數的值是中文的話需要調用請求request的
setCharacterEncoding("..")方法設置相應的編碼方式,只適用於post請求,也可以通過Servlet的Filter來進行中文編碼方式的處理。
<%@page language="java"%>指定JSP的腳本語言,現在只能寫java
<%@page extends=".."> 指定翻譯後代碼類型的父類,最好不要使用這個指令
<%@page session="true|false"%>指定是否自動創建Session,最好不自己指定,使用默認值
<%@page buffer=".." autoflush="true|false"%>設置輸出的緩存和是否自動刷新緩存,一般情況下都使用默認值,緩存的默認值為8KB。
<%@page isThreadSafe="true|false"%>是否線程安全,默認為true,也就是線程安全,只使用默認值。
<%@page info=".."%>設置頁面信息,一般不用
<%@page errorPage=""%>指定異常處理頁面
<%@page isErrorPage="true|false"%>設定本頁面就是異常後跳轉的頁面
<%@page isELIgnored="true|false"%>設定本頁面是否忽略JSP2.0種EL表達式
<%@taglib ..%> 標簽庫指令,用於引入自定義標簽庫
JSP動作
<jsp:... ...>
<jsp:include page="..." flush=true|false> include動作是在翻譯和編譯後運行時進行響應的合並,也就是對應了Servlet中RequestDispatcher類的include(ServletRequest request, ServletResponse response)方法。
include動作可以傳遞參數
<jsp:include page="test.jsp">
<jsp:param name="user" value=" ">
</jsp:include>
在使用參數時,可以用request內置對象來獲取參數的值。
<jsp:forward page="xxx/xxx.jsp">forward動作對應的是Servlet中RequestDispatcher類的forward(ServletRequest request, ServletResponse response)方法,也就是把請求進行轉發。
也可以寫成
<jsp:forward>
<jsp:attribute name="page">xxx/xxx.jsp</jsp:attribute>
</jsp:forward>
這種寫法等價於上面的寫法。
在使用Servlet的response的重定向sendRedirect(String location)方法在使用時要包含應用的路徑,注意,重定向會放棄這個請求,並向服務器發送一個新的請求,但是響應對象還是一個。重定向是用來避免重復提交的。
注意:對頁面的刷新操作就會再一次運行程序,也就仿佛進行了再一次的提交一樣,這也就是重復提交的問題,所以需要使用重定向來解決這個問題。
<jsp:plugin type="bean|applet" code="...">
...
</jsp:plugin>
jsp:plugin動作可以使頁面上運行applet,或者是使用java代碼。
<jsp:useBean id="對象名" class="類全名"|type="類全名"(使用多態時使用)beanName="類全名"scope="page|request|session|application">
jsp:useBean動作,可以通過這個動作來使用java代碼,id就是變量名,clss和type的區別在於,使用type是不會創建對象,而只是會先查找如果有該對象就會使用,如果沒有就會拋出異常,class在沒有該對象存在時,則會創建新對象。scope是用來保存實例的空間范圍,page、request、session、application,由小到大,默認為page。
<jsp:setProperty name="對象名"property="屬性名" value="屬性值"/>
直接指定Bean屬性的值,必須類型一致。
<jsp:setProperty name="對象名"property="屬性名" param="from表單中的響應的參數名"/>
用表單中指定的參數來為Bean屬性賦值,系統會自動作類型轉換。
<jsp:setProperty name="對象名"property="屬性名"/>
用表單中和Bean屬性同名的標單項來給Bean屬性賦值,這樣寫只會為指定的屬性賦值
<jsp:setProperty name="對象名"property="*"/>
這種方式會自動用表單中的同名參數來為Bean的所有屬性賦值
<jsp:setProperty name="對象名" property="屬性名" value="<%= ...%>"/>
使用表達式來為Bean的屬性進行賦值
<jsp:getProperty name="對象名"property="屬性名">
取得指定的屬性,這個動作不常用,一般用表達式代替
我們可以通過設置屬性名的方法名也就是setXxxx()來控制屬性的賦值,用form表單的參數為Bean的屬性賦值時,系統會自動的調用與之同名屬性的setXxxx()方法,尤其是日期類型,可以通過使用這一方法來處理。
例:
import java.sql.*;
public class Person{
private Srting name;
private Date birthday;
public void setName(String name){
this.name=name;
}
public void setBirthdayAsString(String birthday){
this.setBirthday(valueOf(birthday));
}
public void setBirthday(Date birthdays){
this.birthday=birthday;
}
}
add.jsp
<jsp:useBean id="person" type="Person"scope="request">
<jsp:setProper name="person" property="*"/>
</jsp:useBean>
toadd.jsp
<form action="xxx" methmod="post">
<input type="text" name="name">
<input type="text" name="birhtdayAsString">
<input type="submit" value="add.jsp">
</form>
JavaBean和EJB的區別
JavaBean是可視的或者是不可視的,不用部署,EJB是不可視的,需要部署到服務器中。
JavaBean部署在應用程序中,EJB是部署在容器中,可以是有狀態或者是無狀態的,聲明式事務。
JavaBean的屬性和方法是普通的,EJB是需要遵守規范,是需要通過標准的描述符來定義的。
JavaBean是基於事件驅動的,EJB中只有消息驅動Bean是基於事件的
注意:jsp:useBean動作,用表單為Bean的屬性賦值時,也就是jsp:setProperty動作直接收請求中表單的信息為使用的Bean的屬性進行賦值,也就是說jsp:useBean和jsp:setProperty不能夠出現在為這個Bean的屬性賦值的form表單的頁面上。
JSP的異常處理
<%@page errorPage="xxx.jsp"%> 指定本頁面出現異常後要轉到的頁面
<%@page iserrorPage="true"%> 見本頁面指定為異常處理頁面,也就是其他出異常的頁面可以指定本頁面為要轉到的異常處理頁面。
處理異常
運行時異常
1) 一個程序運行時重獲的錯誤;
2) 能被一固有的異常對象引用所使用;
3) 可以利用異常引用創建或產生一個JSP頁面顯示異常信息給用戶。
創建一個異常跟蹤方案
1) 在每一個JSP頁面,包含要創建的異常頁面名稱;
<%@page import="numberguess.NumberGuessBean"errorPage="error.jsp"%>
2) 創建一個異常頁面;
<%@page isErrorPage="true"%>
JSP頁面中的異常處理
1) <%=exception.toString()%> 打印異常名稱;
2) <%exception.printStackTrace();%> 打印當前錯誤流中所有錯誤的列表;
3) <%=exception.getMessage()%> 打印錯誤的詳細描述信息
JSP中異常頁面的部署描述
<error-page>
<error-code>404</error-code>
<location>notFound.html</location>
</error-page>
<error-page>
<exception-type>java.lang.NumberFormatException</exception-page>
<location>error.jsp</location>
</error-page>
JSP隱含內置對象
JSP中隱含內置對象
名稱 類型 注釋和范圍
request javax.servlet.http.HttpServletRequest request
response javax.servlet.http.HttpServletResponse response
page javax.lang.Object page
Exception java.lang.Throwable page
pageContext javax.servlet.jsp.PageContext page
session javax.servlet.http.HttpSession session
application javax.servlet.ServletContext ServletContext
out javax.servlet.jsp.JspWriter OutputStream
config javax.servlet.ServletConfig ServletConfig
內置對象request(HttpServletRequest)
1)封裝了來自客戶端的請求:
2)方法:
Parameter related methods:
+getParameterNames():Enumberation 返回form中對象名稱的枚舉;
+getParameter(String name):String返回指定名稱的對象值;
+getParameterValues(String name) :String[ ] 返回指定名稱的對象值數組;
+getParameterMap():Map
Attribute related methods:
+setAttribute(String name,Object value) :void 設置屬性
+getAttribute(String name) :Oject 返回屬性值;
+removeAttribute(String name) :void
+getAttributeNames():Enumberation 返回屬性名稱
URL related methods:
+getContextPath():String
+getServletPath():String
+getPathInfo():String
State related methods:
+getCookies():Cooie[ ] 取得Cookie數組;
+getSession():HttpSession
+getSession(Boolean create) :HttpSession
內置對象response(HttpServletResponse)
+getWriter():PrintWriter
+addCookie(Cookie c) :void
+encodeURL(String URL) :String
+sendRedirect(String URL) :void
+sendError(int errorCode) :void
內置對象session(HttpSession)
+setAttribute(String name,Object value) :void 設置屬性
+getAttribute(String name) :Oject 返回屬性值;
+removeAttribute(String name) :void
+getAttributeNames():Enumberation 返回屬性名稱
Other motheds:
+seMaxInactiveInterval(int seconds) :void
Invalidate():void
內置對象pageContext(PageContext)
+setAttribute(String name,Object value) :void 設置屬性
+getAttribute(String name) :Oject 返回屬性值;
+removeAttribute(String name) :void
+getAttributeNames():Enumberation 返回屬性名稱
+findAttribute(String name) :Object
Other motheds:
+getRequest():HttpServletRequest
+getSession():HttpSession
+getServletContext():ServletContext
+getOut():JspWriter
內置對象application(ServletContext)
+setAttribute(String name,Object value) :void 設置屬性
+getAttribute(String name) :Oject 返回屬性值;
+removeAttribute(String name) :void
+getAttributeNames():Enumberation 返回屬性名稱
Other methods:
+getRequstDispather(String URL):RequestDispather
+getInitParameter(String name) :String
內置對象out
1)JSPWriter的一個實例, 用於發送響應給客戶端
2)方法:
print(String)/println(String) 用於向頁面輸出
print(int)/println(int)
flush() 刷新out對象的緩存
內置對象exception
1) 用於異常對象的異常實例;
2) 異常頁面在page指令中存在屬性isErrorPage="true";
3) 方法:
getMessage()/printStackTrace()/toString()
內置對象session
1) HttpSession的一個實例, 用於來維護session的狀態
2) 方法:
getAttribute(String name)/setAttribute(String name)
取得設置的屬性的對應資源/設置屬性的對應資源
removeAttribute(String name) 刪除屬性和隊應資源
getAttributeNames()
返回值是一個迭代器,可以獲得session中設置的屬性的名字也就是在set時使用的與資源對應的那個名字
內置對象application
1) ServletContext一個實例,用來維護application的狀態
2) 方法:
getAttribute()/setAttribute() 和session以及request中的那一對設置屬性及其對應資源的方法
getInitParameter() 獲得初始化參數
getServletInfo() 獲得Servlet的信息
3) application的作用域比session大得多,一個session和一個client聯系, 而application保持了用於所有客戶端的狀態。
注意:如果要保存的數據量比較大時,就要使用生命周期比較短的request對象,page對象只在本頁面中有效,也就是會再翻譯後的service方法體內的一個局部變量,service運行結束後就會銷毀,不像request可以轉發。session和application的生命周期都比較長而且作用域比較大。
JSP自定義標簽(tag)
什麼是自定義標簽?
1,用戶自定義的Java語言元素, 實質是運行一個或者兩個接口的JavaBean;
2,可以非常緊密地和JSP的表示邏輯聯系在一起,又具有和普通JavaBean相同的業務邏輯處理能力;
3,當一個JSP頁面轉變為servlet時,其間的用戶自定義標簽轉化為操作一個稱為標簽hander的對象;
4,可操作默認對象,處理表單數據,訪問數據庫以及其它企業服務;
自定義標簽庫的特點
1,通過調用頁面傳遞參數實現定制;
2,訪問所有對JSP頁面可能的對象;
3,修改調用頁面生成的響應;
4,自定義標簽間可相互通信;
5,在同一個JSP頁面中通過標簽嵌套,可實現復雜交互。
如何使用自定義標簽庫
1,聲明標簽庫
2,使標簽庫執行對Web應用程序可用
聲明標簽庫
1,使用taglib指令聲明標簽庫
2,語法:<%@taglib uri="URI"prefix="pre" %>
注意:a. uri屬性可以是絕對的,也可以是相對URL,該URL指向標記庫描述符(TLD)文件;
b. uri屬性也可以是一個並不存在的URL,該URL為web.xml文件中將標記庫描述符(TLD)文件的絕對
URL到本地系統的一個映射;
3,范例:<%@taglib uri="/WEB-INF/template.tld"prefix="test" %>
<%@taglib uri="http://java.sun.com/jstl/core"prefix="core" %>
使標簽庫執行可用
方式一:在WEB-INF/classes目錄下部署標記處理程序類;
方式二:將標記處理程序類打包成jar文件並置於WEB-INF/lib目錄。
幾種典型的標簽
1,不帶屬性和主體的簡單標簽:<mytaglibs:SomeTag/>;
2,不帶主體但有屬性的標簽:<mytaglibs:SomeTaguser="TonyDeng"/>;
3,帶有主體和屬性的標簽:
<mytaglibs:SomeTag user="TonyDeng">
...// 標簽體
</mytaglibs:SomeTag>;
注意:a. 屬性列於start tag中,它是在標記庫描述符(TLD)文件中指定,服務於標記庫的自定義行為;
b. 標簽體位於start tag和end tag間,可以是任何合法的JSP內容或者標簽;
定義標簽
1,開發實現tag的類(tag handler);
2,編輯標記庫描述符(TLD)文件;
3,在web.xml中為標記庫描述符(TLD)文件的絕對URL建立一個映射(該步驟可選);
標記庫描述符(TLD)文件
1,一個描述標記庫的XML文件;
2,內容開始是整個庫的描述,然後是tag的描述;
3,標記庫描述符(TLD)文件用於Web Container確認tag以及JSP頁面發展工具;
實現tag的類(標簽處理器)(tag handler)
1,是一些在引用了標簽的JSP頁面執行期間被WebContainer調用以求自定義標簽值的對象;
2,必須實現Tag, SimpleTag和BodyTag之一;
3,可以繼承TagSupport和BodyTagSupport之一。
標簽庫的接口和類的繼承關系接口的繼承關系:
☉interface javax.servlet.jsp.tagext.JspTag
☉interface javax.servlet.jsp.tagext.SimpleTag
☉interface javax.servlet.jsp.tagext.Tag
☉interface javax.servlet.jsp.tagext.IterationTag
☉interface javax.servlet.jsp.tagext.BodyTag
類的繼承關系:
☉class javax.servlet.jsp.tagext.TagSupport
(implements javax.servlet.jsp.tagext.IterationTag, java.io.Serializable)
☉class javax.servlet.jsp.tagext.BodyTagSupport
(implements javax.servlet.jsp.tagext.BodyTag)
☉class javax.servlet.jsp.tagext.SimpleTagSupport
(implements javax.servlet.jsp.tagext.SimpleTag)
(Interface)
JspTag
|
|ˉˉˉˉˉˉˉˉ|
(Interface) (Interface)JSP2.0
Tag SimpleTag ←--SimpleTagSupport
|
|
(Interface)
IterationTag←--TagSupport
支持迭代的標簽 |
| |
| |
(Interface) |
BodyTag ←---BodyTagSupport
可以處理標簽體
自定義標簽的開發步驟
1,寫標簽處理器,也就是一個符合自定義標簽規范的類xxx.java
2,寫標簽庫定義文件,也就是定義標簽的格式規范,也要符合自定義標簽的規范xxx.tld
3,建上述兩步中的相應文件進行部署。web.xml
tld文件中的配置
<tag>
<name>loop</name>
<tag-class>com.tag.LoopTag</tag-class>
<body-content>jsp</body-content>
<!--設定自定義標簽體內的內容,可以置為empty,也就是只能寫空標簽-->
<attribute>
<name>counter</name><!--配置自定義標簽的屬性名-->
<required>true</required><!--配置屬性是否必須出現-->
<rtexprvalue>true</rtexprvalue><!--允許使用表達式作為屬性的值-->
<type>int<type><!--配置屬性的類型-->
</attribute>
</tag>
簡單的標簽處理程序類
1,必須實現Tag接口的doStartTag()和doEndTag()方法;
2,因為不存在Body,doStartTag()方法必須返回SKIP_BODY;
3,如其余頁面要執行,doEndTag()方法返回EVAL_PAGE,否則返回SKIP_PAGE;
4,對於每一個標簽屬性,你必須在標簽處理程序類裡定義一個特性以及get和set方法以一致於JavaBeans 體系慣例
帶Body的自定義標簽
1,必須實現Tag接口的doStartTag()和doEndTag()方法;
2,可以實現IterationTag接口的doAfterBody()方法;
3,可以實現BodyTag接口的doInitBody和setBodyContent方法;
4,doStartTag方法可以返回SKIP_BODY、EVAL_BODY_INCLUDE、或者EVAL_BODY_BUFFERED(當你想使用 BodyContent);
5,doEndTag方法可以返回SKIP_PAGE或EVAL_PAGE;
6,doAfterBody方法可以返回EVAL_BODY_AGAIN,SKIP_BODY;
定義腳本變量的標簽(迭代標簽)
1,定義腳本標簽的二個步驟:
. 在標記庫描述符(TLD)文件中列明腳本變量;
. 定義標簽擴展信息類(TEI)並且在TLD文件中包括這個類元素(tei-class);
2,變量必須在標簽處理程序類中使用pageContext.setAttribute()方法設置;
3,標簽擴展信息類(TEI)必須繼承TagExtraInfo以及覆蓋getVariableInfo()方法;
4,變量的范圍可以是AT_BEGIN, NESTED, AT_END(標簽擴展信息類(TEI)的VariableInfo中定義)之一;
腳本變量的有效性
變量 | 有效性
---------------------------------------
NESTED | 標簽中的參數在starttag到endtag之間是有效的
AT_BEGIN | 標簽中的參數在標簽的開始到JSP頁面結束是有效的
AT_END | 標簽中的參數在標簽的結束到JSP頁面結束是有效的
Tag接口的方法
interface javax.servlet.jsp.tagext.Tag
------------------------------------------------------
+EVAL_BODY_INCLUDE:int
+EVAL_PAGE:int//繼續執行頁面
+SKIP_BODY:int//跳出標簽體
+SKIP_PAGE:int//跳出頁面,也就是整個JSP不會再運行
------------------------------------------------------
+release():void
+getParent():javax.servlet.jsp.tagext.Tag
+setParent(javax.servlet.jsp.tagext.Tag):void
+doEndTag():int
+doStartTag():int
+setPageContext(javax.servlet.jsp.PageContext):void
Tag的生命周期
1,setPageContext(javax.servlet.jsp.PageContext):void
2,setParent(javax.servlet.jsp.tagext.Tag):void
3,setAttribute:void
4,doStartTag():int
5,doEndTag():int
6,release():void
BodyTag和Tag接口的關系
interface javax.servlet.jsp.tagext.BodyTag-->interfacejavax.servlet.jsp.tagext.Tag
------------------------------------------
+EVAL_BODY_AGAIN:int//繼續執行標簽體
-----------------------------------------
+doInitBody():void
+setBodyContent(javax.servlet.jsp.tagext.BodyContext):void
+doAfterBody():int
BodyTag的處理過程
1,setPageContext(javax.servlet.jsp.PageContext):void
2,setParent(javax.servlet.jsp.tagext.Tag):void //設置此標簽的父標簽,也就是上一層標簽
3,setParent()
4,doStartTag():int
5,setBodyContent(javax.servlet.jsp.tagext.BodyContent):void//設置方法體
6,doInitBody():void//
7,doAfterBody():int
/* 這個方法會被不斷的調用直到不再滿足條件,通過這個方法來控制返回,從而控制循環是否中斷
SKIP_BODY是跳出標簽體的,EVAL_BODY_INCLUDE是繼續執行標簽體,通過返回這兩個值來控制循環是否*/
8,doEndTag():int
9,release():void
SimpleTag接口的方法
javax.servlet.jsp.tagext.SimpleTag
------------------------------------------
+doTag():void
+getParent():JspTag
+setJspBody(JspFragment jspBody):void
+setJspContext(JspContext pc):void
+setParent(JspTag parent):void
SimpleTage接口的生命周期(JSP2.0的自定義標簽接口)
1,new:
每次遇到標簽,容器構造一個SimpleTag的實例,這個構造方法沒有參數。和紅典的標簽一樣, SimpleTag不能緩沖,故不能重用,每次都需要構造新的實例。
2,setJspContext()、setParent(): 只有這個標簽在另一個標簽之,才調用setParent()方法;
3,設置屬性:調用每個屬性的setter方法;
4,setJspBody();
5,doTag(): 所有標簽的邏輯、迭代和Body計算,都在這個方法中;
6,return
例:
package com.tag;
public class HelloTag implements Tag
{
private PageContext pageContext;
private Tag parent;
public HelloTag(){
super();
}
/**
*設置標簽的頁面的上下文
*/
public void setPageContext(final PageContext pageContext) {
this.pageContext=pageContext;
}
/**
*設置上一級標簽 www.2cto.com
*/
public void setParent(final Tag parent) {
this.parent=parent;
}
/**
*開始標簽時的操作
*/
public int doStartTag() throws JspTagException{
return SKIP_BODY; //返回SKIP_BODY,表示不計算標簽體
}
/**
*結束標簽時的操作
*/
public int doEndTag() throws JspTagException{
try{
pageContext.getOut().write("Hello World!你好,世界!");
}
catch(java.io.IOException e){
throw new JspTagException("IO Error: " + e.getMessage());
}
return EVAL_PAGE;
}
/**
*release用於釋放標簽程序占用的資源,比如使用了數據庫,那麼應該關閉這個連接。
*/
public void release() {}
public Tag getParent(){
return parent;
}
}
xxx.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<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/j2eeweb-jsptaglibrary_2_0.xsd"
version="2.0">
<tag>
<description>Extends TagSupport</description>
<name>hello</name>
<tag-class>com.tag.HelloWorldTag</tag-class>
<body-content>jsp</body-content>
</tag>
</taglib>
web.xml
<web-app>
<taglib-uri>/xxx</taglib-uri>
<taglib-location>/WEB-INF/tlds/xxx.tld</taglib-location>
</web-app>
xxx.jsp
<%@ taglib uri="/xxx" prefix="mytag" %>
<%@ page contentType="text/html; charset=gb2312" %>
<html><head><title>first cumstomedtag</title></head><body>
<p>以下的內容從Taglib中顯示:</p>
<p><i><mytag:hello_int/></i>
<br>
<p><mytag:hello_int></mytag:hello_int>
</body></html>
JSP2.0中的表達式語言(EL表達式)
EL語法
EL的語法很簡單,他最大的特點就是使用上很方便
例:
${sessionScope.user.sex}
所有EL都是以${ 為起始、以} 為結尾的。
上述EL范例的意思是:從Session取得用戶的性別。如果使用之前JSP代碼的寫法如下:
<%
User user = (User)session.getAttribute("user");
String sex = user.getSex( );
%>
兩者相比較之下,可以發現EL的語法比傳統JSP代碼更為方便、簡潔。
EL提供. 和[ ] 兩種運算符來存取數據,[ ]可以訪問集合或者是數組的元素、Bean的屬性。下列兩者所代表的意思是一樣的,但是需要保證要取得對象的那個的屬性有相應的setXxx()和getXxx()方法才行。
例:
${sessionScope.user.sex}
等於
${sessionScope.user["sex"]}
. 和[ ] 也可以同時混合使用,如下:
${sessionScope.shoppingCart[0].price}
返回結果為shoppingCart中第一項物品的價格。
在EL中,字符串既可以使用"abc",可以使用'abc'。
EL運算符
EL的算術運算符和Java中的運算符的大致相同,優先級也相同。
注意:'+' 運算符不會連接字符串了,他只用於加法運算。
EL關系運算符有以下六個運算符
關系運算符 說 明 范 例 結果
= = 或eq | 等於 |${ 5 = = 5 } 或${ 5 eq 5 } | true
!= 或ne | 不等於 |${ 5 != 5 } 或${ 5 ne 5 } | false
< 或lt | 小於 |${ 3 < 5 }或${ 3 lt 5 } | true
> 或gt | 大於 |${ 3 > 5 }或${ 3 gt 5 } | false
<= 或le | 小於等於|${ 3 <= 5 }或${ 3 le 5 } | true
>= 或ge | 大於等於|${ 3 >= 5 }或${ 3 ge 5 } | false
empty運算符
Empty運算符主要用來判斷值是否為null或空的,例如:
${ empty param.name }
接下來說明Empty運算符的規則:
{empty} A
如果A為null時,返回true
如果A不存在時,返回true
如果A為空字符串時,返回true
如果A為空數組時,返回true
如果A為空的Map時,返回true
如果A為空的Collection時,返回true
否則,返回false
注意:
在使用EL關系運算符時,不能夠寫成:
${param.password1} = = ${param.password2}
或者
${ ${param.password1 } = = ${ param.password2 } }
而應寫成
${ param.password1 = = param.password2 }
使用EL從表單中取得數據
與輸入有關的隱含對象有兩個:param和paramValues,它們是EL中比較特別的隱含對象。一般而言,我們在取得用戶的請求參數時,可以利用下列方法:
request.getParameter(String name)
request.getParameterValues(String name)
在EL中則可以使用param和paramValues兩者來取得數據。
${param.name}
${paramValues.name}可以取得所有同名參數的值
${paramValues.hobbies[0]}可以通過指定下標來訪問特定的參數的值
這裡param的功能和request.getParameter(Stringname)相同,而paramValues和request.getParameterValues(Stringname)相同。如果用戶填了一個form,form名稱有為username的文本框,則我們就可以使用${param.username}來取得用戶填入文本框的值。
EL函數
EL中使用函數要寫一個要使用到方法的類,然後在配置xxx.tld文件,然後在JSP中使用時和JSP的自定義標簽相似。
xxx.tld中的配置
<function>
<name>reverse</name><!--函數名-->
<function-class>jsp2.examples.el.Functions</function-class><!--函數所在的類-->
<function-signature>java.lang.String reverse( java.lang.String )</function-signature>
<!--函數原型,也就是函數的返回值類型,函數名,參數表,注意一定要寫類型的全名-->
</function>
使用EL函數的寫法
${sn:upper('abc')}
注意:在定義EL函數時,都必須為公開靜態(publicstatic)
EL的隱含對象
EL也可以使用內置對象中設置的屬性,需要使用特定的EL內置對象
屬性范圍 | 在EL中的對象
Page | pageScope
Request | requestScope
Session | sessionScope
Application | applicationScope
EL中使用內置對象的屬性
${requestScope.user}
等價於
<%request.getAttribute("user")%>
如果不寫出特定的范圍 ,那就會在不同的范圍間進行搜索了
例:{user}(user是在request范圍request.setAttribute("user",user))
也就等於
${requestScope.user}
<%request.getAttribute("user")%>
EL的隱含對象
對象 類 型 說 明
PageContext | javax.servlet.ServletContext |表示此JSP的PageContext
-----------------------------------------------------------------------------------
PageScope | java.util.Map |取得Page范圍的屬性名稱所對應的值
-------------------------------------------------------------------------------------
RequestScope | java.util.Map |取得Request范圍的屬性名稱所對應的值
-------------------------------------------------------------------------------------
sessionScope | java.util.Map |取得Session范圍的屬性名稱所對應的值
-------------------------------------------------------------------------------------
applicationScope | java.util.Map |取得Application范圍的屬稱所對應的值
-------------------------------------------------------------------------------------
param | java.util.Map |如同ServletRequest.getParameter(String| |name)返回String類型的值
----------------------------------------------------------------------------------------
paramValues | java.util.Map |如同ServletRequest.getParameterValues| |(String name)。返回String []類型的值
-----------------------------------------------------------------------------------------
header | java.util.Map |如同ServletRequest.getHeader(Stringname) | |返回String類型的值
------------------------------------------------------------------------------------------
headerValues | java.util.Map |如同ServletRequest.getHeaders(Stringname) | |。返回String []類型的值
------------------------------------------------------------------------------------------
cookie | java.util.Map |如同HttpServletRequest.getCookies()
------------------------------------------------------------------------------------------
initParam | java.util.Map |如同ServletContext.getInitParameter(String| |name)。返回String類型的值
-------------------------------------------------------------------------------------------
cookie對象
所謂的cookie是一個小小的文本文件,它是以key、value的方式將Session Tracking的內容記錄在這個文本文件內,這個文本文件通常存在於浏覽器的暫存區內。JSTL並沒有提供設定cookie的動作,因為這個動作通常都是後端開發者必須去做的事情,而不是交給前端的開發者。如果我們在cookie中設定一個名稱為userCountry的值,那麼可以使用${cookie.userCountry}來取得它。
header和headerValues(請求報頭對象)
header儲存用戶浏覽器和服務端用來溝通的數據,當用戶要求服務端的網頁時,會送出一個記載要求信息的標頭文件,例如:用戶浏覽器的版本、用戶計算機所設定的區域等其他相關數據。如果要取得用戶浏覽器的版本,即${header["User-Agent"]}。另外在很少機會下,有可能同一標頭名稱擁有不同的值,此時必須改為使用headerValues來取得這些值。
注意:因為User-Agent中包含“-”這個特殊字符,所以必須使用“[]”,而不能寫成${header.User-Agent}。
initParam
就像其他屬性一樣,我們可以自行設定web應用的環境參數(Context),當我們想取得這些參數時,可以使用initParam隱含對象去取得它,例如:當我們在web.xml中設定如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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/web-app_2_4.xsd"
version="2.4">
<context-param>
<param-name>userid</param-name>
<param-value>mike</param-value>
</context-param>
</web-app>
那麼我們就可以直接使用${initParam.userid}來取得名稱為userid,其值為mike的參數。下面是之前的做法:String userid =(String)application.getInitParameter("userid");
pageContext對象
我們可以使用${pageContext}來取得其他有關用戶要求或頁面的詳細信息。下面列出了幾個比較常用的部分。
Expression 說 明
${pageContext.request} |取得請求對象
${pageContext.session} |取得session對象
${pageContext.request.queryString} |取得請求的參數字符串
${pageContext.request.requestURL} |取得請求的URL,但不包括請求之參數字符串
${pageContext.request.contextPath} |服務的web application的名稱
${pageContext.request.method} |取得HTTP的方法(GET、POST)
${pageContext.request.protocol} |取得使用的協議(HTTP/1.1、HTTP/1.0)
${pageContext.request.remoteUser} |取得用戶名稱
${pageContext.request.remoteAddr } |取得用戶的IP地址
${pageContext.session.new} |判斷session是否為新的,所謂新的session,表示剛由 server產生而client尚未使用
${pageContext.session.id} |取得session的ID
${pageContext.servletContext.serverInfo}|取得主機端的服務信息
JSTL(JSP標准標簽庫)
JSTL由核心標簽,<c:... > ,xml解析標簽<x:...>,國際化標簽<fmt:....>,數據庫訪問標簽<sql:...>,函數標簽<fn:...>
核心標簽
Core
<%@taglib prefix="c"uri="http://java.sun.com/jsp/jstl/core"%>
屬性設置
<c:set> 設置屬性
<c:remove> 移除設置的屬性
過程控制
<c:if test="..."> 條件標簽 只有在test屬性的值為true是才會執行標簽體
例:
<c:if test="${!(empty user.age)}">
<h1>hello</h1>
</c:if>
<c:choose>choose和when是組合在一起使用的,有點類似於swith case的語法 。
<c:when test="...">when也是條件判斷標簽,test屬性的值為true是才會執行標簽體。
例:
<c:choose>
<c:when test="${param.age<18}">
<h1>you is a child<h1>
</c:when>
<c:when test="${param.age>18 and param.age<50 }">
<h1>you is a young person</h1>
</c:when>
<c:when test="${param.age>50}">
<h1>you is a old person</h1>
</c:when>
</c:choose>
<c:forEach>迭代標簽
例:
<c:forEach var="book" item="${store.books}"varStatus="status">
<h1>${book.parice}</h1>
</c:forEach>
<c:forEach begin="1" end="5" step="1">
<h1>hello</h1>
</c:forEach>
<c:forTokens>字符串迭代標簽
<c:import>引入標簽
<c:import url="引入內容的url" var="別名">
${別名}
<c:url>url標簽
<c:url value="...">
<c:param name="..." value="..."/>
</c:url>
<c:url value="...">
使用url標簽可以實現URL回寫
<c:redirect uri="xxx/xxx/xxx.xx"/>
國際化標簽
<fmt:lauguage>
<fmt:bundel>資源指定標簽
<fmt:message>消息標簽
例:
<fmt:setLocale value="zh"/>
<fmt:bundel basename="message.MessageResources">
<fmt:message>name</fmt:message>
</fmt:bundel>
xxxx.properties
name=\0060\0700\