From Gossip@caterpillar

JSP/Servlet: 第一個JSP程式

 

 


首先請確定您已經瞭解了什麼是 Servlet容器,並已設定好Web應用程式相關目錄與web.xml,然後啟動您的伺服器。

假設您的Web應用程式是在myjsp目錄下,直接在該目錄下開始撰寫您的第一個Hello!First JSP!程式,JSP程式的副檔名是*.jsp,假設您的程式檔案命名為hello.jsp,其內容如下:

  • hello.jsp
<html> 
<head><title>Hello!First JSP!</title></head>
<body>
<b><% out.println("Hello!First JSP!"); %></b>
</body>
</html>

在這個JSP網頁中,您主要撰寫HTML的標籤,就如同一般編輯HTML網頁一樣,這是JSP網頁的靜態部份,這部份輸出至瀏覽器的結果就如您所撰寫的內容;<% 與 %>之間的程式碼是JSP的Quoting,您可以在Quoting之間撰寫有關於網頁動態的部份,撰寫的方式可以使用Java語法,但這種寫法是針對熟悉Java的程式設計人員而設計的。

如果是網頁設計人員的話,或許這麼撰寫會比較習慣一點:

  • hello.jsp
<html> 
<head><title>Hello!First JSP!</title></head>
<body>
<b><%="Hello!First JSP!"%></b>
</body>
</html>

<%= expression %>是運算式標籤,可以直接將運算式的結果轉換為文字傳回至瀏覽器,這樣的寫法比較近似於網頁設計人員所熟悉的標籤語法。

上面兩個JSP網頁可以讓您測試Web應用程式的基本環境設定是否正確,沒有意外的話,在瀏覽器中鍵入:
http://localhost:8080/myjsp/hello.jsp

Servlet容器就會開始將JSP網頁轉譯為Servlet原始碼、編譯、載入並執行程式,最後將結果傳回給瀏覽器,結果只是在瀏覽器中顯示 Hello! World!,而傳回的HTML內容如下:
<html>
<head><title>Hello!First JSP!</title></head>
<body>
    <b>Hello!First JSP! </b>
</body>
</html>

上面的例子是將Java的字串物件"Hello! First JSP!"轉換為文字並傳回至瀏覽器,兩個例子都沒有展現動態的輸出,為了展現動態程式的效果,來看下面這個例子:

  • hello.jsp
<html> 
<head><title>Hello!First JSP!</title></head>
<body>
Hello, it's <b><%= new java.util.Date() %> .
</body>
</html>

這寫法是使用Java語法的寫法,簡單的說生成一個 Date 物件,該物件包括時間資訊,轉換為字串並傳回,這個JSP網頁會將目前伺服器上的時間傳回至瀏覽器上,每次都會傳回不同的結果,例如結果是:
<html>
<head><title>Hello!First JSP!</title></head>
<body>
    Hello,  it's <b>Mon Jan 24 18:07:31 GMT+08:00 2005 .
</body>
</html>

JSP網頁會由容器轉換為Servlet原始碼,經由編譯器編譯,然後載入至JVM中,最後執行並傳回執行的結果,在第一個例子中,out.println()表示由一個JSPWriter物件的println ()方法,將指定的文字傳回至瀏覽器,這個部份是包括在<% 與 %>之間,是JSP網頁的動態部份,事實上,區分動態與靜態兩個部份只是在區分HTML標籤與JSP語法部份方便而已,對於JSP網頁轉換過後的 Servlet程式,所有的結果都是Servlet程式運算的結果,即使它是在JSP網頁中是純綷的HTML標籤,舉個例子,Hello! First JSP!的JSP網頁,轉換為Servlet網頁之後,其中輸出的部份是:
 package org.apache.jsp;
 
 import javax.servlet.*;
 import javax.servlet.http.*;
 import javax.servlet.jsp.*;
 
 public final class helloworld_jsp
              extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {
 
    public void _jspService(HttpServletRequest request,
                            HttpServletResponse response)
        throws java.io.IOException, ServletException {
        ......

      out.write("<html>\n");
      out.write(
          "<head><title>Hello!First JSP!</title></head>\n");
      out.write("<body>\n");
      out.write("    <b>");
      out.print("Hello! First JSP!");
      out.write("\n");
      out.write("</body>\n");
      out.write("</html>\n");
 
      ......
    }
 
    ......
 }

如果您有興趣,可以看看完整產生的Servlet原始碼,假設您JSP的所在目錄是 webapps/myjsp/helloworld.jsp,以我的Tomcat5.5.4來說,產生的Servlet原始碼是在 work/Catalina/localhost/myjsp下,由於package是org.apache.jsp,所以您可以在 work/Catalina/localhost/myjsp/org/apache/jsp/下找到對應的原始碼 helloworld_jsp.java,編譯好的Servlet類別檔也在其下。

所以轉換過後,JSP網頁的靜態HTML部份,在Servlet中也是一個Java程式運算輸出的結果,基本上,一個JSP網頁會轉換為一個Servlet類別,一個JSP網頁中不同的元素,會對應至Servlet中的field、method等等目標。

JSP網頁在第一次被讀取時,會轉換為Servlet並載入,之後若JSP網頁沒有變動,則容器就不會再為其進行轉換,而是直接從記憶體中執行載入的 Servlet程式,所以JSP網頁在第一次讀取執行時會比較慢,因為必須先轉換為Servlet原始碼、編譯後載入JVM執行,但之後再次請求同一個 JSP網頁時,執行速度則相當於執行Servlet的速度;如果JSP網頁被修改,則再次讀取JSP網頁時,容器發覺有被修改,就會重新轉換為新的 Servlet程式、編譯後重新載入。

依容器製造商的不同,您可以決定讓JSP先進行轉譯與編譯的動作,在JSP規格文件(JSP 11.4.2)中提過,您可以在查詢時附加一個查詢字串(Query String):?jsp_precompile,如果容器製造商有實作的話,則會先對JSP進行轉譯與編譯的動作。