天天看點

[Servlet&JSP] 從JSP到Servlet訓示元素聲明、Scriptlet與表達式元素隐含對象錯誤處理

jsp與servlet是一體的兩面,jsp最後都會被容器轉譯為servlet源代碼,自動編譯為.class檔案,載入.class檔案然後生成servlet對象。

由容器轉譯後的servlet類具有_jspinit()、_jspdestroy()、_jspservice()等方法,名稱中有下劃線字首,表示這些方法都是容器轉譯時維護的,我們不應該從寫這些方法。如果想要做些jsp初始化或收尾的工作,則應定義jspinit()或jspdestryoy()方法。

jsp訓示(directive)元素的主要目的在于,訓示容器将jsp轉譯為servlet源代碼時,必須遵守的一些資訊。訓示元素的文法如下:

在jsp中有三種常用的訓示類型:page、include和taglib。

page訓示類型告知容器如何轉譯目前的jsp網頁。

include訓示類型告知容器将别的jsp頁面包括進來進行轉譯。

taglib訓示類型告知容器如何轉譯這個頁面中的标簽庫(tag library)。

訓示元素中可以有多對屬性/值,必要時,同一個訓示類型可以用數個訓示元素來設定。

page訓示類型中的import告知容器,轉譯jsp時必須在源代碼中包括的import語句。也可以在一個import語句中,使用逗号分隔開數個import的内容;page訓示類型中的contenttype屬性告知容器,在轉譯jsp時,必須使用httpservletrequest的setcontenttype(),調用方法時傳入的參數就是contenttype的屬性值;pageencoding屬性則是告知容器轉譯和編譯時如何處理這個jsp網頁中的文字編碼,以及内容類型附加的charset設定。如果網頁中包含非ascii編碼範圍内的字元(如中文),就要指定正确的編碼格式,才不會出現亂碼。

可以在使用page訓示類型時一行一行的編寫,也可以編寫在同一個元素中。

page訓示類型還有一些可以設定的屬性,概略說明如下:

info屬性

用于設定目前jsp頁面的基本資訊,這個資訊最後會轉換為servlet成u型中使用getservletinfo()所取得的資訊。

autoflush屬性

用于設定輸出流時候要自動清除,預設為true。如果設定為false,當緩沖區滿了又沒調用flush()把資料送出到用戶端時,就會産生異常。

buffer屬性

用于設定到用戶端的輸出串流緩沖區的大小,設定時必須指定機關,流入buffer=”16kb”,預設是8kb。

errorpage屬性

用來設定當jsp運作錯誤而産生異常時,該轉發哪一個頁面處理這個異常。

extends屬性

用來指定jsp網頁轉譯為servlet程式之後,應該繼承哪一個類。以tomcat為例,預設是繼承至httpjspbase(它繼承至httpservlet)。這個屬性很少會使用到。

iserrorpage屬性

設定jsp頁面是否為處理異常的頁面,這個屬性要與errorpage配合使用。

language屬性

指定容器使用哪種語言的文法來轉譯jsp網頁,不過事實上目前隻能使用java的文法且是預設的。

session屬性

設定在轉譯後的servlet源代碼中是否具有建立httpsession對象的語句。預設是true,若有些頁面不需作會話管理,設為false可以增加一些性能。

iselignored

設定jsp網頁中是否忽略表達式語言,預設是false。這個設定會覆寫web.xml中的<code>&lt;el-ignored&gt;</code>設定。

isthreadsafe屬性

告訴容器在編寫jsp時是否注意到線程安全,預設值為true。如果設定為false,則轉譯之後的servlet會實作singlethreadmodel接口,每次請求時将建立一個servlet執行個體來服務請求,雖然可以避免線程安全問題,但這會影響到性能,極度不建議設定為false。

incude訓示類型用來告知容器将包括另一個網頁的内容進行轉譯。

使用指令元素include來包括其他網頁内容時,由于是在轉譯時期就決定了轉譯後的servlet内容,是一種靜态的包含方式。<code>&lt;jsp:include&gt;</code>标簽則是在運作時将别的網頁動态包括進來進行響應的方式。

jsp網頁會轉譯為servlet類,轉譯後的servlet類應該包括哪些類成員、方法聲明或是哪些語句,在編寫jsp時,可以使用聲明(declaration)元素、scriptlet元素以及表達式(expression)元素來指定。

聲明元素的文法如下:

在<code>&lt;%!</code>與<code>%&gt;</code>之間聲明的程式代碼,都将轉譯為servlet中的類成員或方法。

在使用<code>&lt;%!</code>與<code>%&gt;</code>聲明變量時,必須小心資料共享與線程安全的問題。容器預設會使用同一個servlet執行個體來服務不同使用者的請求,每個請求就是一個線程,而<code>&lt;%!</code>與<code>%&gt;</code>之間聲明的變量對應至類變量成員,是以會有線程共享通路的問題。

如果有一些初始化操作想要在jsp加載時執行,則可以重寫jspinit()方法,也可以用jspdestroy()定義結尾動作。定義這兩個方法就是在<code>&lt;%!</code>與<code>%&gt;</code>之間進行的,這樣轉譯後的servlet源代碼就會有相對應的片段出現。

scriptlet元素文法如下:

在scriptlet元素中可以編寫java語句,就如同在java的方法中編寫語句一樣,事實上,其中所包括的内容将被轉譯為servlet源代碼的_jspservice()方法中的内容。

直接在jsp中編寫的html,都會變成out對象所輸出的内容。scriptlet出現的順序,也就是在轉譯為servlet後,語句出現在_jspservice()中的順序。

表達式元素文法如下:

表達式運算的結果将直接輸出為網頁的一部分。在表達式元素中不用加上分好(;)。

隐含對象

說明(轉譯後對象的對象)

out

jspwriter–&gt;printwriter

request

httpservletrequest

resposne

httpservletresponse

config

servletconfig

application

servletcontext

session

httpsession

pagecontext

pagecontext,它提供了jsp頁面資源的封裝

exception

throwable,它代表jsp頁面抛出的異常對象

page

this

可以通過pagecontext設定四種範圍屬性,而不用使用個别的pagecontext、request、session、application來進行設定。以pagecontext提供單一的api來關系屬性的作用範圍,可以使用以下的方法來進行設定。

scope可以使用以下常數來指定:

pagecontext.page_scope

pagecontext.request_scope

pagecontext.session_scope

pagecontext.application_scope

事實上,很少會使用到pagecontext,pagecontext主要是在轉譯jsp為servlet時,提供給容器一個單一通路的界面。

jsp終究會轉譯為servlet,是以錯誤可能發生在以下三個時候:

jsp轉換為servlet源代碼時

文法錯誤等

servlet源代碼進行編譯時

忘記部署相關的類等

servlet加載容器進行服務單發生運作時錯誤

如nullpointerexception等