JSP的學習(1)——基本知識與底層原理

  經過以前的學習,咱們已經對Servlet有所瞭解,如今咱們先來學習JSP,當能使用JSP進行友好的頁面顯示以後,再回去學習Servlet的其餘高級特性會將整個學習很好的融入進來。java

  JSP,即Java Server Pages,和Servlet同樣,都是SUN公司定義的一種用於開發動態WEB資源的技術。web

  爲何說JSP也是動態web開發的一項技術呢?這是由於寫JSP雖然像是在寫HTML,可是JSP容許在頁面中嵌套Java代碼,或者利用某個標籤表示Java代碼(EL與jstl)。這就使得咱們在寫JSP時可以獲取請求對象Request和響應對象Response等這樣的web開發經常使用對象,實現與瀏覽器的交互。其實JSP就是一種Servlet,爲何這麼說,後面會談到。apache

  咱們先來寫一個JSP,具體的原理咱們先不用管,只先看效果:瀏覽器

  在MyEclipse中建立一個【JSPLearning】的web項目,在【WebRoot】下建立一個「1.jsp」服務器

  

  能夠看到頭部份內容是比較多的,這緣由其實和Servlet同樣,都是因爲MyEclipse建立JSP也是依靠模板來建立的(固然咱們能夠改模板代碼使咱們的JSP更加簡潔):session

  

咱們在<body>標籤中輸入以下代碼:app

1  <body>
2          <%
3              Date date = new Date();
4              out.write(date.toLocaleString());
5           %>
6   </body>

 

而後經過瀏覽器來瀏覽咱們這個JSP,就能夠看到當前時間:jsp

  

  寫JSP的一大便捷之處在於若是該JSP不在【WEB-INF】文件下,那麼每次修改代碼只需保存便可在瀏覽器上觀察,不須要像Servlet同樣要從新部署。學習

咱們看到上面JSP例子,不只包含了HTML標籤語言,同時融入了JAVA代碼。spa

 

  咱們知道瀏覽器在訪問JSP時能將JSP解釋並將內容顯示在瀏覽器上,JSP中有HTML的部分不用說,這瀏覽器確定知道,可是咱們上面的例子中JSP內還有Java部分,那麼瀏覽器又不是JVM,怎麼能執行這部分代碼呢?

  這就要說明一點了,其實瀏覽器訪問JSP只是一個假象,真正的仍是去訪問Servlet。只是Servlet將JSP文件進行了翻譯轉換,即將JSP又變成了Servlet,而後輸出給瀏覽器的就是這翻譯轉換後的Servlet。

  那翻譯轉換後的Servlet在哪裏呢?咱們並無看到在本身的web工程中有多出來的Servlet。其實這個Servlet就在Tomcat的【work】目錄下。【work】目錄是Tomcat的工做目錄,也是Tomcat將JSP轉換爲class文件的工做目錄。轉換的工做原理是當瀏覽器訪問某個JSP頁面時,Tomcat會在【work】目錄下把這個JSP頁面轉換成 .java文件(例如index.jsp會被轉換成index_jsp.java,若是以數字開頭,最前面還會有一下劃線,例如: _1_jsp.java),然後編譯爲 .class文件,最後Tomcat容器經過ClassLoader類將這個轉換後的 .class類裝載進內存,響應客戶端的工做。

  當第一次有人來訪問時,Tomcat須要將JSP轉換成Servlet,訪問可能會比較慢,可是一旦編譯成Servlet後,除非JSP再次修改,不然以後再有用戶訪問就能夠直接訪問該Servlet,因此以後訪問速度快。若是清空了【work】目錄中的內容,那麼全部的過程都會從新來過。

  Tomcat會定時掃描容器內的JSP文件,當發現某個JSP進行了修改以後,Tomcat會從新編譯轉換這個JSP成Servlet。可是Tomcat對JSP的掃描是定時的,即不是實時的,全部並非修改完後就當即生效(如上面所說的雖然修改JSP並不須要從新部署,可是有可能會發生訪問時還未修改)。因此有時候爲了能馬上生效,不少老前輩會建議在修改JSP後當即清除【work】目錄裏的內容。

  (另外,Tomcat容器中,對於轉換後的Java文件(例如index_jsp.java)的編譯最大隻支持64K,因此在其餘服務器容器中的JSP移植到Tomcat容器中時會發生大JSP文件沒法編譯的狀況。因此建議把JSP中的業務邏輯寫入單獨的類,在JSP中經過調用這個類的靜態方法來執行,並將JSP中的JS,CSS等放入單獨的JS文件或CSS文件依靠連接來加入樣式等。)

 

  上面說了這麼多,咱們來探究下Tomcat的【work】目錄,咱們會發如今這個目錄下還有【Catalina】文件夾,還有【localhost】文件夾(若是咱們有其餘虛擬主機,那麼也在【Catalina】下創建其餘虛擬主機的目錄來存放JSP轉換後的class文件):

  

這時候咱們也看到了剛纔剛建的web工程,接着咱們繼續點擊進去(你會發現目錄至關的多 T_T):

  

進到【JSP】目錄下,咱們就能夠看到剛纔從1.JSP轉換過來的 _1_jsp.java文件和 _1_jsp.class文件了(數字開頭,因此前面有一個下劃線)。

  咱們點擊 _1_jsp.java文件,看一看裏面的內容:

  

咱們的 _1_jsp做爲咱們1.JSP所定義的類,繼承了一個名爲HttpJspBase這個類,而HttpJspBase類是能夠從Tomcat的源碼中(由於包中有apache)根據這個類的包名找到:

  

在這個類中繼承了HttpServlet!因此這必須是一個Servlet :

  

  因此咱們訪問JSP,其實並非真正在訪問JSP,而是訪問將JSP轉換後的Servlet。在這個Servlet中,咱們使用請求對象,將所須要的數據經過流的形式寫回客戶端,這點跟以前Servlet的學習到的是同樣的。咱們能夠再看看那個瀏覽器訪問的JSP頁面,查看其碼源:

  

  咱們看到其碼源已經像是正常的HTML頁面,由於只有這樣瀏覽器才能解釋和顯示,同時在原來JSP寫Java代碼的地方直接變成了咱們Java運行後的結果,這是爲何呢?

  當知道JSP要轉成Servlet,而後又Servlet來處理瀏覽器的請求,那根據以前學習的Servlet能夠知道,這個請求是在Servlet中的service()方法中執行的,咱們來看一看 _1_jsp 中的service()方法:

  

  

  咱們能夠看到,在這個service方法中,確實有接收請求對象和響應對象爲參數,同時在方法的內部,經過IO流對象將一些HTML代碼經過write()方法寫出到瀏覽器,而且也將在JSP中寫的Java代碼原封不動的搬移到這個Servlet中,這就是爲何能夠在JSP中寫Java代碼,由於最後Java代碼都會交給Servlet,剩下的就跟以前Servlet的學習沒啥區別了,經過流寫給響應對象,再將響應對象交給瀏覽器顯示。

  這裏你可能會注意到咱們在JSP編寫是對Date對象是經過傳統Java建立對象的方式來實現實例對象,然後面咱們直接經過「out」這個對象來調用方法,那麼這個「out」指的是哪一個對象?還有別的什麼對象能夠直接調用嗎?

  咱們已經知道了JSP最終是要轉換爲Servlet的,而Servlet就是一個Java代碼的類,那麼在JSP中寫的Java代碼會原封不動的搬移到Servlet上,那麼某些某名出如今JSP上的對象確定就是在Servlet上已經被定義過的,咱們再次看看上面剛纔的截圖,能夠看到「out」這個對象是JSPWriter的實例(截圖中out還未得到引用,可是後面的代碼會使out對象得到引用,具體請看JSP轉換後的JAVA源碼),經過JSP的API手冊:

  

  JspWriter是繼承Writer的一個類。若是還記得經過響應對象Response.getWriter()方法得到的PrintWriter其實也是Writer下的一個類,因此JSP使用的字符流和Servlet能獲取到的字符流其實都一個意思。

  綜上,正是由於在轉換的Servlet中會自動幫咱們定義了JspWriter類的一個實例對象:out,因此咱們能在JSP中直接使用這個對象,固然經過上訴截圖咱們還能夠直接使用別的已經定義好的對象,比在JSP中使用「application」表明這個web的Context對象,用「page」表明了JSP對於的這個Servlet,用「session」表明這個web應用中的Session對象 等等,因此這些都是能夠直接在JSP中使用,並表明某個類的對象的:

  

  簡單說來,只要是在JSP轉換後的Servlet中的_jspService()方法中定義過的變量,在JSP頁面編寫代碼時均可以直接使用。

 

  在本篇博客的最後,咱們來最後說明一點,不論是JSP仍是Servlet,雖然均可以用於開發動態web工程,但因爲這兩個技術的各自特色:

  · 使用JSP即用Java代碼產生動態數據,又作瀏覽器界面顯示會致使頁面難以維護。

  · 使用Servlet即處理數據,又在裏面嵌套HTML代碼用於界面顯示,一樣致使程序可讀性差,難以維護,就如同上面的轉換後的Servlet中各類out輸出HTML代碼。

  · 所以最好的方法就是根據這兩門技術的特色,讓它們各自負責各的,Servlet只負責響應請求並處理數據,並把數據經過轉發(forward()方法)帶給JSP,由JSP來顯示,其實就是丟給轉換後自動產生的Servlet來顯示,讓它來幫咱們經過各類out來輸出HTML代碼。

  這篇文章主要介紹了JSP的一些知識和底層的一些技術,下一篇會具體講訴JSP中所須要學習的語法。

相關文章
相關標籤/搜索