JSP+EL+JSTL
JSP
java server page:java伺服器端頁面。其實就是一個特殊的頁面,其中即可以寫html文件,又可以寫java程式碼。JSP本質上就是一個Servlet。
JSP的工作模式是請求/響應模式,客戶端首先發出HTTP請求,JSP程式收到請求後進行處理並返回處理結果。在一個JSP檔案第1次被請求時,JSP引擎(容器)把該JSP檔案轉換成為一個Servlet,而這個引擎本身也是一個Servlet。
像這種將前後端程式碼合在一起的技術成為模板引擎. Java常用的模板引擎除了 jsp 之外還有 Freemarker 和 Beetl.
使用
-
JSP指令碼元素:是指巢狀在<%和%>之中的一條或多條Java程式程式碼。主要包括以下三種類型:
-
JSP指令碼<% 程式碼 %>:這裡寫的程式碼會被放在service方法中,裡面定義的變數都是區域性變數。
-
JSP宣告<%! 程式碼 %>:用於在JSP頁面中定義全域性的變數或方法,是Servlet的成員變數或成員方法。
-
JSP表示式<%= 程式碼 %>:可以是任何Java語言的完整表示式。該表示式的最終運算結果將被轉換為字串並輸出到頁面上。相當於 out.println()
<body> 計算3/2=<%= 3/2 %> <%-- JSP表示式不僅可以插入網頁的文字中,用於輸出文字內容,也可以插入HTML標記中,用於動態設定屬性值。--%> </body>
-
-
註釋
- JSP註釋:<%-- --%> 伺服器端註釋,解析時將跳過這些程式碼,在客戶端是檢視原始碼是看不到這些註釋的。
- html註釋:客戶端註釋,瀏覽器檢視原始碼是可以看到這些註釋的。
-
JSP指令:用來設定JSP頁面中的一些資訊
-
page指令:用來對頁面的某些特性進行描述,如:頁面的編碼方式、JSP 頁面採用的語言等
格式:<%@ page 屬性名1= "屬性值1" 屬性名2= "屬性值2" ...%>
page指令常見屬性:
注意:除了import屬性外,其他的屬性都只能出現一次,否則會編譯失敗。同時page指令的屬性名稱都是區分大小寫的。<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
-
include指令:在實際開發時,有時需要在JSP頁面靜態包含一個檔案,例如HTML檔案、JSP等,這時,可以通過include指令來實現。不過該指令是靜態包含,也就是說被包含檔案中所有內容會被原樣包含到該JSP頁面中,即使被包含檔案中有JSP程式碼,在包含時也不會被編譯執行。使用include指令,最終將生成一個檔案,所以在被包含和包含的檔案中,不能有相同名稱的變數。
格式:<%@ include file="被包含的檔案地址"%>
注意:在應用include指令進行檔案包含時,為了使整個頁面的層次結構不發生衝突,建議在被包含頁面中將<html>、<body>等標記刪除。因為在包含該頁面的文件中已經指定了這些標籤。
top.jsp:<%@ page contentType="text/html;charset=UTF-8" language="java" %> <div style="background-color: antiquewhite;color: blue;font-size: x-large"><%="這是標題"%>></div> <!-- 使用include,兩個頁面的page指令必須一樣-->
index.jsp:
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <%@include file="top.jsp"%> <h1><%= "Hello World!" %> </h1> <br/> <a href="hello-servlet">Hello Servlet</a> </body> </html>
-
taglib:用來匯入外部標籤庫。
<%taglib uri="" prefix=""%>
-
-
動作標識
-
包含檔案標識<jsp:include>用於向當前頁面中包含其他的檔案。被包含的檔案可以是動態檔案,也可以是靜態檔案。
格式:<jsp:Include page=“url” flush=“false|true”/>
- <jsp:include>和include指令的比較
- include指令通過file屬性指定被包含的檔案,並且file屬性不支援任何表示式;<jsp:include>動作標識通過page屬性指定被包含的檔案,而且page屬性支援JSP表示式。
- 使用include指令時,被包含的檔案內容會原封不動地插入包含頁中,然後JSP編譯器再將合成後的檔案最終編譯成一個Java檔案;使用<jsp:include>動作標識包含檔案時,當該標識被執行時,程式會將請求轉發(注意是轉發,而不是請求重定向)到被包含的頁面,並將執行結果輸出到瀏覽器中,然後返回包含頁繼續執行後面的程式碼。因為伺服器執行的是多個檔案,所以JSP編譯器會分別對這些檔案進行編譯。
- 在應用include指令包含檔案時,由於被包含的檔案最終會生成一個檔案,所以在被包含檔案、包含檔案中不能有重名的變數或方法;而在應用<jsp:include>動作標識包含檔案時,由於每個檔案是單獨編譯的,所以在被包含檔案和包含檔案中重名的變數和方法是不相沖突的。
- <jsp:include>和include指令的比較
-
請求轉發標識<jsp:forword>:可以將請求轉發到其他的Web資源,例如,另一個JSP頁面、HTML頁面、Servlet等。
格式:<jsp:forward page="url" />
-
引數傳遞標識<jsp:param>:可以作為其他標識的子標識,用於為其他標識傳遞引數。
格式:<jsp:param name="引數名" value="值">
<jsp:forward page="login.jsp" /> <jsp:param name="username" value="zhangsan" /> </jsp:forward>
通過<jsp:param>動作標識指定的引數,將以“引數名=值”的形式加入請求中。它的功能與在檔名後面直接加“?引數名=引數值一樣。
-
9個內建物件
JSP提供了一些內建物件,不需要例項化就可以直接使用
-
out:字元輸出流物件。可以將資料輸出到頁面上,和resp.getWriter()類似。
resp.getWriter()和out.write()的區別:在tomcat伺服器真正給客戶端做出響應之前,會先找resp緩衝區資料,再找out緩衝區資料。所以resp.getWriter()資料輸出永遠在out.write()之前out物件提供了print()和println()兩種向頁面中輸出資訊的方法。不過使用println方法在頁面中看不到換行的效果。out.println()相當於
<%= %>
-
page:代表當前JSP頁面本身,本質是包含當前Servlet介面引用的變數,可以看作是this關鍵字的別名。
page物件常用方法
-
exception:用來處理JSP檔案執行時發生的所有錯誤和異常。只有在page指令中設定為isErrorPage屬性值為true的頁面中才可以被使用,在一般的JSP頁面中使用該物件將無法編譯JSP檔案。
exception物件幾乎定義了所有異常情況,在Java程式中,可以使用try...catch關鍵字來處理異常情況,如果在JSP頁面中出現沒有捕捉到的異常,就會生成exception物件,並把exception物件傳送到在page指令中設定的錯誤頁面中,然後在錯誤頁面中處理相應的exception物件。
index.jsp頁面產生錯誤,並傳遞給error.jsp<%@ page import="java.util.Date" %> <%@ page import="java.text.SimpleDateFormat" %> <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" errorPage="error.jsp" %> <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <% String str = "100元"; Float price = Float.parseFloat(str); %> </body> </html>
在error.jsp列印錯誤資訊
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %> <html> <head> </head> <body> <%=exception.getMessage() %> </body> </html>
-
PageContext:jsp獨有的,Servlet中沒有。是四大域物件(應用域ServletContext、會話域HttpSession、請求域ServletRequest、PageContext)之一的頁面域物件,還可以操作其他三個域物件中的屬性。生命週期和隨著jsp的建立而存在,隨著jsp的結束而消失。
常用方法:
父類JspContext的方法
案例:使用JSP獲取上次訪問頁面的時間
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<%
long lastAccessedTime = session.getLastAccessedTime();//獲取上次訪問時間的毫秒數
Date date = new Date();
date.setTime(lastAccessedTime);//將毫秒數轉成日期物件
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String str_date = sdf.format(date);//格式化日期物件
%>
<%= str_date%>
</body>
</html>
JSP最佳實戰-MVC模型
MVC模式:model + view + controller 模型+檢視+控制器,是一種軟體設計典範。
M:model,通常用於封裝資料。具體的方法由普通的Java類實現, 一般起名為 xxxService. 如果要進行持久化儲存, 還需要 dao 和 bean, 以便於和資料庫互動.
V:view ,通常用於展示資料。動態展示用jsp頁面,靜態資料展示用html。
C:controller ,通常用於處理請求和響應。一般指的是Servlet。
JavaBean
Java規定了標準的類定義格式,符合這種格式的Java類就是一個JavaBean。要求如下:
- 所有屬性為private
- 提供公共的無參構造方法
- 提供getter和setter
- 實現serializable介面
JavaBean在Java EE開發中,通常用於封裝資料,對於遵循以上寫法的JavaBean元件,其它程式可以通過反射技術例項化JavaBean物件(內省機制),並且通過反射那些遵循命名規範的方法,從而獲知JavaBean的屬性,進而呼叫其屬性儲存資料。
所以符合JavaBean規範的類,就算成員變數是私有的,也可以直接使用物件名.屬性名修改。大大簡化了jsp的程式碼。
EL
Expression Language表示式語言。用來替換和簡化jsp頁面中java程式碼的編寫。
語法:${表示式}。注意EL用在jsp的java程式碼中,jQuery用在JavaScript中。
使用
獲取四大域中的資料
找到了就輸出,沒找到就空著,不會輸出null,比較美觀。
-
el表示式只能從域物件中獲取值
-
${域名稱.鍵名}:從指定域中獲取指定鍵的值
pageScope --> pageContext
requestScope --> request
sessionScope --> session
applicationScope --> application(ServletContext) -
${鍵名}:表示依次從最小的域中查詢是否有該鍵對應的值,直到找到為止。
-
獲取引數:${param.引數名} param是EL內建的物件
-
獲取物件、List集合、Map集合的值
-
物件:${域名稱.物件名.屬性名}
package com.example.JSPDemo;//定義一個JavaBean類 public class Person { private String name;//屬性都是私有的 private Date birthday; public Person(){} //提供無參構造 //getter、setter略 //成員方法 public String getInfo() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); return name + "出生於:"+sdf.format(birthday) ; } }
<%@ page import="com.example.JSPDemo.Person" %> <%@ page import="java.util.Date" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> </head> <body> <% //先使用java程式碼建立一個物件,再儲存到域物件中,就可以使用EL表示式來訪問了 Person person = new Person(); person.setBirthday(new Date()); person.setName("zhangsan"); request.setAttribute("p",person);//這一步是必需的,物件必須儲存到域中,才可以用EL來訪問 %> ${p.name}<br/> ${p.birthday}<br/> ${p.info}<br/><%--像訪問屬性一樣呼叫方法,注意去掉方法名前的get、set,然後名稱一律小寫,直接呼叫--%> </body> </html>
-
List集合:${域名稱.集合名[索引]}
-
Map集合:${域名稱.集合名.key}或${域名稱.集合名["key"]}
-
運算子
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="com.itheima.domain.User" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>EL兩個特殊的運算子</title>
</head>
<body>
<%--空運算子: empty
功能:用於判斷字串、集合、陣列物件是否為null或者長度是否為0
${empty list}:判斷字串、集合、陣列物件是否為null或者長度為0
${not empty str}:表示判斷字串、集合、陣列物件是否不為null 並且 長度>0
--%>
<% String str = null;
String str1 = "";
List<String> slist = new ArrayList<String>();
pageContext.setAttribute("str", str);
pageContext.setAttribute("str1", str1);
pageContext.setAttribute("slist", slist);
%>
${empty str}============當物件為null返回true<br/>
${empty str1 }==========當字串為空字串是返回true(注意:它不會呼叫trim()方法)<br>
${empty slist}==========當集合中的元素是0個時,是true
<hr/>
<%--三元運算子
條件?真:假
--%>
<% request.setAttribute("gender", "female"); %>
<input type="radio" name="gender" value="male" ${gender eq "male"?"checked":""} >男
<input type="radio" name="gender" value="female" ${gender eq "female"?"checked":""}>女
</body>
</html>
11個內建物件
EL表示式也為我們提供隱式物件,可以讓我們不宣告直接來使用,十一個物件見下表,需要注意的是,它和JSP的隱式物件不是一回事:
EL中的隱式物件 | 型別 | 對應JSP隱式物件 | 備註 |
---|---|---|---|
PageContext | Javax.serlvet.jsp.PageContext | PageContext | 完全一樣 |
ApplicationScope | Java.util.Map | application | 應用層範圍 |
SessionScope | Java.util.Map | session | 會話範圍 |
RequestScope | Java.util.Map | request | 請求範圍 |
PageScope | Java.util.Map | 沒有 | 頁面層範圍 |
Header | Java.util.Map | 沒有 | 請求訊息頭key,值是value(一個) |
HeaderValues | Java.util.Map | 沒有 | 請求訊息頭key,值是陣列(一個頭多個值) |
Param | Java.util.Map | 沒有 | 請求引數key,值是value(一個) |
ParamValues | Java.util.Map | 沒有 | 請求引數key,值是陣列(一個名稱多個值) |
InitParam | Java.util.Map | 沒有 | 全域性引數,key是引數名稱,value是引數值 |
Cookie | Java.util.Map | 沒有 | Key是cookie的名稱,value是cookie物件 |
注意:jsp和EL的pageContext物件其實就是同一個物件。
注意
EL沒有空指標異常、沒有索引越界異常、沒有字串拼接的效果
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>EL表示式的注意事項</title>
</head>
<body>
<%--EL表示式的三個沒有--%>
第一個:沒有空指標異常<br/>
<% String str = null;
request.setAttribute("testNull",str);
%>
${testNull}
<hr/>
第二個:沒有陣列下標越界<br/>
<% String[] strs = new String[]{"a","b","c"};
request.setAttribute("strs",strs);
%>
取第一個元素:${strs[0]}
取第六個元素:${strs[5]}
<hr/>
第三個:沒有字串拼接<br/>
<%--${strs[0]+strs[1]}--%>
${strs[0]}+${strs[1]}
</body>
</html>
JSTL
JSP tag library JSP標準標籤庫,用於簡化和替換jsp頁面上的java程式碼。由以下5個部分組成:
組成 | 作用 | 說明 |
---|---|---|
Core | 核心標籤庫。 | 通用邏輯處理 |
Fmt | 國際化有關。 | 需要不同地域顯示不同語言時使用 |
Functions | EL函式 | EL表示式可以使用的方法 |
SQL | 操作資料庫。 | 不用 |
XML | 操作XML。 | 不用 |
使用步驟:
- 匯入jstl相關jar包
- 引入標籤庫:taglib指令:<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
- 使用標籤
核心標籤庫
-
if:相當於java程式碼的if語句
- 屬性:
- test 必須屬性,接受boolean表示式
- 如果表示式為true,則顯示if標籤體內容,如果為false,則不顯示標籤體內容
- 一般情況下,test屬性值會結合el表示式一起使用
- 注意:c:if標籤沒有else情況,想要else情況,就再定義一個c:if
- test 必須屬性,接受boolean表示式
- 屬性:
-
choose:相當於java程式碼的switch語句
- 使用choose標籤宣告 相當於switch宣告
- 使用when標籤做判斷 相當於case
- 使用otherwise標籤做其他情況的宣告 相當於default
-
foreach:相當於java程式碼的for語句
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%--匯入jstl標籤庫 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>JSTL的常用標籤</title>
</head>
<body>
<%-- c:if c:choose c:when c:otherwise --%>
<% pageContext.setAttribute("score","F"); %>
<c:if test="${pageScope.score eq 'A' }">
優秀
</c:if>
<c:if test="${pageScope.score eq 'C' }">
一般
</c:if>
<hr/>
<c:choose>
<c:when test="${pageScope.score eq 'A' }">
AAA
</c:when>
<c:when test="${pageScope.score eq 'B' }">BBB
</c:when>
<c:when test="${pageScope.score eq 'C' }">CCC
</c:when>
<c:when test="${pageScope.score eq 'D' }">DDD
</c:when>
<c:otherwise>其他</c:otherwise>
</c:choose>
<%-- c:forEach 它是用來遍歷集合的
屬性:
items:要遍歷的集合,它可以是EL表示式取出來的
var:把當前遍歷的元素放入指定的page域中。 var的取值就是key,當前遍歷的元素就是value
注意:它不能支援EL表示式,只能是字串常量
begin:開始遍歷的索引
end:結束遍歷的索引
step:步長。i+=step
varStatus:它是一個計數器物件。裡面有兩個屬性,一個是用於記錄索引。一個是用於計數。
索引是從0開始。計數是從1開始
--%>
<hr/>
<% List<String> list = new ArrayList<String>();
list.add("AAA");
list.add("BBB");
list.add("CCC");
list.add("DDD");
list.add("EEE");
list.add("FFF");
list.add("GGG");
list.add("HHH");
list.add("III");
list.add("JJJ");
list.add("KKK");
list.add("LLL");
pageContext.setAttribute("list",list);
%>
<c:forEach items="${list}" var="s" begin="1" end="7" step="2">
${s}<br/>
</c:forEach>
<hr/>
<c:forEach begin="1" end="9" var="num">
<a href="#">${num}</a>
</c:forEach>
<hr/>
<table>
<tr>
<td>索引</td>
<td>序號</td>
<td>資訊</td>
</tr>
<c:forEach items="${list}" var="s" varStatus="vs">
<tr>
<td>${vs.index}</td>
<td>${vs.count}</td>
<td>${s}</td>
</tr>
</c:forEach>
</table>
</body>
</html>