From Gossip@caterpillar

JSP/Servlet: Scripting Elements

 

 


您使用<% 與 %>來包括JSP網頁中動態的部份,在當中撰寫Java程式碼,這是JSP的Scripting Elements之一,Scripting Elements共有三個:Scriptlet、Declaration與Expression。
  1. Scriptlet:以<% 與 %>包括的元素
  2. Declaration:以<%! 與 %>包括的元素
  3. Expression:以<%= 與 %>包括的元素

以<% 與 %>包括的部份可以包括Java程式語法,您可以將程式邏輯分作數個段,例如:
<%
    String c = request.getParameter("condition");
    if(c != null && c.equals("show")) {
%>
    <h1>Message 1 shown</h1>
<%
    } else {
%>
    <h1>Message 1 not shown</h1>
<%
    }
%>
 
request是JSP的隱含物件,轉換為Servlet之後對應於 javax.servlet.http.HttpServletRequest物 件,您可以從request中得到客戶端相關的請求資訊,例如使用request的getParameter("condition")就可以取得客戶端 請求中所設定的"condition"參數,假設檔案儲存為conditionTest.jsp,使用 http://localhost:8080/myjsp/conditionTest.jsp?condition=show,則網頁上會顯示:
Message 1 shown

如果沒有設定任何的參數,則會顯示:
Message 1 not shown

在轉換為Servlet之後,由<% 與 %>包括的部份主要集合為一個_jspService()方法,例如上面的Scriptlet會轉換為:
public void _jspService(HttpServletRequest request,
                         HttpServletResponse response)
        throws java.io.IOException, ServletException {
    ....
    String c = request.getParameter("condition");
    if(c != null && c.equals("show")) {
      out.write("\n");
      out.write("    <h1>Message 1 shown</h1>\n");
    } else {
      out.write("\n");
      out.write("    <h1>Message 1 not shown</h1>\n");
    }
    ....
}
 
注意到在JSP中<% 與 %>間宣告的變數,其轉換為方法中的一個區域變數,這可以與<%!與%>間宣告的變數相比較,JSP網頁最後會轉譯為一個Servlet類別,如果您在JSP中使用<%!與%>來宣告一個變數,則它在Servlet中會對應至一個field成員,例如:
<%!
    String str1;
    int i, j;
%>
 
<%
    str1 = "This is a test!";
    i = 10;
    j = 20;
%>
 

這個簡單的程式在轉換為Servlet之後,主要對應的部份如下:
public final class Test_jsp
    extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {
    .....
    String str1;
    int i, j;
 
    ....
    public void _jspService(HttpServletRequest request,
                            HttpServletResponse response)
        throws java.io.IOException, ServletException {
 
        str1 = "This is a test!";
        i = 10;
        j = 20;
    }
}
 

由於Servlet被載入後,將會一直存在於JVM中,直到容器規定的存在期限過期,或是關閉伺服器後才會清除Servlet產生的實例,所以使用<%!與% >宣告變數時,必須小心資料共用與執行緒安全的問題,預設上容器會使用同一個Servlet實例來服務來自不同使用者的請求,而 <%!與%>間宣告的變數對應至field成員,所以對於同一個實例來說,如果某個請求已設定了str1,而另一個請求要求顯示str1,則 第二個請求有可能顯示的會是第一個請求所設定的值,因而使得顯示的請求不正確。

並不是要求不要在<%!與%>間宣告變數,只要瞭解其實際對應產生的是Servlet類別中的一個field,而且預設上容器會使用同一個實 例來服務來自不同使用者的請求,視需求使用即可,不過建議學習過Java Thread的人來使用,因為會比較瞭解資料共用、執行緒安全等問題與解決方法。
<%!與%>之間也可以宣告method,例如:
<%!
    private String sayHelloto(String name) {
         return "Hello, " + name;
    }
%>
 

這個method可以在同一個JSP頁面中呼叫,而它將在轉換為Servlet之後,成為Servlet類別的一個method member,您可以自己試著看看產生之後的Servlet程式碼。

<%= expression %>是一個運算式表示,它可以視作 <% out.println(expression); %> 的一個簡單表示法,其中expression是一個運算表示式,例如:<% out.println(new java.util.Date()); %>就可以寫成<%= new java.util.Date() %>,注意這個表示法中最後不需要加上分號,例如這樣就是錯的語法:
<%= new java.util.Date(); %>


對於Web應用程式來說,Scriptlet是個不樂意被見到的東西,因為它會使得HTML與Java程式碼交相混雜,對於程式的維護來說相當的麻煩,必 要的時候,您可以在web.xml中加上<script-invalid>標籤,設定所有的JSP網頁都不可以使用Scriptlet,例 如:
...
<web-app ..>
    ....
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <script-invalid>true</script-invalid>
        </jsp-property-group>
    </jsp-config>
....
</web-app>