到目前為止,我們已經介紹了很多Servlet相關的內容,相信對於如何使用Servlet有一個比較好的基礎了。
說真的,現在純粹用Servlet來寫網站的應該不多,大部份都是使用一些Framework來寫,那麼,爲什麽還要介紹這麼多關於Servlet呢?原因是,大部份的Framework都是站在Servlet上面。換句話說,Framework只是在Servlet上面多蓋上一層,讓我們更好操作,不過實際底層在跑還是Servlet。
講了這麼多,只是爲了介紹今天的主題,也就是Servlet的轉址功能。
(和我部落格同時發佈:http://www.dotblogs.com.tw/alantsai/archive/2013/10/03/122268.aspx)
轉址的重要性
寫到現在,相信大家有一個共識,那就是用Servlet寫html是在太費工了。Servlet適合的應該是處理邏輯而不是用來做顯示的部份。那這就牽扯到了幾個問題:
1.如何傳遞資料 - 從邏輯層傳到顯示層
2.如何從邏輯層轉到顯示層
寫過Asp .net webform的就很熟悉在寫html的時候透過<% %>的方式來寫C#。Java 也有一樣的概念,稱之為Java Server Page(JSP),而JSP就比較適合做顯示層。
之後會在介紹JSP,今天專注的是如何在頁面之間傳遞資料,和如何轉址到正確的頁面。
如何轉址
在Servlet裡面提供了兩個方法:
1.一個是透過RequestDispatcher().forward()來達到
2.一個是透過SendRedirect()的方法
上面兩個差異在於,forward()是Servlet內部自己轉址,所以對於使用者或者Browser來說,還是同一個網址,只不過內容是另外一個Servlet或者Resource的內容。
SendRedirect()則是發送一個http status 301 或者 302給browser告知內容的位置,由browser在去對那個網址發出request。因此,browser的連接會變換,同時 browser總共會有兩個request(一個取得301或302,然後在發出一個request到返回的地址)。
使用forward()的方法還有一個好處,那就是有些外部沒法直接取得的內容(例如在WEB-INF下面的資源是沒有辦法透過http request取得),不過用forward就可以取得資料。
下面我會簡單介紹兩個方法。
使用forward()的方式
還記得之前我們在輸入名字的例子裡面,當傳入的字串符合某一個特定的字串,他就可以看到一個在WEB-INF下面的secret.html的內容。
這邊我會對程式碼做一點介紹。
我們可以從request取得RequestDispatcher(),而裡面輸入的參數就是要轉址的位置。如果是以"/"作為開頭,表示取得網站的root path,然後在加上path。以我們的例子就是,我網站的root是http://localhost:8080/ServletSample,然後加上我們在裏面設定的路徑,表示取得的資料如果以http request表示的話是: http://localhost:8080/ServletSample/WEB-INF/Secret.html。
不過因為他在WEB-INF下面,因此預設Tomcat是不會允許用http取得裡面的資料:
不過只要我們透過forward()就可以取得資源,例如我這邊設定是如果輸入的是"alan"就轉址,因此:
這邊注意到網址沒有變。
符合我們html的內容:
使用forward()需要注意的地方
forward()會需要兩個參數,一個是HttpServletRequest,一個是HttpServletResponse。
程式碼這邊還要注意到,我呼叫forward()之後,就放了一個return;。這個原因是,當呼叫了forward()以後,程式還是會繼續執行下去。不過,因為你已經說要把內容輸出交給另外一個資源(RequestDispatcher()所定義的資源位置),如果你還在你這邊輸出內容,就會出錯。因此,我需要呼叫forward()以後,跳出這個 method,避免輸出到內容造成出錯。
SendRequest()
現在我們來看另外的轉址方式,也就是透過回送http status 301或 302的方式。
首先,我們會需要有一個能夠從http取得資料的資源,因此把secrete.html放到網站的root:
現在我們把程式碼修改一下,變成使用SendRedirect()
這一次輸入一樣alan到textbox裡面,這個時候內容還是出現了,不過網址也變了:
頁面之間傳遞資料
介紹完了頁面轉址的功能,這邊會需要介紹一下如何在兩個頁面之間傳遞資料。
總共有兩種方式:
1.使用request.setAttribute("{key}","{value}") - 傳入的參數是key value pair。
2.另外一個是使用request.getSession取得HttpSession然後在呼叫setAttribute() - 傳入的參數和上面介紹的一樣。
使用request.setAttribute()有點像我們在MVC裡面使用ViewData在Controller和View之間傳資料。設定以後,他只會在forward()的頁面裏面存在,過了forward()的頁面就不存在了。
需要注意的是,因為sendRedirect()實際上是兩個不同的request,因此request.setAttribute()裡面的資料會被清掉,因此不適用。
因為如此,所以我們有Session的方式來記錄不同頁面的request能夠取得同樣的內容。
Session我就暫時介紹到這邊,相信對於Session應該有幾本的瞭解。Java web的Session和 asp .net的一樣。
結語
這篇結束以後,Servlet也算是介紹到了一個段落。
Servlet非常重要,因為它是很多framework的building block,所以瞭解他的原理,對於瞭解其他framework就會比較容易。
那這篇介紹的是servlet裡面最後一塊拼圖,讓我們瞭解Servlet是如何和別的framework結合,好讓我們開發大型程式更簡單。