6,jsp 中的 out 輸出和 response.getWriter 輸出的區別
什麼是 jsp ,它有什麼用?
-
jsp 的全稱是 java server pages。Java 的服務器頁面。
-
jsp 的主要作用是代替 Servlet 程序回傳 html 頁面的數據。
-
因爲 Servlet 程序回傳 html 頁面數據是一件非常繁鎖的事情。開發成本和維護成本都極高。
-
Servlet 回傳 html 頁面數據的代碼:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通過響應的回傳流回傳 html 頁面數據
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("<!DOCTYPE html>\r\n");
writer.write(" <html lang=\"en\">\r\n");
writer.write(" <head>\r\n");
writer.write(" <meta charset=\"UTF-8\">\r\n");
writer.write(" <title>Title</title>\r\n");
writer.write(" </head>\r\n");
writer.write(" <body>\r\n");
writer.write(" 這是 html 據 頁面數據 \r\n");
writer.write(" </body>\r\n");
writer.write("</html>\r\n");
writer.write("\r\n");
}
- jsp 回傳一個簡單 html 頁面的代碼
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
這是 html 頁面數據
</body>
</html>
-
jsp 如何訪問:
jsp 頁面和 html 頁面一樣,都是存放在 web 目錄下。訪問也跟訪問 html 頁面一樣。
比如:在 web 目錄下有如下的文件:
web 目錄
a.html 頁面 訪問地址是 ====》
http://ip:port/工程路徑/a.html
b.jsp 頁面 訪問地址是 ====》http://ip:port/工程路徑/b.jsp
jsp 的本質是什麼?
-
jsp 頁面本質上是一個 Servlet 程序。
-
當我們第一次訪問 jsp 頁面的時候。Tomcat 服務器會幫我們把 jsp 頁面翻譯成爲一個 java 源文件。並且對它進行編譯成爲.class 字節碼程序。我們打開 java 源文件不難發現其裏面的內容是:
-
HttpJspBase 類。它直接地繼承了 HttpServlet 類。也就是說。jsp 翻譯出來的 java 類,它間接了繼承了 HttpServlet 類。也就是說,翻譯出來的是一個 Servlet 程序
-
總結:通過翻譯的 java 源代碼我們就可以得到結果:jsp 就是 Servlet 程序。
jsp 的三種語法
- jsp 的 page 指令可以修改 jsp 頁面中一些重要的屬性,或者行爲。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
屬性 | 含義 |
---|---|
language | 表示 jsp 翻譯後是什麼語言文件,暫時只支持 java |
contentType | 表示 jsp 返回的數據類型是什麼,也是源碼中 response.setContentType()參數值 |
pageEncoding | 表示當前 jsp 頁面文件本身的字符集 |
import | 跟 java 源代碼中一樣。用於導包,導類 |
autoFlush | 設置當 out 輸出流緩衝區滿了之後,是否自動刷新衝級區。默認值是 true |
pageEncoding | 表示當前 jsp 頁面文件本身的字符集 |
errorPage | 設置當 jsp 頁面運行時出錯,自動跳轉去的錯誤頁面路徑 |
isErrorPage | 設置當前 jsp 頁面是否是錯誤信息頁面。默認是 false。如果是 true 可以獲取異常信息 |
session | 設置訪問當前 jsp 頁面,是否會創建 HttpSession 對象。默認是 true |
extends | 設置 jsp 翻譯出來的 java 類默認繼承誰 |
- 緩衝區溢出錯誤:
-
聲明腳本( 極少使用)
聲明腳本的格式是: <%! 聲明 java 代碼 %>
作用:可以給 jsp 翻譯出來的 java 類定義屬性和方法甚至是靜態代碼塊。內部類等。
- 案例:
<%--1 、聲明類屬性 --%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>
<%--2 、聲明 static 靜態代碼塊 --%>
<%!
static {
map = new HashMap<String,Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
}
%>
<%--3 、聲明類方法 --%>
<%!
public int abc(){
return 12;
}
%>
<%--4 、聲明內部類 --%>
<%!
public static class A {
private Integer id = 12;
private String abc = "abc";
}
%>
-
表達式腳本 (常用)
表達式腳本的格式是:
<%=表達式%>
表達式腳本的作用是:的 jsp 頁面上輸出數據。
-
表達式腳本的特點:
①、所有的表達式腳本都會被翻譯到_jspService() 方法中
②、表達式腳本都會被翻譯成爲 out.print()輸出到頁面上
③、由於表達式腳本翻譯的內容都在_jspService() 方法中,所以_jspService()方法中的對象都可以直接使用。
④、表達式腳本中的表達式不能以分號結束。
-
案例:
-
<%=12 %> <br>
<%=12.12 %> <br>
<%=" 我是字符串" %> <br>
<%=map%> <br>
<%=request.getParameter("username")%>
-
代碼腳本
-
代碼腳本的格式是:
<% java 語句 %>
-
代碼腳本的作用是:可以在 jsp 頁面中,編寫我們自己需要的功能(寫的是 java 語句)
-
代碼腳本的特點是:
①、代碼腳本翻譯之後都在_jspService 方法中
②、代碼腳本由於翻譯到_jspService()方法中,所以在_jspService()方法中的現有對象都可以直接使用。
③、還可以由多個代碼腳本塊組合完成一個完整的 java 語句。
④、代碼腳本還可以和表達式腳本一起組合使用,在 jsp 頁面上輸出數據
-
代碼腳本 for 循環語句案例:
-
<body>
<table border="1" cellspacing="0">
<%
for (int j = 0; j < 10; j++) {
%>
<tr>
<td>第 <%=j + 1%>行</td>
</tr>
<%
}
%>
</table>
</body>
-
html 註釋
html 註釋會被翻譯到 java 源代碼中。在_jspService 方法裏,以 out.writer 輸出到客戶端。
<!-- 這是 html 註釋 -->
-
java 註釋
java 註釋會被翻譯到 java 源代碼中
<%
// 單行 java 註釋
/* 多行 java 註釋 */
%>
-
jsp 註釋
jsp 註釋可以注掉,jsp 頁面中所有代碼
<%-- 這是 jsp 註釋 --%>
jsp 九大內置對象
- jsp 中的內置對象,是指 Tomcat 在翻譯 jsp 頁面成爲 Servlet 源代碼後,內部提供的九大對象,叫內置對象
對象名 | 含義 |
---|---|
request | 請求對象 |
response | 響應對象 |
pageContext | jsp的上下文對象 |
session | 會話對象 |
application | ServletContext對象 |
config | ServletConfig對象 |
out | jsp輸出流對象 |
page | 指向當前jsp的對象 |
exception | 異常對象 |
jsp 四大域對象
域對象名 | 含義 |
---|---|
pageContext (PageContextImpl 類) | 當前 jsp 頁面範圍內有效 |
request (HttpServletRequest 類) | 一次請求內有效 |
session (HttpSession 類) | 一個會話範圍內有效(打開瀏覽器訪問服務器,直到關閉瀏覽器) |
application (ServletContext 類) | 整個 web 工程範圍內都有效(只要 web 工程不停止,數據都在) |
-
域對象是可以像 Map 一樣存取數據的對象。四個域對象功能一樣。不同的是它們對數據的存取範圍,四個域在使用的時候,優先順序分別是,他們從小到大的範圍的順序:
pageContext ====>>> request ====>>> session ====>>> application
-
案例:
index.jsp 頁面
<body>
<h1>index.jsp 頁面</h1>
<%
// 往四個域中都分別保存了數據
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
pageContext 域是否有值:<%=pageContext.getAttribute("key")%> <br>
request 域是否有值:<%=request.getAttribute("key")%> <br>
session 域是否有值:<%=session.getAttribute("key")%> <br>
application 域是否有值:<%=application.getAttribute("key")%> <br>
<%
request.getRequestDispatcher("/resp.jsp").forward(request,response);
%>
</body>
resp.jsp 頁面
<body>
<h1>resp.jsp 頁面</h1>
pageContext 域是否有值:<%=pageContext.getAttribute("key")%> <br>
request 域是否有值:<%=request.getAttribute("key")%> <br>
session 域是否有值:<%=session.getAttribute("key")%> <br>
application 域是否有值:<%=application.getAttribute("key")%> <br>
</body>
jsp 中的 out 輸出和 response.getWriter 輸出的區別
-
response 中表示響應,我們經常用於設置返回給客戶端的內容(輸出)
-
out 也是給用戶做輸出使用的。
-
當jsp頁面中所有代碼執行完成後會做以下兩個操作:
①,執行out.flush()操作,會把out緩衝區中的數據追加寫入到response緩衝區末尾
②,會執行response的刷新操作。把全部數據寫給客戶端
-
由於 jsp 翻譯之後,底層源代碼都是使用 out 來進行輸出,所以一般情況下。我們在 jsp 頁面中統一使用 out 來進行輸出。避免打亂頁面輸出內容的順序。
out.write() 輸出字符串沒有問題
out.print() 輸出任意數據都沒有問題(都轉換成爲字符串後調用的 write 輸出)
jsp 的常用標籤
-
<%@ include file=""%>
就是靜態包含file 屬性指定你要包含的 jsp 頁面的路徑地址中第一個斜槓 / 表示爲 http://ip:port/ 工程路徑 / 映射到代碼的 web 目錄 -
靜態包含的特點:
① 、靜態包含不會翻譯被包含的 jsp 頁面。
② 、靜態包含其實是把被包含的 jsp 頁面的代碼拷貝到包含的位置執行輸出。
-
示例
<%@ include file="/include/footer.jsp"%>
-
<jsp:include page=""></jsp:include>
這是動態包含,page 屬性是指定你要包含的 jsp 頁面的路徑動態包含也可以像靜態包含一樣。把被包含的內容執行輸出到包含位置 -
動態包含的特點:
①、動態包含會把包含的 jsp 頁面也翻譯成爲 java 代碼
②、動態包含底層代碼使用如下代碼去調用被包含的 jsp 頁面執行輸出。
JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
③ 、動態包含,還可以傳遞參數
-
示例說明:
<jsp:include page="/include/footer.jsp">
<jsp:param name="username" value="bbj"/>
<jsp:param name="password" value="root"/>
</jsp:include>
- 動態包含的底層原理:
-
<jsp:forward page=""></jsp:forward>
是請求轉發標籤,它的功能就是請求轉發page 屬性設置請求轉發的路徑 -
示例說明:
<jsp:forward page="/scope.jsp"></jsp:forward>
jsp 的練習題
<style type="text/css">
table{
width: 650px;
}
</style>
</head>
<body>
<h1 align="center">九九乘法口訣表</h1>
<table align="center">
<%-- 外層循環遍歷行 --%>
<% for (int i = 1; i <= 9; i++) { %>
<tr>
<%-- 內層循環遍歷單元格 --%>
<% for (int j = 1; j <= i ; j++) { %>
<td><%=j + "x" + i + "=" + (i*j)%></td>
<% } %>
</tr>
<% } %>
</table>
</body>
- 思路
- Student 類:
public class Student {
private Integer id;
private String name;
private Integer age;
private String phone;
}
- SearchStudentServlet 程序:
/**
* @author Tommey周
* @create 2020-05-25 9:24
*/
public class SearchStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取請求的參數,發 sql 語句查詢學生的信息,使用 for 循環生成查詢到的數據做模擬
List<Student> studentList = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
int t = i + 1;
studentList.add(new Student(t,"name"+t,18+t,"phone"+t));
}
// 保存查詢到的結果(學生信息)到 request 域中
req.setAttribute("stuList", studentList);
// 請求轉發到 showStudent.jsp 頁面
req.getRequestDispatcher("/showStudent.jsp").forward(req,resp);
}
}
- showStudent.jsp 頁面:
<style>
table{
border: 1px blue solid;
width: 600px;
border-collapse: collapse;
}
td,th{
border: 1px blue solid;
}
</style>
</head>
<body>
<%
List<Student> studentList = (List<Student>) request.getAttribute("stuList");
%>
<table>
<tr>
<td>編號</td>
<td>姓名</td>
<td>年齡</td>
<td>電話</td>
<td>操作</td>
</tr>
<% for (Student student : studentList) { %>
<tr>
<td><%=student.getId()%></td>
<td><%=student.getName()%></td>
<td><%=student.getAge()%></td>
<td><%=student.getPhone()%></td>
<td>刪除、修改</td>
</tr>
<% } %>
</table>
</body>
</html>
Listener 監聽器
①、Listener 監聽器它是 JavaWeb 的三大組件之一。JavaWeb 的三大組件分別是:Servlet 程序、Filter 過濾器、Listener 監聽器。
②、Listener 它是 JavaEE 的規範,就是接口。
③、監聽器的作用是,監聽某種事物的變化。然後通過回調函數,反饋給客戶(程序)去做一些相應的處理。
-
ServletContextListener 它可以監聽 ServletContext 對象的創建和銷燬。
-
ServletContext 對象在 web 工程啓動的時候創建,在 web 工程停止的時候銷燬。
-
監聽到創建和銷燬之後都會分別調用 ServletContextListener 監聽器的方法反饋
-
兩個方法分別是:
public interface ServletContextListener extends EventListener {
/**
* 在 ServletContext 對象創建之後馬上調用,做初始化
*/
void contextInitialized(ServletContextEvent sce);
/**
* 在 ServletContext 對象銷燬之後調用
*/
void contextDestroyed(ServletContextEvent sce);
}
-
如何使用 ServletContextListener 監聽器監聽 ServletContext 對象?
使用步驟如下:1、編寫一個類去實現 ServletContextListener
2、實現其兩個回調方法
3、到 web.xml 中去配置監聽器
-
監聽器實現類:
public class MyServletContextListenerImpl implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContextEvent對象被創建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContextEvent對象被銷燬了");
}
}
- web.xml 中的配置:
<!-- 配置監聽器 -->
<listener>
<listener-class>com.MyServletContextListenerImpl</listener-class>
</listener>