1.scriptlet : <% %> ,百分號之間添加java代碼塊,例如<%out.print(Counter.getCount())%>
2.指令:<%@ %> 主要用於導入所需要的java文件,比如 <%@ page import ="java.util.*"%>
3.表達式:<%= %>表達式內容寫在=後邊,需要有返回值,不需要";" ,因爲表達式是以參數的形式傳遞out.print()
<%=Counter.getCount()%> 會轉換爲<%out.print(Counter.getCount())%>
4.申明:<%! int count = 0;%> JSP聲明用於申明所生成的servlet類的成員,所以可以申明方法和變量,即所有申明都會添加到類中
因此以下的代碼,不能統計頁面訪問量,因爲scriptlet中的變量會被定義在生成的servlet的方法中,每次訪問count重新定義爲0
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
this page count is:
<%
int cpunt = 0;
%>
<%= count++%>
</body>
</html>
需要達到統計的效果,可以將count放到申明中,代碼如下
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
this page count is:
<%!
int count = 0;
%>
<%= count++%>
</body>
</html>
那麼容器如何處理JSP文件的呢
1.查看指令,得到轉換時可能需要的信息
2.創建HttpServlet子類
3.如果page指令有import屬性,會在類文件的最上邊,package下面寫import語句
4.如果有申請,容器將這些申明寫到類文件中,通常在類申明洗下面,服務方法前面
5.簡歷服務方法,服務方法的具體名爲_jspService(),所生成的servlet會覆蓋servlet超類的service方法,_jspService方法就由service方法調用,需要接受HttpServletRequest和HttpServletResponse參數,建立這個方法是,容器會申明並初始化所有隱式對象,
6.將普通的HTML,scriptlet和表達式放到服務方法中,完成格式化,並寫入PrintWriter響應輸出
除了以上四個元素之外,還有一種稱爲動作,
5.標準動作
<jsp:useBean id="person" class="foo.Person" scope="request"/>
person is <jsp:getProperty name="person" property="name"/>
思考:動作<jsp:include page="Header.jsp"/>和指令<%@ include file="Header.jsp"%>都可以爲頁面添加制定的JSP內容,有何不同呢?
1.生成的servlet代碼不同,指令會在servlet中將jsp的內容和jsp頁面的內容拼裝成新的html,而標準動作則不會,它只是運行時調用。即指令在轉換時發生,動作在運行時發生。指令是在生成servlet時合併引進來的html代碼,之後如果有改動,必須重新生成,而動作是每次在運行時合併兩個servlet。
2.需要注意的是指令在合併的時候需要將重用jsp的html和body標記去掉,否則這兩個標記會嵌入到新的html中間
6.EL表達式
EL表達式對於顯示屬性的屬性變得非常容易,比如Person類中有Dog屬性,dog中有name屬性,需要打印dog的name時,只需要如下
${person.dog.name}
這條EL表達式相當於下面
<%= ((foo.person)request.getAttribute("person")).getDog().getname() %>
${A.B}也可以表示爲${A[B]},其中[]可以是數組,bean以及list
除此之外,EL表達式可以直接讀取隱式對象中的屬性,同時可以處理null值(參見head first servlet&JSP第八章)