RabbitMq常見的面試題
阿新 • • 發佈:2020-09-03
javaWEB
2020/9/3 17:21:44
伺服器搭建
tomcat獨立環境 安裝 前置條件: 1. 環境變數中, 配置JAVA_HOME變數, 變數值為: JDK安裝的路徑, 切記不包含\bin 2. 關閉防火牆, 解除安裝防毒軟體 解除安裝**安全管家 , 解除安裝 *60安全衛士 步驟: 1. 下載tomcat (官網- http://tomcat.apache.org/ )(下載tomcat85) 2. 解壓到任意英文目錄下 . 3. 使用管理員身份, 進入dos命令列 4. 在dos命令列中, 進入tomcat解壓目錄/bin 5. 輸入安裝指令並回車 service install 6. 觀察安裝成功的提示資訊: the service 'tomcat8' has been installed; 執行tomcat , 通過網址訪問 前置條件: tomcat預設埠號為 8080 , 將其修改為 8090 1. 找到tomcat\conf\server.xml 2. 在service.xml 大概70行的位置, 將8080更改為8090 1. 開啟tomcat\bin\tomcat8w.exe 2. 點選start啟動伺服器 3. 在瀏覽器中, 通過ip:8090 來訪問網站
解除安裝tomcat:
方式1. 通過tomcat自身service命令 完成解除安裝
1. 管理員身份, dos命令列進入tomcat\bin
2. 執行解除安裝指令: service remove
方式2. 通過windows指令, 刪除服務
1. 管理員身份, dos命令列輸入: sc delete 服務名
HTTP協議
超文字傳輸協議 , 是一個應用層的網路傳輸協議 . 屬於TCP/IP協議集中的一個子協議. 特點: 1. 簡單 , 快速 2. 無連線協議 , 每次連線伺服器只處理一次客戶端的請求, 處理完畢, 立即斷開. 3. 無狀態協議 , 處理請求時 , 以及給客戶端回覆時. 沒有記憶能力 . 4. 支援多種不同的資料提交方式, GET/POST等等 5. 資料傳輸靈活, 支援任意資料型別.
HTTP協議的組成部分
由兩部分組成 1. 請求 請求由四部分組成: 1. 請求頭 request header 請求的頭部資訊 , 由一個個的鍵值對組成, 這些鍵值對描述的是客戶端的資訊. 2. 請求體 GET請求不存在請求體 ,將請求的引數儲存在網址中 POST請求請求體的作用: 用於儲存客戶端請求的資料 3. 請求空行 請求頭部與請求體之間的一行空白行 4. 請求行 由一個個的鍵值對組成, 這些鍵值對描述的是 請求的方式 ,訪問的網址, 以及http協議的版本. 2. 響應 響應由三部分組成: 1. 響應頭 響應頭部的資訊, 由一個個的鍵值對組成, 這些鍵值對描述的是伺服器的資訊. 2. 響應體 一個單獨的資料報, 是伺服器給客戶端回覆的主要內容. 3. 響應行 由一個個的鍵值對組成, 這些鍵值對描述的是 : 響應的狀態碼, 以及響應成功與失敗的提示 常見的響應狀態碼: 200 : 成功 404 : 資源不存在 500 : 伺服器內部錯誤, (當程式出現異常時)
動態網頁技術
網頁會根據資料的不同, 展示不同的效果.
HttpServlet類
簡介:
是JavaWeb體系中 三大元件之一.
本質上, 就是一個執行在tomcat中的java類,
作用是:可以用來處理客戶端的請求, 以及對客戶端進行響應.
實現步驟:
1. 編寫一個類 , 繼承自HttpServlet類
2. 重寫父類的service(HttpServletRequest request,HttpServletResponse response)
3. 在service方法中, 準備響應體.
將HttpServlet 對映到網址上 *****
web3.0版本之前:
步驟:
1. 通過eclipse的javaEE 工具, 建立web.xml (在3.0之前的專案建立時, web.xml預設是存在的)
2. 向web.xml的根節點, 加入子節點:
將Java類配置到tomcat中.
<servlet>
<servlet-name>給servlet起別名</servlet-name>
<servlet-class>servlet的包名.類名</servlet-class>
</servlet>
給tomcat中的某個類, 新增網址
<servlet-mapping>
<serlvet-name>要新增網址的別名</servlet-name>
<url-pattern>/對映網址</url-pattern>
</servlet-mapping>
注意:
如果對映網址為: /demo1
則瀏覽器訪問時: http://ip地址:埠號/專案名稱/demo1
案例:
Java:
public class Servlet1 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 設定響應內容的編碼格式, 以及內容型別
response.setContentType("text/html;charset=utf-8");
//2. 通過響應物件, 得到用於準備響應體的列印流
PrintWriter out = response.getWriter();
//3. 列印內容
out.println("<h1>Hello JavaWeb</h1>");
}
}
web.xml
<servlet>
<servlet-name>haha</servlet-name>
<servlet-class>cn.xdl.demo1.Servlet1</servlet-class>
</servlet>
<!-- 給tomcat中的某個類, 新增網址 -->
<servlet-mapping>
<servlet-name>haha</servlet-name>
<url-pattern>/s1</url-pattern>
</servlet-mapping>
web3.0版本 和 3.0版本之後:
通過註解來完成對映網址的配置 :
案例:
@WebServlet("/s2")
public class Servlet2 extends HttpServlet {
/**
* service方法, 表示服務方法
* 當用戶每次請求對應的網址時 , 此方法自動執行.
* 方法中的引數:
* 引數1. HttpServletRequest http協議中請求部分由tomcat進行了封裝, 封裝為了此物件, 物件中包含的是請求的相關資訊.
* 引數2. HttpServletResponse
* http協議存在響應部分, 而響應的內容, 是由我們的程式碼所生成的 ,
* 而HttpServletResponse , 它就是tomcat為了方便我們進行響應, 將響應的操作 ,封裝為了這個物件.
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 設定內容的型別 以及 編碼
response.setContentType("text/html;charset=utf-8");
//2. 通過響應物件 得到向響應體輸出的流
PrintWriter out = response.getWriter();
//3. 通過列印流, 向響應體中列印內容
out
.append("<html>")
.append("<head><title>Servlet準備的網頁內容</title></head>")
.append("<body>")
.append("<h1>示例標題</h1>");
for (int i = 0; i < 100; i++) {
out.append("<div>嘿嘿嘿"+i+"</div>");
}
out
.append("</body>")
.append("</html>")
;
//4. 當此方法執行完畢後, 則tomcat認為 響應體準備完畢, 會將內容響應給客戶端.
}
servlet的生命週期
指的是 Servlet從建立到消亡的週期
Servlet的建立時機:
預設情況下, 當用戶第一次訪問Servlet的對映地址時, Servlet的物件被建立。
Serlvet的銷燬時機:
當tomcat關閉, 或 應用被解除安裝時, Servlet被銷燬
(當tomcat關閉後 或 應用被解除安裝後, 使用者無法再訪問Servlet , 我們Servlet也就不需要在記憶體中存在了, 所以此時被銷燬)
tocmat為了方便我們 進行資源的快取 ,
為了讓我們能在Servlet建立時, 初始化一些重複利用的資源,
為了讓我們能在Servlet銷燬時, 釋放這些重複利用的資源,
提供了生命週期對應的方法 :
1. init 方法: 當Servlet被建立時, 此方法執行,用於告知程式設計師, 第一次訪問產生了. 我們可以在此方法中初始化後續重複利用的資源.
2. service 方法: 服務方法, 當用戶每一次訪問時, 都會執行, 用於處理使用者的請求, 以及對使用者進行響應.
3. destroy 方法: 當servlet即將被銷燬時 , tomcat會呼叫此方法, 告知程式設計師. 我們可以在此方法中釋放初始化的那些重複利用的資源.
調整Servlet物件的建立時機 (可以理解為: 懶漢變餓漢)
使用web.xml的配置方式:
在servlet節點中, 加入子節點: load-on-startup 來調整啟動時機
格式:
<serlvet>
<servlet-name></..
<servlet-class>></...
<load-on-startup>整型數字</load-on-startup>
</servlet>
load-on-startup:
取值為數字 , 預設值為-1:
當值為負數時: 第一次請求時載入.
當值≥0時 , 含義是: 伺服器啟動時 , 就載入servlet.
多個servlet之間值越小 越早載入. 值相同按照web.xml中自上而下的配置順序載入
ServletConfig
是Servlet的配置物件, 每一個Servlet都擁有一個配置物件.
我們在web.xml中, 進行servlet的配置時 , 可以向Servlet中新增初始化的引數
這些引數, 會被儲存到一個ServletConfig 物件中.
web.xml中配置的格式:
<servlet>
...
...
<!-- servlet節點中, 可以編寫n個init-param節點, 每一個init-param節點都表示一個鍵值對. -->
<init-param>
<param-name>鍵</param-name>
<param-value>值</param-value>
</init-param>
</servlet>
從servlet中得到SerlvetConfig物件的格式:
在Servlet類中, 可以通過兩種方式, 來獲取配置物件 , 這兩種方式在使用中, 是互斥的.
方式1.
生命週期init方法中, 儲存ServletConfig 引數. 在方法中使用引數即可.
方式2.
在Servlet的任意程式碼位置, 通過getServletConfig()方法得到物件
從servletConfig物件中, 根據鍵得到值的格式:
String value = config物件.getInitParameter(String name);
GET請求 與 POST請求的區別
GET請求:
- 請求的引數 以多個鍵值對的形式儲存在網址中, 在網址的?後 , 鍵與值鍵值使用等號連線, 多個鍵值對之間&分割
- 只能闡述字串型別的引數
- 網址的最大長度為4kb , 通常支援的文字數量是: 最大2048
- 資料傳輸的時 不安全
POST請求:
- 請求的引數 以多個鍵值對的形式儲存在單獨的資料包中 , 這個資料包叫做請求體.
- 請求體中可以包含任意型別的資料, 例如: 圖片 . 音訊 等..
- 資料大小, 理論上是無上限的.
- 因為請求體是單獨的資料包, 所以較GET請求而言 安全;
什麼樣的請求 是 GET
以我們目前掌握的技術來說, 只有表單提交時method=POST , 請求方式是POST. 其他方式都是GET:
- 瀏覽器輸入網址 , 回車
- 點選超連結訪問
- 表單提交時, method=GET
- 通過js: wondow.location物件, 進行替換與跳轉
- ajax的get請求
什麼樣的請求 是 POST
- 表單提交時method=POST
- ajax的post請求
如何接受請求的引數:
1. 根據一個name , 接收單個引數
String value = request.getParameter(String name);
2. 根據一個name , 接收一組引數
String[] values = request.getParameterValues(String name);
上述的兩個方法在獲取資料時, name不存在, 則獲取的結果為null
請求亂碼的問題解決:
解決亂碼問題的兩種方式:
方式1.
適用於tomcat8版本之前的GET請求亂碼解決, 以及所有版本的POST亂碼解決:
解決亂碼的原理:
將文字亂碼的流程, 倒序執行一遍,得到正確的文字.
倒序:
1. 將亂碼的文字,按照ISO-8859-1轉換為位元組陣列
2. 將位元組陣列按照UTF-8的編碼轉換為文字
格式:
//1. 將亂碼的文字,按照ISO-8859-1轉換為位元組陣列
byte[] bytes = 亂碼文字.getBytes("ISO-8859-1");
//2. 將位元組陣列按照UTF-8的編碼轉換為文字
String text = new String(bytes,"UTF-8");
方式2.
適用於tomcat所有版本的post亂碼的解決.
解決亂碼的原理:
在使用請求體之前, 將請求體的預設編碼更改為utf-8.
格式:
//設定請求體的編碼, 一定要寫在獲取引數之前.
request.setCharacterEncoding("UTF-8");
Servlet執行緒安全問題
Servlet的service方法, 在使用者每次請求時呼叫.
service方法的呼叫比較特殊:
service方法的執行, 每一次都是在新的執行緒中.
因為service方法, 執行在新執行緒中, 有可能同時存在多個執行緒. 多執行緒操作時, 有可能發生執行緒安全問題.1
1. 靜態的同步方法的 同步鎖 --> 類.class 這個物件
2. 非靜態的同步方法的 同步鎖 --> this物件
3. 同步程式碼塊的 同步鎖 --> 程式設計師使用時 提供.
案例:
@WebServlet("/s1.do")
public class Servlet1 extends HttpServlet {
//餘票
private int count = 10;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
synchronized(this) {
if(count>0) {
//有票
System.out.println("有票, 正在出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count--;
System.out.println("出票完成, 餘票:"+count);
}else {
System.out.println("很遺憾 ,沒有餘票了");
}
}
response.getWriter().append("ok");
}
}
請求的轉發
概念: 將一個web元件 為處理完畢的請求, 通過tomcat轉交給另一個web元件處理.
步驟:
1. 獲取請求轉發器
RequestDispatcher rd = request.getRequestDispatcher("轉發的地址");
2. 通過轉發器 發起轉發
rd.forward(請求物件 , 響應物件);
簡寫步驟:
request.getRequestDispatcher("轉發的地址").forward(請求物件 , 響應物件);
原理(tomcat內部執行流程):
1. 當瀏覽器訪問伺服器中的tomcat時.
2. tomcat將協議中的請求進行封裝, 封裝為HttpServletRequest物件 , 將響應封裝到HttpServletResponse物件中
3. 找到對應對映地址的Servlet , (第一次尋找會建立物件) , 呼叫物件的service方法, 傳入請求與響應物件.
4. 在serlvet中, 我們可以控制將請求轉發到另一個地址 ,
5. tomcat接收到請求轉發指令後, 將原請求物件 和 新的響應物件傳給轉發的新地址.
6. 此時舊的響應物件就失效了, 無法在進行響應了. 由新的地址的響應物件 負責給使用者進行響應.
7. 新地址準備完畢響應體, 傳送給瀏覽器
特點:
1. 轉發的過程中, 只發生了一次請求, 多個Servlet之間共享一份請求資訊.
2. 轉發無法跨域實現 ( 無法跨網站進行轉發, 例如: 京東無法轉發給淘寶.)
3. 無論轉發過程中, 觸發了多少個web元件 , 對於瀏覽器而言, 它能感知到的 只是發起了一次請求, 接收到了一次響應.
4. 轉發過程中, 瀏覽器地址不會發生改變
5. 相較於重定向而言, 效率高.
請求的重定向
概念: 在進行響應時, 告知瀏覽器新的請求地址, 瀏覽器接到後,自動發起新的請求找指定的地址.
步驟:
response.sendRedirect("重定向的新地址");
原理(執行流程):
1. 當瀏覽器請求某個Servlet時.
2. Servlet對瀏覽器響應一個302的狀態碼 , 以及一個 鍵為location的值, 這個值表示新的地址;
3. 當瀏覽器接收到302的狀態碼以後, 會自動尋找lcoation的值, 併網頁自動跳轉到location的值表示地址上 !
特點:
1. 重定向會產生新的請求 和 新的響應.
2. 使用重定向, 可以跨域實現 (可以跨網站操作 ,例如: 京東可以將請求重定向到淘寶)
3. 瀏覽器地址會發生改變 , 顯示的是重定向的地址;
4. 相較於請求轉發而言, 效率較低.
注意:
1. 在使用者的一次訪問過程中, 我們可以進行無限次的轉發/重定向 ! 但是記住一點: 在多次轉發/重定向的操作中, 一定要有出口 !
2. 不只是可以將請求轉發/重定向到servlet上, 任何的web資源都可以接受轉發 和 重定向.
3. 當我們的程式碼進行了轉發/重定向時 , 相當於將響應的操作交給了其他資源. 那麼在進行轉發和重定向的程式碼後面, 就不要再編寫響應的操作了. 因為無效.
HttpServletRequest 類的常用操作
1. 獲取客戶端的ip地址:
String ip = request.getRemoteAddr();
2. 獲取客戶端訪問的地址:
String url = reuqest.getRequestURI();
3. 獲取tomcat執行的ip地址
String ip = request.getServerName();
4. 獲取tomcat執行的埠號
String port = request.getServerPort();
5. 獲取請求方式
String method = request.getMethod();
6. 獲取get請求的?後的引數列表
String params = request.getQueryString();
HttpServletResponse 類的常用操作
1. 設定響應的內容型別(網頁) 以及 編碼格式(UTF-8)
response.setContentType("text/html;charset=utf-8");
2. 設定響應的內容編碼格式 (常用於響應JSON資料)
response.setCharacterEncoding("UTF-8");
3. 響應錯誤碼給客戶端
response.sendError(int status,String msg);
ServletContext 物件 (Servlet上下文)
每一個Servlet都是一個獨立的網頁地址 , 它們之間無法進行通訊以及交流 ,
例如: 我們想統計網站的訪問次數 , 每一個servlet只能統計自己被訪問的次數, 無法彙總.
Servlet上下文物件, 就是用於Servlet之間資訊共享的, 是多個servlet之間通訊的橋樑
Servelt上下文物件, 在專案的執行過程中, 只有一個.每一個Servlet獲取的上下文物件, 都是同一份.
Servlet上下文物件, 就像一個Map集合, 可以儲存n個鍵值對資訊!
如何得到專案的Servlet上下文物件
格式:
ServletContext context = getServletContext();
上下文物件常用方法 熟悉
1. 儲存資料
context.setAttribute(String name,Object value);
2. 獲取資料
Object value = context.getAttribute(String name);
3. 刪除資料
context.removeAttribute(String name);
4. 獲取專案執行時的資料夾 絕對路徑.
String path = context.getRealPath("/");
會話跟蹤技術 (狀態管理)
Http協議是無狀態的 , 沒有記憶能力.
在瀏覽器與伺服器互動時, 因為無狀態的特性, 會導致無法連貫的互動.
HTTP協議實現狀態管理, 有兩種方式:
1. Cookie技術 : 將互動時產生的狀態 儲存在客戶端中.
2. Session技術 : 將互動時產生的狀態 儲存在伺服器中.
Cookie技術
技術步驟, 以及原理:
1. 當伺服器向客戶端響應時, 可以向響應頭中加入Cookie , 每一個Cookie表示一個鍵值對
2. 當瀏覽器接收到響應頭中的Cookie後, 會將其儲存在本地的一個文字檔案中,
3. 當瀏覽器再次訪問相同的伺服器時, 會去文字檔案中尋找這個伺服器之前儲存的Cookie
4. 將尋找到的Cookie 攜帶到請求頭中, 傳送給伺服器.
如何建立一個Cookie
Cookie 在Java程式中的體現 是一個表示鍵值對的 Java類. 類名為Cookie
格式:
Cookie cookie = new Cookie(String name,String value);
如何將建立的Cookie 新增到響應的頭部
通過響應物件, 將Cookie 新增到響應的頭部
格式:
response.addCookie(Cookie cookie);
一次響應, 可以新增0-n個Cookie ,
瀏覽器接收後, 會儲存到文字檔案中 , 如果相同域的相同路徑 儲存相同鍵的Cookie , 會導致舊值被覆蓋.
如何從請求頭部 得到 我們之前儲存的多個Cookie
可以從請求物件中, 得到之前儲存的Cookie資訊, 得到的是一個Cookie陣列 , 如果從未儲存過Cookie ,則得到的資料是null
格式:
Cookie[] cookies = request.getCookies();
如何調整Cookie的存活時長
cookie.setMaxAge(int 秒);
傳入的值:
- 負數 : 預設值為-1, 負數表示瀏覽會話結束時 刪除. (指的是瀏覽器關閉)
- 正數 : 存活的秒數
- 0 : 存活的秒數, 通常使用者覆蓋一個Cookie ,來完成刪除操作.
Cookie儲存時的路徑問題
因為Cookie傳送時, 需要匹配域 和路徑 .
我們在編寫專案時, 經常因為路徑不同, 導致cookie無法讀取.
Java為我們提供了設定Cookie路徑的方法, 我們可以在任意的servlet中, 將Cookie路徑設定為一致, 來儲存和讀取.
格式:
在cookie新增到響應頭部之前 設定:
cookie.setPath("/");
Cookie技術的優缺點:
缺點:
1. Cookie儲存的資料型別有限制, 只能儲存字串 ( 早期無法儲存中文 )
2. 資料儲存的大小有限制, 不能超過4kb (4096個位元組)
3. 資料儲存在使用者的計算機的 文字檔案中 , 不安全, 有可能被惡意程式讀取.
4. 受限於使用者的瀏覽器設定, 當瀏覽器禁用Cookie時, cookie就無法使用了.
優點:
資料儲存在客戶端中, 分散了伺服器的壓力.
Session技術
技術步驟, 以及原理
1. 瀏覽器訪問伺服器時, 伺服器可以主動建立Session物件 , 一個session表示一個鍵值對的容器 ,類似Map集合
2. 每一個Session建立時, 會產生一個id , 這個id會儲存到一個Cookie中, 併發送給瀏覽器
3. 等瀏覽器下一次訪問時, 會攜帶Cookie, cookie中包含session的id ,
4. 我們就可以根據得到的sessionid , 從伺服器中尋找到屬於這個瀏覽器的session物件.
如何獲取session物件
格式1. ****
呼叫請求的獲取session的方法 (無參) , 方法的內部呼叫了一參方法, 傳入了true
HttpSession session = request.getSession();
格式2.
呼叫請求的獲取session的方法 (一參)
HttpSession session = request.getSession(boolean isNew);
引數的含義:
true: 根據瀏覽器發來的sessionid 尋找session物件並返回, 如果不存在 ,則建立新的並返回
false: 根據瀏覽器發來的sessionid 尋找session物件並返回, 如果不存在 ,則返回null
session的常用方法
1. 儲存資料
session.setAttribute(String name,Object value);
2. 取出資料
Object value = session.getAttribute(String name);
3. 刪除資料
session.removeAttribute(String name);
4. 銷燬這個Session
session.invalidate();
session的存活時長
session的預設存活時長為30分鐘,
當用戶的上一次訪問 距離現在已經超過30分鐘時, session會自動銷燬.
設定session的儲存時長:
方式1. 修改單個session的時長:
session.setMaxInactiveInterval(int 秒);
方式2. 修改tomcat下, 所有session的預設時長
獨立環境: 找到conf/web.xml檔案
開發環境: 找到servers/web.xml
修改其中的session-config節點
案例:
<session-config>
<session-timeout>數值分鐘</session-timeout>
</session-config>
session的優缺點
優點:
1. 資料儲存在伺服器中, 安全
2. session中可以儲存任意型別資料
3. 儲存的資料大小, 理論上是無限制的.
缺點:
資料儲存在伺服器中, 大量的使用者儲存session時, 會對伺服器造成極大的壓力, 極易導致伺服器資源耗盡.
Cookie技術 和 Session技術 不是互斥的.
Cookie和session 我們是結合使用的.
對於安全無要求的字串資料, 儲存在cookie中
對於安全敏感的資料, 儲存在session中
對於安全敏感 , 且較大資料, 儲存在資料庫中...
JSP簡介
Java Server Pages Java的動態網頁技術
JSP引擎
引擎原理:
JSP引擎用於將JSP檔案, 轉換為Servlet
原理步驟:
1. 在伺服器啟動時, JSP引擎讀取JSP檔案
2. 將檔案轉換為Servlet , 並給Servlet新增對映地址為 原JSP 檔名稱.
3. 當用戶訪問 xxxx.jsp時, 請求的不是jsp檔案, 而是JSP引擎根據檔案轉換的Servlet
JSP語法結構 *
JSP檔案儲存在 .jsp檔案中 . 儲存的路徑: webContent目錄下.
JSP語法存在三大語法結構:
1. HTML程式碼
2. Java程式碼
3. JSP特有的一些語法結構.
Java程式碼宣告區
指的是 Java類的成員位置 , 在JSP檔案中的Java程式碼宣告區中編寫的Java程式碼, 會原封不動的生成到Servlet的成員位置!
語法格式:
<%!
編寫宣告區的Java程式碼
%>
Java程式碼執行區
指的是Servlet的service方法. 用於每次請求都會執行
語法格式:
<%
編寫Java邏輯程式碼, 生成到service方法中
%>
輸出表達式
用於快速的將Java程式碼中的變數, 輸出到網頁中
語法格式:
<%=變數名 %>
上述語法格式中的值, 其實是被生成到了out的print方法中,
例如: <%=count %>
生成的Servlet: out.print(count);
JSP中的註釋:
因為JSP包含了三種語法結構.
所以三種結構的註釋, 都可以使用.
HTML註釋:
語法: <!-- 註釋 -->
注意: 在JSP中, 只能編寫在HTML程式碼的位置 ,只能用於註釋HTML部分.
編寫的HTML註釋會被JSP引擎認為是HTML程式碼 , 轉換為: out.write("<!-- 註釋 -->");
Java註釋:
語法: //單行 /*多行*/ /**文件*/
注意: 在JSP中, 只能編寫在Java程式碼的位置, 只能用於註釋Java部分.
編寫Java註釋會被JSP引擎認為是Java程式碼, 原封不動的轉換到Servlet中
JSP註釋:
語法: <%-- JSP的註釋 --%>
注意: 指的是JSP檔案的註釋, 被JSP註釋的內容, 在JSP引擎轉換時期被忽略.
JSP三大指令
指令的格式:
<%@ 指令名稱 屬性名1=值 屬性名2=值 ... 屬性名n=值 %>
page指令
完整格式:
<%@ page
language="java"
contentType="text/html;charset=utf-8"
pageEncoding="UTF-8"
extends="繼承的類"
buffer="數字|none" -- 是否允許快取, 以及允許快取的大小. 預設快取, 大小為8kb
autoFlush="true|false" -- 緩衝器是否自動清除, 預設為true
session="true|false" -- 是否在service方法中, 提前建立好session , 預設true
isThreadSafe="true|false" -- service方法是否是執行緒安全的. 預設false
errorPage="網址" -- 當JSP中的程式碼出異常時, 頁面自動跳轉到網址 ,通常用語提示BUG. **
isErrorPage="true|false" -- 用於處理錯誤的頁面 , 通常isErrorPage=true的頁面, 會被其他頁面通過errorPage引入. **
-- 為true時, 會在service中提前準備好, 異常物件 exception
import="導包列表" -- 屬性值是導包的內容, 多個包之間使用逗號隔開 **
%>
指定專案全域性錯誤碼的 處理頁面 *
步驟:
1. 先開啟專案的 web.xml檔案
2. 在根節點中, 加入子節點:
<error-page>
<error-code>錯誤碼</error-code>
<location>處理的頁面地址</location>
</error-page>
注意: error-page可以編寫多個
例如:
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
include指令
用於將一個JSP 或 HTML檔案, 引入到另一個JSP檔案中
格式: <%@ include file="地址" %>
include動作
用於將一個JSP或HTML檔案 引入到另一個JSP檔案中.
格式: <jsp:include page="地址" flush="true" />
include 指令與動作的區別
include指令: 在JSP的轉換時期 , 將引入的JSP檔案嵌入到了include指令的位置 (合併為了一個檔案), 然後轉換為Servlet ! 最終生成的是一個.java檔案
include動作: 在JSP程式的轉換時期, 引入的JSP檔案會獨立轉換為Servlet , 到訪問時, 在將響應體合併, (將被引入檔案的響應體 , 動態載入在檔案中) !
JSP內建物件(隱含物件)
內建物件指的是: JSP引擎在轉換時期 , 在service方法的前面, 幫我們提前準備好的一些物件. 我們在<%%>程式碼塊中, 可以直接使用它們.
作用:
這些物件包含了我們進行動態網頁開發 常用的一些物件. 提供了大量的便於我們開發的功能, 可以簡化我們的開發過程.
九大內建物件
1. *
物件名 : request
型別 : HttpServletRequest
作用 : 請求物件, 包含了請求相關的資訊 !
2. *
物件名 : response
型別 : HttpServletResponse
作用 : 響應物件, 包含了一些用於響應的功能
3. *
物件名 : pageContext
型別 : PageContext
作用 : 頁面的上下文 , 用於獲取其它8大內建物件.
4. *
物件名 : session
型別 : HttpSession
作用 : 會話物件 , 用於會話跟蹤 與 狀態管理
5. *
物件名 : application
型別 : ServletContext
作用 : Servlet的上下文 , 一個應用程式啟動中, 只會存在一個Servlet上下文, 用於多個Servlet之間的資料共享與通訊.
6.
物件名 : out
型別 : JSPWriter
作用 : 列印流, 用於向響應體中輸出資料.
7.
物件名 : config
型別 : ServletConfig
作用 : Servlet的配置物件, 用於初始化一些鍵值對資訊
8.
物件名 : page
型別 : Object , 但是在賦值時, 使用的是this . 所以本質上是當前JSP轉換的Servlet類的型別.
作用 : 指當前頁面自身 .
9.
物件名 : exception
型別 : Throwable
作用 : 當頁面的page指令: isErrorPage="true"時, 才會存在的一個物件.
當別的頁面發生異常後, 跳轉到此頁面時 , exception是發生的異常物件.
JSP的四大域物件
九大內建物件中, 包含四個較為特殊的物件. 這四個物件我們稱其為: 域物件!
域物件存在一個特點:
都包含儲存資料 / 刪除資料 / 獲取資料的方法 , 所謂的域, 指的是儲存的資料使用的作用域.
儲存資料:
setAttribute(String key,Object value);
獲取資料:
Object value = getAttribute(String key);
刪除資料:
removeAttribute(String key);
四大域物件:
- pageContext (一個JSP頁面的域物件)
頁面的上下文 , 儲存在pageContext中的資料 , 域是最小的, 只有當前請求的當前頁面才可以使用. 頁面響應完畢物件就被垃圾回收了.
- request (一次請求域物件)
請求物件 , 儲存在request物件中的資料, 只有當前請求 , 才可以使用 ! 一次請求可能發生多次轉發 ,所以有可能跨越多個Servlet/JSP頁面.
- session (一次會話域物件)
會話物件, 儲存在session物件中的資料, 在當前會話中可以使用. 一次會話可能包含多次請求.
- application (一次服務域物件)
Servlet上下文物件, 儲存在application中的資料, 在伺服器關閉之前都可以使用.
應用的一次啟動, 伺服器中只會存在一個application物件, 一次伺服器啟動中可能包含多次會話.
EL表示式
作用, 用於快速的從域物件中 取出資料, 並將結果輸出到網頁中 .
格式:
${ 表示式 }
EL表示式的使用
1. 用於運算
${1+2+3+4+5} 輸出的結果是: 15
2. 用於取出域物件中的資料
訪問儲存的資料格式: ***
${儲存的key}
訪問儲存的物件的屬性:
格式1. ${儲存的key.屬性名} ***
格式2. ${儲存的key["屬性名"]}
格式3.
動態取值:
指的是按照域物件中儲存的一個屬性名, 以及物件名, 從物件中取出屬性值
${儲存的物件key[屬性名的key]}
3. 用於取出域物件中的集合/陣列中的物件屬性
格式1. ${儲存的key[下標].屬性名}
格式2. ${儲存的key[下標]["屬性名"]}
格式3.
動態取值:
指的是按照域物件中儲存的一個屬性名, 以及物件名, 從物件中取出屬性值
${儲存的物件key[下標][屬性名的key]}
EL表示式, 取出資料的流程
尋找的順序: 從域範圍小的 到 域範圍大的
步驟:
1. 先從pageContext中, 尋找資料是否存在.
2. 如果pageContext中不存在資料, 則去request中尋找資料是否存在.
3. 如果request中不存在資料, 則去session中尋找資料是否存在.
4. 如果session中不存在資料, 則去application中尋找資料是否存在
5. 如果application中不存在資料, 則向網頁輸出 : ""
在上述的步驟中, 一旦尋找到資料, 則流程結束, 將尋找到的資料輸出到網頁中.
taglib 指令 熟悉
用於在JSP中, 引入標籤庫.
語法格式:
<%@ taglib prefix="短名稱" uri="地址"%>
屬性:
prefix : 是引入的標籤庫的名稱, 用於區分引入的多個標籤庫 ,
在使用標籤庫中的標籤時 , 需要在前面加入庫名:
uri : 引入標籤庫的操作 與 網頁中引入其他靜態資源不一樣.
引入靜態資源(圖片,音樂等等) , 使用相對路徑.
每一個標籤庫都擁有uri屬性, 引入標籤庫, 不需要路徑, 只需要匹配uri就可以
JSTL標籤庫的使用
JSTL 是一套JSP的標準標籤庫
IF標籤
格式
<短名稱:if test=""></短名稱:if>
test值: boolean值 , 可以是具體的boolean值, 也可以是el表示式運算的結果
如果test值為true , 則內容顯示
如果test值為false , 則內容不顯示 (內容不會通過流, 輸出到響應體中)
案例:
<heihei:if test="${ flag }">
從前有一座山 , 山上有座尼姑庵 , 庵裡有個老尼姑 和 一個小姐姐 .
</heihei:if>
choose + when + otherwise
類似Java中的: switch + case + default
作用:
用於多分支, 顯示.
案例:
<%
pageContext.setAttribute("flag",6);
%>
<heihei:choose>
<heihei:when test="${ flag==1 }">孔子東遊 , 見兩小兒辯日</heihei:when>
<heihei:when test="${ flag==2 }">千呼萬喚始出來</heihei:when>
<heihei:when test="${ flag==3 }">白日依山盡</heihei:when>
<heihei:when test="${ flag==4 }">日照香爐生紫煙</heihei:when>
<heihei:when test="${ flag==5 }">萬里江陵十日還</heihei:when>
<heihei:otherwise>
停車坐愛楓林晚
</heihei:otherwise>
</heihei:choose>
forEach 標籤
用於遍歷集合或陣列元素
格式:
<標籤庫名稱:forEach items="" var="">
</標籤庫名稱:forEach>
屬性:
items : 使用el表示式, 從域物件中取出的要遍歷的陣列或集合物件.
var : 在進行遍歷時, 陣列或集合中的每一個元素被取出後, 會單獨儲存在pageContext中, var的值就是儲存時的鍵
案例:
<%
ArrayList<String> data = new ArrayList<>();
data.add("孔子東遊 , 見兩小兒辯日");
data.add("千呼萬喚始出來");
data.add("白日依山盡");
data.add("日照香爐生紫煙");
data.add("萬里江陵十日還");
data.add("停車坐愛楓林晚");
data.add("老驥伏櫪志在千里");
pageContext.setAttribute("data", data);
%>
<heihei:forEach items="${data }" var="str">
<h1>${ str }</h1>
</heihei:forEach>
自定義標籤庫
步驟:
1. 編寫一個類, 繼承SimpleTagSupport 類
2. 重寫類的doTag方法 ,
3. 在doTag方法中, 通過getJspContext() 方法 得到JSP的上下文.
4. 通過上下文物件, 可以得到其他8大內建物件 , 通常我們是getOut()得到輸出流, 向網頁輸出內容.
5. 編寫tld檔案, 描述標籤庫和標籤.
案例:
Class:
public class MyTag extends SimpleTagSupport {
private static ArrayList<String> data = new ArrayList<>();
static {
data.add("理想是人生的太陽。 —— 德萊賽");
data.add("真實是人生的命脈,是一切價值的根基。 —— 德萊塞");
data.add("真的猛士,敢於直面慘淡的人生,敢於正視淋漓的鮮血。 —— 魯迅");
data.add("人生須自重。 —— 黃宗羲");
data.add("在人生的道路上,當你的希望一個個落空的時候,你也要堅定,要沉著。 —— 朗費羅");
data.add("真理惟一可靠的標準就是永遠自相符合。 —— 歐文");
data.add("竹子用了4年紮根,第五年一出頭就被做成竹筍炒肉。");
data.add("公主病的成因沒別的,不是醜就是窮。“那有錢又漂亮脾氣卻不好的呢?”那本來就是公主,不叫病。");
data.add("所謂的女漢子,只不過是因為長得醜而已,但凡有些爺們氣質的漂亮姑娘,都被稱為女王大人。");
data.add("騰不出時間來睡覺的人,遲早會騰出時間來生病;騰不出時間來戀愛的人,遲早會騰出時間來相親。");
data.add("快樂分享錯了人就成了顯擺,難過分享錯了人就成了矯情。");
data.add("請記住,你並不是一無所有,你還有病!哈哈");
data.add("魚和熊掌不可兼得,但單身和窮可以!");
data.add("用錢當然買不到快樂,但只要你有錢,別人會想辦法讓你快樂。");
data.add("你才二十多歲,沒有遇到對的人很正常,以後你就知道,大概遇不到了!");
data.add("這年頭,當個宅男宅女,也得先買房子!");
data.add("能背後給你一刀的,往往是你信任的!");
data.add("失敗並不可怕,可怕的是你還相信這句話。");
data.add("比一個人吃火鍋更寂寞可憐的是,一個人沒有錢吃火鍋。");
data.add("你只知道人家化妝比你好看,卻不知道,她們卸了妝,不僅比你好看,面板還吹彈可破。");
data.add("從前車馬很慢,書信很遠,一生只夠愛一個人,但是能納很多妾。");
data.add("歲月告訴我,除了快遞,我啥也等不到!");
data.add("假如今天的你被生活辜負了,別傷心,因為明天生活還會繼續辜負你!");
}
@Override
public void doTag() throws JspException, IOException {
JspContext context = getJspContext();
JspWriter out = context.getOut();
String text = getText();
out.print(text);
}
public String getText() {
Random r = new Random();
int i = r.nextInt(data.size());
return data.get(i);
}
}
TLD檔案:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<!-- 註釋 ,描述 -->
<description>這是兄弟連Java30期自定義的一個標籤庫</description>
<!-- 名稱 -->
<display-name>XDL</display-name>
<!-- 版本 -->
<tlib-version>5.21</tlib-version>
<!-- 短名稱 -->
<short-name>x</short-name>
<!-- 用於匹配的uri -->
<uri>http://hahaha.heiheihei.com</uri>
<!-- 在標籤庫中 一個tag節點 , 表示庫中的一個自定義標籤 -->
<tag>
<!-- 標籤的描述 ,在使用時, 會提示 -->
<description>這個標籤會向網頁中輸出一條雞湯句子</description>
<!-- 標籤的名稱 -->
<name>djt</name>
<!-- 標籤的類的全名 -->
<tag-class>cn.xdl.tag.MyTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
web三大元件
1. Servlet
2. Filter 過濾器
3. Listener 監聽器
Filter 過濾器
所謂的過濾. 指的是過濾請求.
有時我們進行後段專案開發時, 有些請求 ,需要特定的條件才能操作 我們可以通過Filter , 來過濾不滿足的使用者操作.
例如:
用於的個人中心, 應該是登入 後才可以檢視的.
當用戶請求個人中心頁面時, 我們就可以編寫過濾器, 將未登入的所有使用者過濾掉, 並重定向至登入頁面.
採用了面向切面程式設計思想(AOP) .
使用步驟:
1. 編寫一個類 , 實現Filter介面
2. 通過web.xml 或 註解的方式, 配置過濾器的過濾地址.
案例:
public class ParamFilter implements Filter {
/**
* 當發生匹配過濾地址的請求時, doFilter執行
* 過濾器執行在web的所有資源之前 , 預設此方法是攔截請求的,
* 如果需要放行 , 需編寫: chain.doFilter(request,response);
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if(req.getParameter("a")==null) {
resp.setContentType("text/html;charset=utf-8");
//攔截
resp.getWriter().append("<h1>很遺憾, 引數錯誤, 無法訪問</h1>");
}else {
//放行
chain.doFilter(request, response);
}
}
}
web.xml
<filter>
<filter-name>pf</filter-name>
<filter-class>cn.xdl.demo1.ParamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>pf</filter-name>
<url-pattern>/home.jsp</url-pattern>
</filter-mapping>
過濾器鏈
當多個過濾器, 過濾地址重複時 , 就形成了過濾器鏈 . 使用者的請求, 需要過濾器鏈中的所有過濾器放行, 才可以正常訪問.
過濾器鏈執行的順序:
web.xml中的順序: 按照web.xml中配置的先後順序, 來執行.
註解配置的順序: 按照類名的自然排序, 順序執行.
web.xml中配置的過濾器, 一定執行在註解配置過濾器的前面.
Listener
監聽器 , 監聽是伺服器的一些事件 .
兩類事件:
1. 伺服器中元件的生命週期相關事件.
2. 域物件中資料的變化事件 .
ServletContextListener
用於監聽Servlet上下文的建立與銷燬.
案例:
@WebListener
public class MyServletContextListener implements ServletContextListener {
/**
* 當上下文物件 即將銷燬時, 方法執行
* 上下文物件銷燬的時機, 是 伺服器關閉或專案被解除安裝. 所以我們常在這裡進行全域性資源釋放的操作.
*/
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("專案關閉了");
}
/**
* 當上下文物件 被建立初始化時 , 這個方法執行
* 因為上下文物件建立的時機是 伺服器中專案啟動時 , 所以我們常在這裡進行全域性資源的初始化操作.
*/
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("專案啟動了");
}
}
ServletContextAttributeListener
用於監聽ServletContext中屬性的變化
案例:
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
/**
* 當向上下文中 新增屬性時, 程式碼執行
*/
public void attributeAdded(ServletContextAttributeEvent e) {
//從事件物件中, 得到儲存的鍵和值
String key = e.getName();
Object value = e.getValue();
System.out.println("監聽到ServletContext中資料的增加:"+key+" --> "+value);
}
/**
* 當從上下文中 移除屬性時, 程式碼執行
*/
public void attributeRemoved(ServletContextAttributeEvent e) {
//從事件物件中, 得到被移除的鍵和值
String key = e.getName();
Object value = e.getValue();
System.out.println("監聽到ServletContext中資料的移除:"+key+" --> "+value);
}
/**
* 當操作上下文物件 儲存資料 ,發生替換時, 程式碼執行.
*/
public void attributeReplaced(ServletContextAttributeEvent e) {
//從事件物件中, 得到被替換掉的舊的鍵和值
String key = e.getName();
Object oldValue = e.getValue();
System.out.println("監聽到ServletContext中資料的替換, 舊資料:"+key+" --> "+oldValue);
//從事件物件中, 得到上下文物件
Object newValue = e.getServletContext().getAttribute(key);
System.out.println("監聽到ServletContext中資料的替換, 新資料:"+key+" --> "+newValue);
}
}
HttpSessionListener
用於監聽session的建立與銷燬.
@WebListener
public class MySessionListener implements HttpSessionListener {
private static int count = 0;
private static Random r = new Random();
ArrayList<Integer> nums = new ArrayList<>();
public void sessionCreated(HttpSessionEvent arg0) {
//30-60的隨機數字
int num = r.nextInt(31)+30;
count+=num;
nums.add(num);
}
public void sessionDestroyed(HttpSessionEvent arg0) {
int num = nums.remove(nums.size()-1);
count-=num;
}
public static int getCount() {
return count;
}
}
HttpSessionAttributeListener
用於監聽session中的資料的增加 ,刪除, 修改.
public class LoginServlet2 extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
request.getSession().setAttribute("username", request.getRemoteAddr()+":"+uname);
response.sendRedirect("home2.jsp");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}