JSP概述 什麼是 jsp JSP(全稱 Java Server Pages)是由 Sun 公司專門為瞭解決動態生成 HTML 文檔的技術。 Servlet 程式輸出 html 頁面 在 jsp 技術之前,如果我們要往客戶端輸出一個頁面。我們可以使用 Servlet 程式來實現。具體的代碼如下: p ...
目錄
- JSP概述
- jsp 的運行原理
- jsp 的語法
- jsp 九大內置對象
- jsp 四大域對象
- jsp中out輸出流和response.getwriter()輸出流
- jsp 的常用標簽
- Listener 監聽器
- ServletContextListener 監聽器
JSP概述
什麼是 jsp
JSP(全稱 Java Server Pages)是由 Sun 公司專門為瞭解決動態生成 HTML 文檔的技術。
Servlet 程式輸出 html 頁面
在 jsp 技術之前,如果我們要往客戶端輸出一個頁面。我們可以使用 Servlet 程式來實現。具體的代碼如下:
public class HtmlServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 設置返回的數據內容的數據類型和編碼
response.setContentType("text/html; charset=utf-8");
// 獲取字元輸出流
Writer writer = response.getWriter();
//輸出頁面內容
writer.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\"http://www.w3.org/TR/html4/loose.dtd\">");
writer.write("<html>");
writer.write("<head>");
writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
writer.write("<title>Insert title here</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("這是由 Servlet 程式輸出的 html 頁面內容!");
writer.write("</body></html>");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
}
在瀏覽器中輸入訪問 Servlet 的程式地址得到以下結果:
從上面的代碼可以發現。通過 Servlet 輸出簡單的 html 頁面信息都非常不方便。
如果要輸出一個複雜頁面的時候,就更加的困難,而且不利於頁面的維護和調試。
所以 sun 公司推出一種叫做 jsp 的動態頁面技術來實現對頁面的輸出繁鎖工作。
jsp 頁面的訪問不能像 HTML 頁面一樣拖到瀏覽器中。只能通過瀏覽器訪問 Tomcat 伺服器再訪問 jsp 頁面。
如何創建一個 jsp 動態頁面程式
- 選中 Web 目錄,右鍵創建一個 jsp 文件
-
輸入 jsp 頁面的文件名
-
在 body 標簽中添加你想要顯示的文本內容
-
先啟動Tomcat伺服器,
然後在瀏覽器中輸入 jsp 頁面的訪問地址。
jsp 頁面的訪問地址和 html 頁面的訪問路徑一樣 http://ip:埠號/工程名/文件名
也就是 http://127.0.0.1:8080/Test/Demo.jsp 或 http://localhost:8080/Test/Demo.jsp(以自己的工程路徑為準)如何修改 jsp 文件的預設編碼
有些idea的預設編碼格式可能是GBK格式或者其他格式的,然後在JSP編碼時候可能會出現亂碼,修改為UTF-8格式可以避免亂碼。
註意事項:
1、jsp 頁面是一個類似於 html 的一個頁面。 jsp 直接存放到 WebContent 目錄下,和 html 一樣
訪問 jsp 的時候,也和訪問 html 一樣
2、jsp 的預設編碼集是 iso-8859-1 修改 jsp 的預設編碼為 UTF-8
jsp 的運行原理
jsp的本質其實是一個Servlet程式。
首先我們去找到我們 Tomcat 的目錄下的 work\Catalina\localhost 目錄。
當我們新建Demo工程。並啟動 Tomcat
伺服器後。我們發現
在 work\Catalina\localhost 目錄下多出來一個 JSPDemo目錄。
一開始目錄還是空目錄。
然後,我們在瀏覽器輸入一個 jsp 文件的訪問路徑訪問。
比如 http://127.0.0.1:8080/JSPDemo/Demo.jsp訪問Demo.jsp 文件
JSPDemo目錄馬上會生成 org\apache\jsp 目錄。
並且在會中有兩個文件。
Demo_jsp.class 文件很明顯是 index_jsp.java 源文件編譯後的位元組碼文件。
那麼Demo_jsp.java 是個什麼內容呢?
生成的 java 文件名,是以原來的文件名加上_jsp 得到。 xxxx_jsp.java 文件的名字
我們打開 Demo_jsp.java 文件查看裡面的內容:
發現,生成的類繼承於 HttpJspBase 類。這是一個 jsp 文件生成 Servlet 程式要繼承的基類!!!
自動生成的java文件繼承於HttpJspBase類
於是,關聯源代碼去查看一下 HttpJspBase 類的內容。從源碼的類註釋說明中,發現HttpJspBase 這個類就是所有 jsp 文件生成 Servlet 程式需要去繼承的基類。並且這個 HttpJspBase 類繼承於 HttpServlet 類。所以 jsp 也是一個 Servlet 小程式。
我們分別在工程的 Web 目錄下創建多個 jsp 文件。然後依次訪問。它們都被翻譯為.java 文件並編譯成為.class 位元組碼文件
打開 Demo_jsp.java 文件查看裡面的內容可以發現。jsp 中的 html 頁面內容都被翻譯到 Servlet 中的 service
方法中直接輸出。
小結:
從生成的文件我們不難發現一個規則。
a.jsp 翻譯成 java 文件後的全名是 a_jsp.java 文件
b.jsp 翻譯成 java 文件後的全名是 b_jsp.java 文件
麽 那麼 當我們訪問 個 一個 xxx.jsp 文件後 成 翻譯成 java 文件的全名是 xxx_jsp.java 文件
xxx_jsp.java 文件是一個 Servlet 程式。原來 jsp 中的 html 內容都被翻譯到 Servlet 類的 service 方法中原樣輸出。
jsp 的語法
jsp 文件頭部聲明介紹(page 指令介紹)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
這是 jsp 文件的頭聲明。表示這是 jsp 頁面。
屬性 | 含義 |
---|---|
language | 屬性值只能是 java,表示翻譯的得到的是 java 語言的 |
contentType | 設置響應頭 contentType 的內容 |
pageEncoding | 設置當前 jsp 頁面的編碼 |
import | 給當前 jsp 頁面導入需要使用的類包 |
autoFlush | 設置是否自動刷新 out 的緩衝區,預設為 true |
buffer | 設置 out 的緩衝區大小。預設為 8KB |
errorPage | 設置當前 jsp 發生錯誤後,需要跳轉到哪個頁面去顯示錯誤信息 |
isErrorPage | 設置當前 jsp 頁面是否是錯誤頁面。是的話,就可以使用 exception 異常對象 |
session | 設置當前 jsp 頁面是否獲取 session 對象,預設為 true |
extends | 給伺服器廠商預留的 jsp 預設翻譯的 servlet 繼承於什麼類 |
jsp 中的三種腳本介紹
一、聲明腳本:
聲明腳本格式如下:
<%!
java 代碼
%>
在聲明腳本塊中,我們可以乾 4 件事情
1.我們可以定義全局變數。
2.定義 static 靜態代碼塊
3.定義方法
4.定義內部類
幾乎可以寫在類的內部寫的代碼,都可以通過聲明腳本來實現
二、表達式腳本
表達式腳本格式如下:
<%=表達式 %>
表達式腳本 用於向頁面輸出內容。
表達式腳本 翻譯到 Servlet 程式的 service 方法中 以 out.print() 列印輸出
out 是 jsp 的一個內置對象,用於生成 html 的源代碼
註意:表達式不要以分號結尾,否則會報錯
表達式腳本可以輸出任意類型。
比如:
1.輸出整型
2.輸出浮點型
3.輸出字元串
4.輸出對象
三、代碼腳本
代碼腳本如下:
<% java 代碼 %>
代碼腳本里可以書寫任意的 java 語句。
代碼腳本的內容都會被翻譯到 service 方法中。
所以 service 方法中可以寫的 java 代碼,都可以書寫到代碼腳本中
jsp 中的註釋
// 單行 java 註釋
/*
多行 java 代碼註釋
*/
單行註釋和多行註釋能在翻譯後的 java 源代碼中看見。
<%-- jsp 註釋 --%>
jsp 註釋在翻譯的時候會直接被忽略掉
<!-- html 註釋 -->
html 的註釋會被翻譯到 java 代碼中輸出到 html 頁面中查看
jsp 九大內置對象
我們打開翻譯後的 java 文件。查看_jspService 方法。
通過源碼可以發現 jsp 中九大內置對象分別是:
對象 | 含義 |
---|---|
request 對象 | 請求對象,可以獲取請求信息 |
response 對象 | 響應對象。可以設置響應信息 |
pageContext 對象 | 當前頁面上下文對象。可以在當前上下文保存屬性信息 |
session 對象 | 會話對象。可以獲取會話信息 |
exception 對象 | 異常對象只有在 jsp 頁面的 page 指令中設置 isErrorPage="true" 的時候才會存在 |
application 對象 | ServletContext 對象實例,可以獲取整個工程的一些信息 |
config 對象 | ServletConfig 對象實例,可以獲取 Servlet 的配置信息 |
out 對象 | 輸出流 |
page 對象 | 表示當前 Servlet 對象實例(無用,用它不如使用 this 對象) |
九大內置對象 , 都是我們可以在 【 代碼腳本 】 中或 【 表達式腳本 】 中直接使用的對象。
jsp 四大域對象
四大域對象經常用來保存數據信息。
域對象 | 含義 |
---|---|
pageContext | 可以保存數據在同一個 jsp 頁面中使用 |
request | 可以保存數據在同一個 request 對象中使用。經常用於在轉發的時候傳遞數據 |
session | 可以保存在一個會話中使用 |
application(ServletContext) | 就是 ServletContext 對象 |
四個作用域的測試代碼:
新建兩個 jsp 頁面。分別取名叫:context1.jsp
,context2.jsp
context1.jsp 的頁面代碼如下:
<%--
Created by IntelliJ IDEA.
User: Kohler
Date: 2022/8/26
Time: 20:00
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>context1</title>
</head>
<body>
這是 context1 頁面<br/>
<%
//設置 page 域的數據
pageContext.setAttribute("key", "pageContext-value");
//設置 request 域的數據
request.setAttribute("key", "request-value");
//設置 session 域的數據
session.setAttribute("key", "session-value");
//設置 application 域的數據
application.setAttribute("key", "application-value");
%>
<%-- 測試當前頁面作用域 --%>
<%=pageContext.getAttribute("key") %><br/>
<%=request.getAttribute("key") %><br/>
<%=session.getAttribute("key") %><br/>
<%=application.getAttribute("key") %><br/>
<%
// 測試 request 作用域
// request.getRequestDispatcher("/context2.jsp").forward(request, response);
%>
</body>
</html>
context2.jsp 的頁面代碼如下:
<%--
Created by IntelliJ IDEA.
User: Kohler
Date: 2022/8/26
Time: 20:03
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>context2</title>
</head>
<body>
這是 context2 頁面 <br/>
<%=pageContext.getAttribute("key") %><br/>
<%=request.getAttribute("key") %><br/>
<%=session.getAttribute("key") %><br/>
<%=application.getAttribute("key") %><br/>
</body>
</html>
測試 pageContext 作用域:
直接訪問 context1.jsp 文件,結果:
測試 request 作用域:
1.在 context1.jsp 文件中添加轉發到 context2.jsp(有數據)
2.直接訪問 context2.jsp 文件 (沒有數據)
測試 session 作用域:
1.訪問完 context1.jsp 文件
2.關閉瀏覽器。但是要保持伺服器一直開著
3.打開瀏覽器,直接訪問 context2.jsp 文件
測試 application 作用域:
1.訪問完 context1.jsp 文件,然後關閉瀏覽器
2.停止伺服器。再啟動伺服器。
3.打開瀏覽器訪問 context2.jsp 文件
context1.jsp頁面中:
context1頁面的pageContent的值成為null了,因為添加轉發跳轉到了另一個jsp頁面
request還有值是因為,雖然跳轉到了另一個頁面但是這還屬於一次請求。
context1和context2中session還有值是因為當前都是在一個瀏覽器中訪問,換一個瀏覽器的結果:
application一直有值是因為當前tomcat一直在一次運行中,如果重新部署或者重啟伺服器就會變為null
重啟伺服器:
jsp中out輸出流和response.getwriter()輸出流
jsp中out 和response的writer的區別演示
<%--
Created by IntelliJ IDEA.
User: Kohler
Date: 2022/8/26
Time: 20:41
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>output</title>
</head>
<body>
<%
// out 輸出
out.write("這是 out 的第一次輸出<br/>");
// out flush 之後。會把輸出的內容寫入 writer 的緩衝區中
out.flush();
// 最後一次的輸出,由於沒有手動 flush,會在整個頁面輸出到客戶端的時候,自動寫入到 writer 緩衝區
out.write("這是 out 的第二次輸出<br/>");
// writer 的輸出
response.getWriter().write("這是 writer 的第一次輸出<br/>");
response.getWriter().write("這是 writer 的第二次輸出<br/>");
%>
</body>
</html>
在瀏覽器里輸入 http://localhost:8080/JSPDemo/output.jsp運行查看的結果:
out 流和 writer 流的兩個緩衝區如何工作
jsp 的常用標簽
<%-- 靜態包含 --%>
<%-- 動態包含 --%>
<%-- 轉發 --%>
靜態包含--很常用
<%@ include file="" %>
靜態包含是把包含的頁面內容原封裝不動的輸出到包含的位置。
動態包含--很少用
<jsp:include page=""></jsp:include>
動態包含會把包含的 jsp 頁面單獨翻譯成 servlet 文件,然後在執行到時候再調用翻譯的 servlet 程式。並把
計算的結果返回。
動態包含是在執行的時候,才會載入。所以叫動態包含。
頁面轉發--常用
<jsp:forward page=""></jsp:forward>
<jsp:forward 轉發功能相當於
request.getRequestDispatcher("/xxxx.jsp").forward(request, response); 的功能。
靜態包含 | 動態包含 | |
---|---|---|
是否生成 java 文件 | 不生成 | 生成 |
service 方法中的區別 | 把包含的內容原封拷貝到 service 中 | JspRuntimeLibrary.include 方法 |
是否可以傳遞參數 | 不能 | 可以 |
編譯次數 | 1 | 包含的文件 + 1 |
適用範圍 | 適用包含純靜態內容(CSS,HTML,JS),或沒有;非常耗時操作。或大量 java 代碼的 jsp | 包含需要傳遞參數。含有大量 java 代碼,運算,耗時很長的操作。 |
補充:
在工作中,幾乎都是使用靜態包含。理由很簡單。因為 jsp 頁面雖然可以寫 java 代碼,做其他的功能操作。但是由於 jsp 在開發過程中被定位為專門用來展示頁面的技術。也就是說。jsp 頁面中,基本上只有 html,css,js。還有一些簡單的 EL,表達式腳本等輸出語句。所以我們都使用靜態包含。
Listener 監聽器
什麼是 Listener 監聽器
什麼是監聽器?監聽器就是實時監視一些事物狀態的程式,我們稱為監聽器。
就好像朝陽群眾?朝陽區只要有哪個明星有什麼不好的事,他們都會知道,然後舉報。
那麼朝陽群眾就是監聽器,明星就是被監視的事物,舉報就是響應的內容。
又或者說是,電動車的報警器。當報警器鎖上的時候。我們去碰電動車,電動車就會報警。
報警器,就是監聽器,電動車就是被監視的對象。報警就是響應的內容。
ServletContextListener 監聽器
javax.servlet.ServletContextListener ServletContext 監聽器
監聽器的使用步驟。
第一步:我們需要定義一個類。然後去繼承生命周期的監聽器介面。
第二步:然後在 Web.xml 文件中配置。
ServletContextListener 監聽器,一定要在 web.xml 文件中配置之後才會生效
<listener>
<listener-class>全類名</listener-class>
</listener>
生命周期監聽器兩個方法:
public void contextInitialized(ServletContextEvent sce) 是 ServletContext 對象的
創建回調
public void contextDestroyed(ServletContextEvent sce) 是 ServletContext 對象的銷
毀回調
以 ServletContext 的監聽器為例:
創建一個 ServletContextListenerImpl 類實現 ServletContextListener 介面。
package com.kailong.servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ServletContextListenerImpl implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext 對象被創建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext 對象被銷毀了");
}
}
在 web.xml 文件中的配置如下:
<listener>
<listener-class>com.kailong.servlet.ServletContextListenerImpl</listener-class>
</listener>
這個時候,啟動 web 工程和正常停止 web 工程,後臺都會如下列印:
如圖片失效等情況請參閱公眾號文章:https://mp.weixin.qq.com/s/jWej5-yDpj6DZJz_saYZ_Q
歡迎關註公眾號:愚生淺末