本篇接上一篇《JSP的學習(2)——語法知識一》,繼續來學習JSP的語法。本文主要從JSP指令中的page指令,對其各個屬性進行詳細的學習:
JSP指令:
JSP指令是為JSP引擎而設計的,JSP指令不產生任何可見輸出,只是告訴在轉換成Servlet的過程中如何處理JSP頁面中的其余部分。在JSP 2.0 規范中共定義了三個指令:
1) page指令
2) include指令
3) taglib指令
taglib指令是導入標簽庫的指令,以后會介紹到。
JSP指令格式:
<%@ 指令(如page、include或taglib) 屬性1="屬性值" 屬性2="屬性值" … %>
例如:
<%@ page contentType = "text/html;charset=utf-8" %>
如果一個指令有多個屬性,這多個屬性可以寫在一個指令中,也可以分開寫。
例如:
1 <%@ page contentType = "text/html;charset=utf-8" %> 2 <%@ page import = "java.util.Date" %>
或者寫成:
<%@ page contentType="text/html;charset=utf-8" import="java.util.Date" %>
page指令
page指令用於定義JSP頁面的各種屬性,無論page指令出現在JSP頁面中的什么地方,它作用的都是整個JSP頁面,為了保持程序的可讀性和良好習慣,page指令最好都放置在整個page頁面的起始位置。
page指令包含以下屬性(屬性值為示例):
(1). language = “java ” 指示JSP頁面如果嵌入的代碼為Java代碼。
(2). extends = “package.class” 指定當該JSP轉換后的Servlet繼承哪個類(通常不用動)。
(3). import = ”包名.類名”或者”包名.*” 等等格式,
其中JSP引擎會自動導入如下包:
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
正是因為這樣,所以我們在JSP中使用像System,response,request這樣的類或對象都不需要再另外導包。
使用多條page指令的“import”屬性進行導入多個類或包,也可以在一條page指令的“import”屬性中導入多個類或包,其中每個包或者類之間用逗號隔開,例如:
<%@ page import=" java.util.Date , java.util.* " %>
(4). session = “true”(默認值)或”false”
若在page指令中將“session”屬性置為“true”,那么在JSP轉換后的Servlet中將自動創建Session對象。
如果我們在page指令中指定“session”屬性置為“true”,那么在Tomcat的【work】目錄下JSP對應的 .java文件中就自動出現如下代碼:
session = pageContext.getSession() ;
這時我們就可以在JSP腳步片斷中直接使用session,如果在page指令中指定“session”屬性置為“false”,那么就不能在JSP腳步片斷中直接使用session,想使用就手動獲取 (request.getSession())。
(5). buffer = “none” 或 ”8 kb”(默認值) 或 ”自定義值kb”
指定JSP頁面是否需要緩沖。即我們直到JSP轉換后的Servlet中包含大量的通過out對象進行輸出,但輸出的數據並非直接寫給瀏覽器,而是直到緩沖滿時才將數據發送回瀏覽器上。
(6). autoFlush = “true”(默認值) 或”false”
指定JSP頁面是否自動刷新。
(7). isThreadSafe = “true”(默認值) 或”false”
JSP中的“isThreadSafe”屬性如果設置為“false”,那么表示轉換后的Servlet將會繼承SingleThreadMode接口,以Singleton(單線程)模式運行,這種模式同一個時刻只允許一個實例,若多個用戶同時訪問該JSP,那么只有先訪問者完全訪問完該頁面后,后訪問者才能開始進行訪問。
例:未設置“isThreadSafe”屬性時:
設置“isThreadSafe”屬性為“false”后:
而如果“isThreadSafe”屬性設置為“true”,默認值也是“true”,那么表示轉換后的Servlet以多線程方式運行,是線程安全的。
(8). info = “自定義信息…”
用於在JSP頁面中定義一些說明,可以在Servlet中通過getServletInfo()方法獲取通過page指令獲取”info”的值。
(9). errorPage = “/ 相對URL ”
當JSP頁面錯誤,或者其中的Java程序出錯,拋出異常沒有處理,那么在瀏覽器上訪問的JSP頁面可以跳轉到“errorPage”屬性指定的某個頁面,友好顯示。
注意,”errorPage”屬性的值是相對於web應用下的地址(給服務器端的地址,因為拋出異常的話是由服務器來處理跳轉到哪個頁面)。
例如:在web工程【JSPLearning】下,創建一個【exceptions】目錄,並在該目錄下新建一個“error.jsp”,同時記住將該JSP中的JSP指令中的“pageEncoding”改為支持中文格式的編碼,內容如下:
1 <body> 2 對不起,你的頁面內容有錯。。。 3 </body>
在該web工程的【WebRoot】即根目錄下創建一個“1.jsp”文件,寫入一段JSP腳本片斷:
1 <% 2 int x = 1; 3 out.write(1/0); //會拋出異常 4 %>
同時在該JSP的上部添加進JSP指令,這里直接寫了屬性:
errorPage = "/exceptions/error.jsp"
那么現在我們來訪問這個web應用的“1.jsp”頁面,可以看到:
會拋出我們沒有處理的異常的JSP自動跳轉到了我們在“errorPage”屬性設置的頁面,這樣用戶就不會看到那些“經典”的505頁面和里面各種異常的說明了。
題外話:
當我們是個大項目時,里面會有很多個網頁,當這些網頁多起來后,如果對每個JSP網頁都設置“errorPage”肯定是不切實際的。這時我們就可以在web.xml文件中設置錯誤處理頁面。如果要將Tomcat中所有的web應用設置,就在Tomcat的【conf】文件下的web.xml文件中設置;如果只對某個web應用設置錯誤處理頁面,就在該web應用中【WEB-INF】目錄下的web.xml文件中設置。
在web.xml文件中使用<error-page>標簽為整個web應用程序設置錯誤處理頁面,其中<exception-type>子元素指定具體異常完整包名和異常名稱,<location>標簽指定以“/”開頭的錯誤處理頁面的路徑(也是以web應用為根目錄的路徑,即服務器端的路徑)。
我們對上面的例子進行重新改寫,將包含“errorPage”屬性的page指令從1.jsp中刪除,由於我們知道在1.jsp文件中我們的JSP腳本片斷會拋出ArithmeticException異常,因此記下這個異常及異常的包名路徑,之后需要添加到<exception-type>標簽中。
接着我們我們到web工程【JSPLearning】中的【WEB-INF】目錄下的web.xml文件,添加下面幾句代碼:
1 <error-page> 2 <exception-type>java.lang.ArithmeticException</exception-type> 3 <location>/exceptions/error.jsp</location> 4 </error-page>
完成上面的工作之后,當訪問該web應用下的某個資源(不管是JSP還是Servlet等等),只要會拋出ArithmeticException這個異常,服務器會立馬將資源跳轉到指定這個異常的錯誤處理頁面,在我們的例子中是/exceptions/error.jsp,再次訪問1.jsp還是看到同樣的效果:
這樣就完成了在一個web應用中進行全部資源的錯誤處理頁面的配置,當然這點有一個不足的地方就是使用這種方法必須指明會發生何種錯誤異常(<exception-type>必須指明)。但如果使用<error-code>就可以免去這種煩擾,后面會說到。
另外一個,采用這種方法時,如果瀏覽器,比如說IE,在其【工具】--->【Internet選項】中,選擇【高級】,找到一個【顯示友好HTTP錯誤信息】,如下圖所示:
通常這個選項瀏覽器默認是勾選上的,這會有一個什么問題呢,就是采用在web.xml文件中配置<error-page>這元素時,如果我們的錯誤處理頁面中的內容太少,不足1024字節,那么在瀏覽器是無法正常跳轉到錯誤處理頁面的,比如說我們剛才的/exceptions/error.jsp中將<body>標簽內容就設置為:ERROR!,內容夠少了吧,那么我們重新打開瀏覽器來訪問1.jsp:
可以看到無法看到錯誤處理頁面。
兩種解決方式:1,將【Internet選項】中的【顯示友好HTTP錯誤信息】鈎去除;2,在/exceptions/error.jsp錯誤處理頁面中將內容添加超過1024字節(多添加點很容易就超過了)。以上兩種方法都可以重新看到錯誤處理頁面。
上面說到在<error-page>中可以設置<exception-type>這個子元素,但是我們必須給定明確的異常,畢竟麻煩。但是在<error-page>中還可以設置<error-code>這個子元素,這個元素用來表明當瀏覽器訪問遇到錯誤響應碼時應該訪問哪些頁面,有哪些錯誤的響應碼呢? 404!500!眼熟嗎,T_T!
我們繼續以上面的web工程【JSPLearning】為例,在之前的【exceptions】目錄下新建一個error404.jsp,添加自定義內容。
接着我們繼續在該web工程的web.xml中添加如下代碼:
1 <error-page> 2 <error-code>404</error-code> 3 <location>/exceptions/error404.jsp</location> 4 </error-page>
當我們訪問一個在web應用中不存在的資源時,服務器就會幫我們跳轉到這個出現404錯誤而設置的錯誤處理頁面,友好顯示:
可以看到,這樣就比指定特別異常要方便的多,當然指定某個特定異常自然有其作用的地方,這些都要靠實際情況來考慮。
題外話講多了,不過這都是對開發有幫助的技巧。這里最后說明一點,如果在某個頁面中設置了“errorPage”屬性的page指令,那么在web.xml文件中設置的<error-page>兩種形式都對其沒有作用,也就是說JSP頁面只先認page指令的“errorPage”屬性。
(10). isErrorPage = “true” 或”false”(默認值)
結合上一點,當我們將某個JSP頁面設置為錯誤處理頁面,那么我們最好將該頁面設置page指令的“isErrorPage”屬性,並置其為“true”。
這么做有什么好處呢?當這個錯誤處理JSP頁面之后被轉換成Servlet后,在這個Servlet中會自動生成一個異常對象exception,該對象封裝了之前錯誤訪問的一些信息。記住,如果在錯誤處理頁面中沒有設置page指令的“isErrorPage”屬性或者說為”false”的話,那么轉換之后的Servlet是不會有這個exception對象的。
那么我們還是以上面的web工程【JSPLearning】為例,當我們為/exceptions/error.jsp這個JSP設置了page指令的“isErrorPage”屬性:
<%@ page isErrorPage="true" %>
讓瀏覽器訪問一次有錯誤代碼的1.jsp使得瀏覽器跳轉到錯誤處理頁面后,我們到Tomcat的【work】目錄下查看 error_jsp.java文件,我們會發現在error_jsp這個類中的_jspService()方法中多出了對exception對象的定義,這是沒有設置“isErrorPage”為”true”的JSP轉換Servlet所沒有的:
這個exception對象同out對象,page對象等,都是可以在JSP中直接使用的,切記這個對象一定是在那些聲明了“isErrorPage”為”true”的JSP中直接使用。
(11). contentType = “ MIME類型/對應類型 [(;chrset=某個編碼表)可選] ”
在page指令中的“contentType”屬性告訴JSP引擎(或Tomcat)該JSP頁面的類型,例如:
<%@ page contentType="text/html; charset=ISO-8859-1" %>
在JSP轉換到Servlet時,會根據page指令中的“contentType”屬性生成相應的調用ServletResponse.setContentType(…)方法語句。
“contentType”屬性是用來通知瀏覽器以什么碼表來解碼打開JSP(其實是Servlet)中的內容。
這個屬性可以用來解決JSP中可能出現的亂碼問題,這個問題我們以后會討論到。
(12). pageEncoding = “某個編碼表”
該page指令的屬性“pageEncoding”指定服務器以什么碼表將JSP文件翻譯成.java文件中的內容。當設置了這個“pageEncoding”屬性之后,其實也默認將“contentType”屬性中的編碼表設置的和它一樣,所以總結來說我們只需設置“pageEncoding”屬性即可。
(13). isELIgnored = “true” 或 “false”(默認值)
告訴JSP引擎(或Tomcat)該JSP頁面是否忽略EL表達式。默認值為“false”即JSP均支持EL表達式。