## JSP 簡介
JSP(全稱Java Server Pages)是由 Sun Microsystems 公司倡導和許多公司參與共同創建的一種使軟件開發者可以響應客戶端請求,而動態生成 HTML、XML 或其他格式文檔的Web網頁的技術標準。
JSP 技術是以 Java 語言作為腳本語言的,JSP 網頁為整個服務器端的 Java 庫單元提供了一個接口來服務于HTTP的應用程序。
JSP文件后綴名為 ***.jsp** 。
JSP開發的WEB應用可以跨平臺使用,既可以運行在 Linux 上也能運行在 Windows 上。
## JSP 概念
jsp全名為Java Server Pages,中文名叫java服務器頁面,其根本是一個簡化的Servlet設計,它是由Sun Microsystems公司倡導、許多公司參與一起建立的一種動態網頁技術標準。
jsp外表看起來和HTML沒有多少區別,只是多了一個頭部的標識,和文件后綴名改為了.jsp的形式,但是本質上區別是很大的。jsp是運行在服務端的java,html本質上就是靜態頁面。
## JSP 語法
上面說過,jsp實際上就是java代碼,也就是說可以直接在頁面上寫java代碼。下面就是書寫方式。
```html
<% 代碼片段 %>
```
下面的案例是通過java代碼在頁面上輸出的結果為你的IP地址
```html
<html>
<head>
<title>Hello World</title>
</head>
<body>
Hello World!<br/>
<%
out.println("Your IP address is " + request.getRemoteAddr());
%>
</body>
</html>
```
**注意:**請確保正確安裝了tomcat,然后再檢查文件名字是不是hello.jsp,把文件復制到tomcat安裝目錄的webapps/ROOT文件夾下面,瀏覽器訪問:http://localhost:8080/hello.jsp 得到測試結果。
## JSP 指令
JSP指令用來設置整個JSP頁面相關的屬性,如網頁的編碼方式和腳本語言。指令可以有很多個屬性,它們以鍵值對的形式存在,并用逗號隔開。
JSP中的三種指令標簽:
| 指令 | 描述 |
| ------------ | ------------ |
| <%@ page ... %> | 定義網頁依賴屬性,比如腳本語言、error頁面、緩存需求等等 |
| <%@ include ... %> | 包含其他文件 |
| <%@ taglib ... %> | 引入標簽庫的定義 |
**Page指令**
Page指令為容器提供當前頁面的使用說明。一個JSP頁面可以包含多個page指令。
Page指令的語法格式:
```html
<%@ page 屬性="屬性值" %>
```
Page指令相關的屬性:
| 屬性 | 描述 |
| ------------ | ------------ |
| buffer | 指定out對象使用緩沖區的大小 |
| autoFlush | 控制out對象的 緩存區 |
| contentType | 指定當前JSP頁面的MIME類型和字符編碼 |
| errorPage | 指定當JSP頁面發生異常時需要轉向的錯誤處理頁面 |
| isErrorPage | 指定當前頁面是否可以作為另一個JSP頁面的錯誤處理頁面 |
| extends | 指定servlet從哪一個類繼承 |
| import | 導入要使用的Java類 |
| info | 定義JSP頁面的描述信息 |
| isThreadSafe | 指定對JSP頁面的訪問是否為線程安全 |
| language | 定義JSP頁面所用的腳本語言,默認是Java |
| session | 指定JSP頁面是否使用session |
| isELIgnored | 指定是否執行EL表達式 |
| isScriptingEnabled | 確定腳本元素能否被使用 |
**Include指令**
JSP可以通過include指令來包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是該JSP文件的一部分,會被同時編譯執行。
Include指令的語法格式如下:
```html
<%@ include file="相對路徑" %>
```
Include指令中的文件名實際上是一個相對的URL。如果您沒有給文件關聯一個路徑,JSP編譯器默認在當前路徑下尋找。
**Taglib指令**
JSP API允許用戶自定義標簽,一個自定義標簽庫就是自定義標簽的集合。
Taglib指令引入一個自定義標簽集合的定義,包括庫路徑、自定義標簽。
Taglib指令的語法:
```html
<%@ taglib uri="標簽庫的位置" prefix="標簽庫的前綴" %>
```
## JSP 隱式對象
JSP隱式對象是JSP容器為每個頁面提供的Java對象,開發者可以直接使用它們而不用顯式聲明。JSP隱式對象也被稱為預定義變量。
**JSP九大隱式對象:**
| 對象 | 描述 |
| ------------ | ------------ |
| request | HttpServletRequest類的實例 |
| response | HttpServletResponse類的實例 | |
| out | PrintWriter類的實例,用于把結果輸出至網頁上 |
| session | HttpSession類的實例 |
| application | ServletContext類的實例,與應用上下文有關 |
| config | ServletConfig類的實例 |
| pageContext | PageContext類的實例,提供對JSP頁面所有對象以及命名空間的訪問 |
| page | 類似于Java類中的this關鍵字 |
| Exception | Exception類的對象,代表發生錯誤的JSP頁面中對應的異常對象 |
**request對象**
request對象是javax.servlet.http.HttpServletRequest 類的實例。每當客戶端請求一個JSP頁面時,JSP引擎就會制造一個新的request對象來代表這個請求。
request對象提供了一系列方法來獲取HTTP頭信息,cookies,HTTP方法等等。
**response對象**
response對象是javax.servlet.http.HttpServletResponse類的實例。當服務器創建request對象時會同時創建用于響應這個客戶端的response對象。
response對象也定義了處理HTTP頭模塊的接口。通過這個對象,開發者們可以添加新的cookies,時間戳,HTTP狀態碼等等。
**out對象**
out對象是 javax.servlet.jsp.JspWriter 類的實例,用來在response對象中寫入內容。
最初的JspWriter類對象根據頁面是否有緩存來進行不同的實例化操作。可以在page指令中使用buffered='false'屬性來輕松關閉緩存。
JspWriter類包含了大部分java.io.PrintWriter類中的方法。不過,JspWriter新增了一些專為處理緩存而設計的方法。還有就是,JspWriter類會拋出IOExceptions異常,而PrintWriter不會。
下表列出了我們將會用來輸出boolean,char,int,double,Srtring,object等類型數據的重要方法:
| 方法 | 描述 |
| ------------ | ------------ |
| out.print(dataType dt) | 輸出Type類型的值 |
| out.println(dataType dt) | 輸出Type類型的值然后換行 |
| out.flush() | 刷新輸出流 |
**session對象**
session對象是 javax.servlet.http.HttpSession 類的實例。和Java Servlets中的session對象有一樣的行為。
session對象用來跟蹤在各個客戶端請求間的會話。
**application對象**
application對象直接包裝了servlet的ServletContext類的對象,是javax.servlet.ServletContext 類的實例。
這個對象在JSP頁面的整個生命周期中都代表著這個JSP頁面。這個對象在JSP頁面初始化時被創建,隨著jspDestroy()方法的調用而被移除。
通過向application中添加屬性,則所有組成您web應用的JSP文件都能訪問到這些屬性。
**config對象**
config對象是 javax.servlet.ServletConfig 類的實例,直接包裝了servlet的ServletConfig類的對象。
這個對象允許開發者訪問Servlet或者JSP引擎的初始化參數,比如文件路徑等。
以下是config對象的使用方法,不是很重要,所以不常用:
```html
config.getServletName();
```
它返回包含在<servlet-name>元素中的servlet名字,注意,<servlet-name>元素在 WEB-INF\web.xml 文件中定義。
**pageContext 對象**
pageContext對象是javax.servlet.jsp.PageContext 類的實例,用來代表整個JSP頁面。
這個對象主要用來訪問頁面信息,同時過濾掉大部分實現細節。
這個對象存儲了request對象和response對象的引用。application對象,config對象,session對象,out對象可以通過訪問這個對象的屬性來導出。
pageContext對象也包含了傳給JSP頁面的指令信息,包括緩存信息,ErrorPage URL,頁面scope等。
PageContext類定義了一些字段,包括PAGE_SCOPE,REQUEST_SCOPE,SESSION_SCOPE, APPLICATION_SCOPE。它也提供了40余種方法,有一半繼承自javax.servlet.jsp.JspContext 類。
其中一個重要的方法就是removeArribute(),它可接受一個或兩個參數。比如,pageContext.removeArribute("attrName")移除四個scope中相關屬性,但是下面這種方法只移除特定scope中的相關屬性:
```html
pageContext.removeAttribute("attrName", PAGE_SCOPE);
```
**page 對象**
這個對象就是頁面實例的引用。它可以被看做是整個JSP頁面的代表。
page 對象就是this對象的同義詞。
**exception 對象**
exception 對象包裝了從先前頁面中拋出的異常信息。它通常被用來產生對出錯條件的適當響應。
## JSTL 標準標簽庫
JSP標準標簽庫(JSTL)是一個JSP標簽集合,它封裝了JSP應用的通用核心功能。
JSTL支持通用的、結構化的任務,比如迭代,條件判斷,XML文檔操作,國際化標簽,SQL標簽。 除了這些,它還提供了一個框架來使用集成JSTL的自定義標簽。
根據JSTL標簽所提供的功能,可以將其分為5個類別。
- 核心標簽
- 格式化標簽
- SQL 標簽
- XML 標簽
- JSTL 函數
- JSTL 庫安裝
## JSTL 使用前提
首先導入jstl-1.2.jar,然后在使用標簽的頁面頭部引用對應的標簽庫,通常使用<c:forEach>,<c:if>,<c:choose>,<c:when>,都需要在頁面頭部寫一下內容:
```html
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
```
## JSTL 核心標簽
核心標簽是最常用的JSTL標簽。引用核心標簽庫的語法如下:
```html
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
```
| 標簽 | 描述 |
| ------------ | ------------ |
| <c:out> | 用于在JSP中顯示數據,就像<%= ... > |
| <c:set> | 用于保存數據 |
| <c:remove> | 用于刪除數據 |
| <c:catch> | 用來處理產生錯誤的異常狀況,并且將錯誤信息儲存起來 |
| <c:if> | 與我們在一般程序中用的if一樣 |
| <c:choose> | 本身只當做<c:when>和<c:otherwise>的父標簽 |
| <c:when> | <c:choose>的子標簽,用來判斷條件是否成立 |
| <c:otherwise> | <c:choose>的子標簽,接在<c:when>標簽后,當<c:when>標簽判斷為false時被執行 |
| <c:import> | 檢索一個絕對或相對 URL,然后將其內容暴露給頁面 |
| <c:forEach> | 基礎迭代標簽,接受多種集合類型 |
| <c:forTokens> | 根據指定的分隔符來分隔內容并迭代輸出 |
| <c:param> | 用來給包含或重定向的頁面傳遞參數 |
| <c:redirect> | 重定向至一個新的URL. |
| <c:url> | 使用可選的查詢參數來創造一個URL |
## JSTL 格式化標簽
JSTL格式化標簽用來格式化并輸出文本、日期、時間、數字。引用格式化標簽庫的語法如下:
```html
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
```
| 標簽 | 描述 |
| ------------ | ------------ |
| <fmt:formatNumber> | 使用指定的格式或精度格式化數字 |
| <fmt:parseNumber> | 解析一個代表著數字,貨幣或百分比的字符串 |
| <fmt:formatDate> | 使用指定的風格或模式格式化日期和時間 |
| <fmt:parseDate> | 解析一個代表著日期或時間的字符串 |
| <fmt:bundle> | 綁定資源 |
| <fmt:setLocale> | 指定地區 |
| <fmt:setBundle> | 綁定資源 |
| <fmt:timeZone> | 指定時區 |
| <fmt:setTimeZone> | 指定時區 |
| <fmt:message> | 顯示資源配置文件信息 |
| <fmt:requestEncoding> | 設置request的字符編碼 |
## JSTL SQL標簽
JSTL SQL標簽庫提供了與關系型數據庫(Oracle,MySQL,SQL Server等等)進行交互的標簽。引用SQL標簽庫的語法如下:
```html
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
```
| 標簽 | 描述 |
| ------------ | ------------ |
| <sql:setDataSource> | 指定數據源 |
| <sql:query> | 運行SQL查詢語句 |
| <sql:update> | 運行SQL更新語句 |
| <sql:param> | 將SQL語句中的參數設為指定值 |
| <sql:dateParam> | 將SQL語句中的日期參數設為指定的java.util.Date 對象值 |
| <sql:transaction> | 在共享數據庫連接中提供嵌套的數據庫行為元素,將所有語句以一個事務的形式來運行 |
## JSTL XML 標簽
JSTL XML標簽庫提供了創建和操作XML文檔的標簽。引用XML標簽庫的語法如下:
```html
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
```
在使用xml標簽前,你必須將XML 和 XPath 的相關包拷貝至你的<Tomcat 安裝目錄>\lib下:
XercesImpl.jar下載地址: http://www.apache.org/dist/xerces/j/
xalan.jar下載地址: http://xml.apache.org/xalan-j/index.html
| 標簽 | 描述 |
| ------------ | ------------ |
| <x:out> | 與<%= ... >,類似,不過只用于XPath表達式 |
| <x:parse> | 解析 XML 數據 |
| <x:set> | 設置XPath表達式 |
| <x:if> | 判斷XPath表達式,若為真,則執行本體中的內容,否則跳過本體 |
| <x:forEach> | 迭代XML文檔中的節點 |
| <x:choose> | <x:when>和<x:otherwise>的父標簽 |
| <x:when> | <x:choose>的子標簽,用來進行條件判斷 |
| <x:otherwise> | <x:choose>的子標簽,當<x:when>判斷為false時被執行 |
| <x:transform> | 將XSL轉換應用在XML文檔中 |
| <x:param> | 與<x:transform>共同使用,用于設置XSL樣式表 |
## JSTL 函數
JSTL包含一系列標準函數,大部分是通用的字符串處理函數。引用JSTL函數庫的語法如下:
```html
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
```
| 標簽 | 描述 |
| ------------ | ------------ |
| fn:contains() | 測試輸入的字符串是否包含指定的子串 |
| fn:containsIgnoreCase() | 測試輸入的字符串是否包含指定的子串,大小寫不敏感 |
| fn:endsWith() | 測試輸入的字符串是否以指定的后綴結尾 |
| fn:escapeXml() | 跳過可以作為XML標記的字符 |
| fn:indexOf() | 返回指定字符串在輸入字符串中出現的位置 |
| fn:join() | 將數組中的元素合成一個字符串然后輸出 |
| fn:length() | 返回字符串長度 |
| fn:replace() | 將輸入字符串中指定的位置替換為指定的字符串然后返回 |
| fn:split() | 將字符串用指定的分隔符分隔然后組成一個子字符串數組并返回 |
| fn:startsWith() | 測試輸入字符串是否以指定的前綴開始 |
| fn:substring() | 返回字符串的子集 |
| fn:substringAfter() | 返回字符串在指定子串之后的子集 |
| fn:substringBefore() | 返回字符串在指定子串之前的子集 |
| fn:toLowerCase() | 將字符串中的字符轉為小寫 |
| fn:toUpperCase() | 將字符串中的字符轉為大寫 |
| fn:trim() | 移除首位的空白符 |
## JSTL 案例 -- 遍歷list集合
```java
package com.sponge.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sponge.dao.UserDao;
import com.sponge.entity.User;
@WebServlet("/showServlet")
public class ShowServlet extends HttpServlet { // 顯示全部數據
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AdminDao dao = new AdminDao();
List<User> userList = dao.getAll();
// servlet中存放list集合
req.setAttribute("userList", userList);
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
```
```java
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>顯示</title>
<style type="text/css">
table {
border: 1px solid pink;
margin: 0 auto;
}
td{
width: 150px;
border: 1px solid pink;
text-align: center;
}
</style>
</head>
<body>
<table>
<tr>
<td>編號</td>
<td>帳號</td>
<td>密碼</td>
<td>操作</td>
</tr>
<c:forEach items="${userList}" var="user">
<tr>
<td>${user.id }</td>
<td>${user.username }</td>
<td>${user.userpwd }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
```