# JSP
JSP——Java Server Page:Java服務端頁面,在html頁面中編寫Java代碼的頁面。
絕大多數時候,我們希望響應的不是簡簡單單一句話,而是一個頁面,我們用PrintWriter對象去寫一個頁面也是可以的,但缺點太明顯。
所以直接返回一個頁面,并且能夠寫Java代碼就能大大簡化我們的開發,這就是——JSP。
JSP是簡化Servlet編寫的一種技術,它將Java代碼和HTML語句混合在同一個文件中編寫,只對網頁中的要動態產生的內容采用Java代碼來編寫,而對固定不變的靜態內容采用普通靜態HTML頁面的方式編寫。
***
### 建立對JSP的直觀認識
在JSP頁面中編寫的Java代碼需要嵌套在<%和%>中,嵌套在<%和%>之間的Java代碼被稱之為**腳本片段**(Scriptlets),沒有嵌套在<%和%>之間的內容被稱之為JSP的**模版元素**。
JSP文件就像普通的HTML文件一樣,它們可以放置在WEB應用程序中的除了WEB-INF及其子目錄外的其他任何目錄中,JSP頁面的訪問路徑與普通HTML頁面的訪問路徑形式也完全一樣。
在JSP頁面中也可以使用一種稱之為JSP表達式的元素,只需將要輸出的變量或表達式直接封裝在<%= 和 %>之中,就可以向客戶端輸出這個變量或表達式的運算結果。在JSP表達式中嵌套的變量或表達式后面不能有分號。
WEB容器(Servlet引擎)接收到以.jsp為擴展名的URL的訪問請求時,它將把該訪問請求交給JSP引擎去處理。
每個JSP 頁面在第一次被訪問時,JSP引擎將它翻譯成一個Servlet源程序,接著再把這個Servlet源程序編譯成Servlet的class類文件,然后再由WEB容器(Servlet引擎)像調用普通Servlet程序一樣的方式來裝載和解釋執行這個由JSP頁面翻譯成的Servlet程序——JSP本質上就是一個Servlet。
新建一個jsp頁面hello.jsp
~~~
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
Date date = new Date();
System.out.println(date);
%>
</body>
</html>
~~~
運行可以看到控制臺上有時間輸出。
***
### JSP中9個隱式對象(重點)
隱式對象(或隱含變量):在JSP當中我們沒有手動聲明創建,但實際存在,可以直接使用的對象。
~~~
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
// 還有request和response以及exception對象,一共9個
~~~
①**request**:客戶端的請求信息被封裝在request對象中,通過它才能了解用戶的需求,然后做出響應
②response:包含了響應客戶請求的有關信息,但在JSP中使用很少
③pageContext:頁面的上下文,是PageContext的一個對象,可以從該對象中獲取到其他8個隱含對象,也可以獲取到當前頁面的其他信息
④**session**:指的是客戶端與服務器的一次會話,從客戶端連到服務器的一個WebApplication開始,知道客戶端與服務器斷開連接為止
⑤**application**:代表當前web應用,是ServletContext對象,能實現用戶間數據的共享,可存放全局變量,它開始于服務器的啟動,直到服務器的關閉,在此期間,此對象一直存在;這樣在用戶的前后連接或不同用戶之間的連接中,可以對此對象的同一屬性進行操作;在任何地方對此對象屬性的操作,都將影響到其他用戶對此的訪問。服務器的啟動和關閉決定了application對象的生命周期
⑥config:當前JSP對應的Servlet的ServletConfig對象,可獲取該Servlet的初始化參數(開發時基本不用),需要通過映射的地址才可以。
⑦**out**:JspWriter對象,調用out.println()可以直接把字符串打印到瀏覽器上
⑧page:page對象就是指向當前JSP頁面本身,類型為Object,有點類似于類中的this,幾乎不使用
⑨exception:該對象是一個例外對象,只有頁面是一個錯誤頁面,即isErrorPage設置為true的時候(默認為false)才能使用,否則無法編譯。
#### **注意:JSP可以放置在WEB應用程序中的除了WEB-INF及其子目錄外的其他任何目錄中**
***
### JSP模板元素
JSP頁面中的靜態HTML內容稱之為JSP模版元素(比如html,body等等),在靜態的HTML內容之中可以嵌套JSP的其他各種元素來產生動態內容和執行業務邏輯。
JSP模版元素定義了網頁的基本骨架,即定義了頁面的結構和外觀。
***
### JSP表達式
JSP表達式(expression)提供了將一個java變量或表達式的計算結果輸出到客戶端的簡化方式,它將要輸出的變量或表達式直接封裝在<%= 和 %>之中。
~~~
<body>
<%
Date date = new Date();
%>
<%= date %>
</body>
~~~
***
### JSP腳本片斷
像片段一樣的JSP表達式,但整體必須是完整的
~~~
<body>
<%
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
if(age > 18){
%>
成年....
<% }else{ %>
未成年...
<% } %>
</body>
~~~
***
### JSP注釋
~~~
<%--
<%= new Date() %>
--%>
~~~
~~~
<!--
<%= new Date() %>
-->
~~~
能夠阻止Java代碼運行,html注釋則沒有此功能
***
### 屬性相關方法
①設置屬性:void setAttribute(String name,Object o)
②獲取指定屬性:Object getAttribute(String name)
作為了解
③獲取所有的屬性的名字組成的Enumeration對象:Enumeration getAttributeNames()
④移除指定的屬性:removeAttribute(String name)
#### 域對象
**能夠使用這些方法的對象有4個:
pageContext,request,session,application-->這4個對象也稱為域對象**
新建jsp書寫一下代碼運行測試
~~~
<body>
<%
pageContext.setAttribute("pageAttr", "pageValue");
request.setAttribute("requestAttr", "requestValue");
session.setAttribute("sessionAttr", "sessionValue");
application.setAttribute("applicationAttr", "applicationValue");
%>
<h2>Page1</h2>
pageContextAttr:<%= pageContext.getAttribute("pageAttr") %>
<br><br>
requestAttr:<%= request.getAttribute("requestAttr") %>
<br><br>
sessionAttr:<%= session.getAttribute("sessionAttr") %>
<br><br>
applicationAttr:<%= application.getAttribute("applicationAttr") %>
<br><br>
<a href="attr_2.jsp">to Page 2</a>
</body>
~~~
正常的得到當前jsp的屬性。

點擊超鏈接,跳轉的attr_2.jsp

pageContext:屬性的作用范圍僅限于當前JSP頁面
request:屬性的作用范圍僅限于同一個請求
session:屬性的作用范圍限于一次會話(瀏覽器打開直到關閉,稱為一次會話,前提是在此期間會話沒有失效)
關閉瀏覽器,直接去attr_2.jsp發現

application:屬性的作用范圍限于當前WEB應用,是范圍最大的屬性作用范圍,只要在一處設置屬性,在其他各處的JSP或Servlet中都可以獲取,直到服務器關閉。
但學到這里其實還不能做什么,當有了請求轉發和請求重定向將威力無窮。
***
### **請求轉發和請求重定向(絕對重點)**
#### 一.請求轉發
請求轉發需要借助于一個接口,RequestDispatcher接口 ,利用這個接口的forward方法實現請求轉發。
#### 二.請求重定向
用HttpServletResponse的sendRedirect方法實現請求重定向。
***
請求轉發
~~~
<body>
<a href="forwardServlet">Forward</a>
</body>
~~~
~~~
@WebServlet("/forwardServlet")
public class ForwardServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ForwardServlet's doGet");
// 請求轉發
// 1.調用HttpServletRequest的getRequestDispatcher()方法獲得RequestDispatcher對象
// 調用getRequestDispatcher()需要傳入要轉發的地址(/代表當前WEB應用的根目錄)
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/testServlet");
// 2.調用HttpServletRequest的forward(request,response)進行請求轉發
requestDispatcher.forward(request, response);
}
}
~~~
~~~
@WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("TestServlet's doGet方法");
}
}
~~~
運行html,點擊查看控制臺

***
請求重定向
~~~
<body>
<a href="forwardServlet">Forward</a>
<a href="redirectServlet">Redirect</a>
</body>
~~~
~~~
@WebServlet("/redirectServlet")
public class RedirectServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RedirectServlet's doGet");
response.sendRedirect("testServlet");
}
}
~~~
再次運行html,點擊Redirect,查看控制臺

貌似與請求轉發沒什么區別,但實際區別非常之大。
觀察用請求轉發和請求重定向時地址欄的變化
請求轉發地址欄沒變

請求重定向地址欄變化了

說明一個重要問題(本質區別):
**請求轉發只發出了一個請求
請求重定向發出了連個請求**
#### 驗證:
~~~
@WebServlet("/forwardServlet")
public class ForwardServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ForwardServlet's doGet");
// 設置一個屬性
request.setAttribute("name", "yzn");
// 請求轉發
// 1.調用HttpServletRequest的getRequestDispatcher()方法獲得RequestDispatcher對象
// 調用getRequestDispatcher()需要傳入要轉發的地址(/代表當前WEB應用的根目錄)
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/testServlet");
// 2.調用HttpServletRequest的forward(request,response)進行請求轉發
requestDispatcher.forward(request, response);
}
}
~~~
~~~
@WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object name = request.getAttribute("name");
System.out.println(name);
}
}
~~~
同樣的,使用請求重定向,再次發出請求,發現得不到RedirectServlet中設置的屬性,說明請求不是同一個。
**發現能夠得到在ForwardServlet中設置的屬性,說明請求是同一個請求**
***
~~~
@WebServlet("/redirectServlet")
public class RedirectServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RedirectServlet's doGet");
request.setAttribute("name", "yzn111");
response.sendRedirect("testServlet");
}
}
~~~
***
### 在JSP中也可以實現的請求轉發和重定向,但實際意義不大
***
#### **重要知識點:**
1.POST和GET的區別:
1)Get?是用來從服務器上獲得數據,而Post?是用來向服務器上傳遞數據;
2)Get?將表單中數據按照variable=value?的形式,添加到action?所指向的?URL?后面,并且兩者使用“?”連接,而各個變量之間使用“&”連接;Post?是將?表單中的數據放在form?的數據體中,按照變量和值相對應的方式,傳遞到action?所指向URL;?
3)Get?是不安全的,因為在傳輸過程,數據被放在請求的URL?中;Post?的?所有操作對用戶來說都是不可見的;
4)Get?傳輸的數據量小,這主要是因為受URL?長度限制;而Post?可以傳輸大量的數據,所以在上傳文件只能使用Post;?
2.請求轉發及請求重定向的區別:
①請求轉發實際上是問題的轉發,在跳轉的過程中并沒有響應客戶端,在源和目標之間是可以用request對象進行傳值的;請求重定向在跳轉的過程中實際上是響應了客戶端了,客戶端發送了兩次請求,不能夠使用request進行傳值;
②客戶端可以看到請求重定向目標資源的URL,不能看到請求轉發目標資源的URL;
③請求轉發速度快,請求重定向速度慢;
④請求轉發只能訪問站內資源,而請求重定向可以定位到站外資源(比如 百度);
⑤請求轉發:/代表的是當前WEB應用的根目錄;請求重定向:/代表的是當前WEB站點的根目錄(http://localhost:8080/)
- 第一章 配置和安裝Tomcat
- 第二章 Servlet(一)
- 第三章 Servlet(二)
- 練習 一 . Servlet配置級獲取初始化參數
- 第四章 JSP(一)
- 第五章 JSP(二)
- 第六章 MVC設計模式
- 第七章 Cookie
- 第八章 Session
- 練習 二 . 簡易版購物車
- 第九章 EL表達式
- 第十章 JSTL
- 第十一章 過濾器
- 第十二章 監聽器
- 第十三章 文件的上傳與下載
- 復習總結
- 如何手動啟動Tomcat
- 如何修改Tomcat端口號
- 如何在web.xml中配置Servlet
- Servlet生命周期
- load-on-startup參數
- Servlet映射路徑
- POST和GET的區別
- JSP中9個隱式對象及功能
- 請求轉發及請求重定向的區別
- JSP指令有哪些
- 簡述對MVC設計模式的理解
- 簡述Cookie機制
- 簡述Session機制
- HttpSession的生命周期
- Cookie和Session有什么區別
- 簡述創建過濾器步驟
- 過濾器經典案例--統一編碼字符集
- getParameter與getAttribute的區別
- JSP頁面中可以包含哪些元素
- web應用中,是如何跟蹤用戶的
- InteliJ創建web項目