servlet 和 jsp 技術(01)
一、瞭解 http 協議
1、概念作用特點
(1)概念:超文字傳輸協議
(2)作用:規範客戶端和伺服器之間的互動
(3)特點:簡單便捷、無狀態(對事務處理沒有記憶能力)、無連線(1.1版本支援連線保持)
2、互動流程請求格式和請求方式
(1)互動流程:建立連線、傳送請求、接受響應、關閉連線
(2)請求格式:行(請求方式、協議、地址)、頭(附加資訊)、空行(必須)、資料(體)
(3)請求方式:
- GET/POST比較:安全性、請求資料的位置和大小限制
3、響應格式和狀態碼
(1)響應格式:頭、行、空行、實體(資料)
(2)狀態碼:200--成功;300--重定向;400--客戶端錯誤;500--伺服器錯誤
二、tomcat介紹和使用
1、伺服器的概念
(1)概念:就是一個接受客戶端請求而呼叫對應邏輯程式碼的容器
2、tomcat的目錄結構
(1)結構:bin(可執行檔案)、lib(依耐的jar)、conf(配置檔案)、webapps(專案)、logs(日誌)、
work(jsp編譯目錄)
3、tomcat安裝配置常見錯誤
(1)路徑不要有中文
(2)埠的佔用問題
(3)電腦必須要有 jdk 環境
三、servlet
1、servlet簡介
(1)第一個 web 程式:
(2)什麼是servlet:執行在伺服器端的 java 程式,就是一個類實現了 servlet 介面
(3)servlet編寫:
- 寫一個類繼承 httpServlet;
- 重寫 service 方法;
- 在 web xml中配置 servlet;
2、servlet 訪問流程和生命週期
(1)訪問流程:請求url------專案-------web.xml-------servlet
(2)生命週期:
- 配了 load-on-startup 就是伺服器的啟動到停止(load-on-startup 配在 servlet 中,數字表示優先順序);
- 沒有配就是第一次訪問到伺服器關閉;
- 工作原理:init 初始化------呼叫 service 提供服務(doget 和 dopost)------ destroy 銷燬例項
3、service、doGet和doPost
(1)作用:service 可以處理get 和 post 請求;doGet只能處理get;doPost只能處理post;
(2)優先:三者都存在的前提下,優先使用 service;
(3)說明:
- 父類的service 方法是做get和post 的判斷,然後呼叫doGet 或 doPost方法;
- 一般使用用service 方法,在service做 get 和 post 判斷,呼叫相應的程式碼;
4、request 和 response 物件
(1)request物件
- 獲取行資訊:getMethod(方法)、getRequestURL和getRequestURI、getScheme(協議);
- 獲取頭資訊:
- getHeader("key")、getHeaderNames();key不存在返回 null;
- 獲取請求體的資料:
- getParameter("key")、getParameterNames()、getParameterValues()
(2)response物件
- 設定響應頭:setHeader(name,value)和 addHeader();前者會產生同鍵覆蓋,後者不會;
- 設定響應狀態:sendError(int code,str msg)--自定義錯誤響應的狀態;
- 設定響應體:resp.getWriter.write(string str)
- 設定編碼:resp.setContentType("text/html;charset=utf-8")
- servlet 中 service 的編寫邏輯:
- 設定請求響應編碼;
- 獲取請求資料;
- 處理請求資料:資料庫操作(mvc思想);
- 響應處理結果(直接響應;重定向;轉發);
(3)說明:
- request 和 response 物件都是有伺服器建立的;
- 請求引數亂碼的問題:
- 解決方法一:new String(str.getBytes("iso8859-1"),"utf-8")------get 和 post 都可以這樣處理;
- 解決方法二:post--setCharatorEncoding("utf-8");get----除了前面的設定外還要配置server xml(在connector 中配置useBodyEncodingforURI=true)
(4)登入練習:jsp、servlet、service、dao、jdbc、mysql
5、轉發和重定向
(1)請求轉發
- 作用:實現多個 servlet 的聯動處理請求,解決了程式碼冗餘,提高了靈活性;
- 方法:request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
- 特點:一次請求,位址列不變;
- 注意:轉發後直接 return;
(2)request物件的作用域
- request 實質是以域物件,就是一個容器,可以從裡面存取東西;
- request 在一次請求的範圍內有效;
- request 域物件的作用是實現多個 servlet 之間的資料共享(資料流轉);
(3)重定向
- 作用:解決表單的重複提交問題;解決sevlet無法處理的問題;
- 方法:response.sendRedirect("/login/jsp/suc.jsp");
- 特點:兩次請求,兩個 request;位址列會發生改變;
- 問題:重定向的資料的共享問題用 session 解決;
(4)二者的比較
- 轉發只能訪問統一站點同一 web 應用下的其他資源,而重定向不僅可以訪問同一 web 應用的其他資源,還可以訪問同一站點其他應用的資源,甚至可以訪問其他站點的資源;
- 二者的速度來講,轉發比重定向更快,在使用二者都無所謂的前提下建議使用轉發;
- 但是在表單提交之類的特殊場景,為了避免資料的重複提交,應該使用重定向;
- 二者路徑的寫法,轉發沒有專案名,而重定向要包括專案名;
6、cookie(鑰匙) 和 session(房間)
(1)cookie(瀏覽器端)
- 作用:解決不同次請求之間的資料的共享問題
- 使用:Cookie c = new Cookie();resp.addCookie(c);req.getCookies()返回陣列遍歷即可(注意非空的判斷);
- 特點:
- cookie 在伺服器端新增,存到瀏覽器;
- 預設cookie是臨時儲存,存到記憶體;設定過期時間(setMaxAge)之後序列化到硬碟實現定期儲存;
- 有限期內符合路徑要求的請求都會攜帶該 cookie(有效路徑沒有設定的話都會攜帶的setPath);
- 注意:一個 cookie 物件存一條 cookie(一個鍵值對通過構造方法傳入);
- 練習:三天之類免登入的 demo;
(2)session(伺服器端)
- 作用:實現一個使用者不同次請求之間的資料共享的問題,一般 session 中存放使用者資料,便於取用
- 原理:使用者第一次請求建立一個 session 物件,並將 Jsessionid 隨 cookie 傳到瀏覽器,以後使用者再次請求的時候,帶上 cookie 根據 id取到屬於自己的 session,從而獲得 session 中共享的資料
- 特點:由伺服器建立並存儲,依賴 cookie 技術,在不失效的前提下,作用域為一次會話;
- 使用:
- req.getSession() 可以做幾件事:
- 第一次訪問會建立一個 session 並將 id 存到瀏覽器的 cookie 中
- 再次訪問在 cookie 和 session 都沒有失效的前提下,可以直接根據請求中的 cookie 中的id 取到自己的session
- setAttribute(str,obj) getAttribute():session 是域物件可以使用通用的存取資料的方法;
- setMaxInactiveInterval():設定session 的失效時間,預設是 30 分鐘,每次訪問都會重新計時
- invalidate():強制銷燬 session;
- session 的失效處理:將請求中的 JSESSIONID 和後臺獲取到的 id 進行對比,不一致則為失效;還可以做資料的 null 判斷
- 練習:login 示例的使用者名稱 null 的顯示
7、servletContext
(1)作用:解決不同使用者之間的資料的共享的問題;
(2)特點:伺服器建立;使用者共享(一個專案有且只有一個);
(3)作用域和生命週期:整個專案內;伴隨伺服器的啟停;
(4)SC 物件的建立:可以通過servlet、servletConfig、session物件的 get方法來獲取
(5)SC 物件的使用
- 域物件可以使用通用的方法存取資料;
- 獲取web xml 中的全域性配置資料:getInitParameter(name)getInitParameterNames()返回鍵的列舉;
- 獲取專案根目錄下資源的絕對路徑:sc.getRealPath(path),這個方法能獲取到專案根目錄的絕對路徑;
- 獲取專案根目錄下資源的IO流:sc.getResourceAsStream(path)只能獲取普通資原始檔的流,無法獲取 class 檔案的流;
- web xml 中全域性配置變數:注意一個 context-param 只能配一個全域性引數
<context-param>
<param-name>haha</param-name>
<param-value>123</param-value>
</context-param>
(6)練習:網站訪問的計數(兩個路徑的訪問都要計數,同時伺服器停止要利用流技術進行持久化的儲存)
(7)servletConfig物件
- 作用:獲取獨屬於每個 servlet 的初始化引數;
- 特點:一個 servlet 物件一個 servletConfig;
- 使用:物件獲取----this.getServletConfig();引數獲取------sc.getInitParameter(name);
<servlet>
<init-param>
<param-name>haha</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
(8)web xml 和 server xml 檔案
- web xml
- 位置:專案和 tomcat 都有,專案的是隻針對本專案有效,而 tomcat 的配置是全域性的,預設先找專案的再找全域性的;
- 核心元件:全域性上下文配置、servlet 配置、監聽器和過濾器;
- 載入時機:都是在伺服器的啟動時載入;
- server xml
- 核心:
- 注意:埠號的配置和專案熱部署的配置,專案熱部署後,如果移除專案需要刪掉對應的context;
- 熱部署:<Context docBase="xxx" path="/xxx" reloadable="true"/>
四、jsp
1、jsp 概述
(1)概念
- java server pages 中文java 伺服器網頁,是一種動態網頁技術;
- 兼具 html 和 servlet 的優點,本質還是一個servlet,可以跨平臺;
(2)原理
- tomcat 只認識 servlet;
- localhost:8080/login/1.jsp 這樣的url 後面部分的 1.jsp 會被 tomcat 認為是一個 servlet 的對映;
- 通過這個對映會去找 tomcat 的 web xml 中的相關的配置,最終會找到一個名為 jspservlet 的servlet 程式(tomcat的jsp引擎);
- 這個sevlet 的作用就是把 jsp 檔案進行轉譯輸出,java原封不變,html相關的會 write 出去;
2、jsp page 指令
(1)作用:配置 jsp 檔案轉譯相關引數
(2)jsp 的三種註釋:
- 前端註釋:會轉譯會發送但是瀏覽器不會執行;
- java 註釋:會轉譯但sevlet 不會執行;
- jsp 註釋:不會轉譯;<%-- --%>
(3)格式:
<%@ page language="java" pageEncoding="utf-8"%>
(4)詳述:
- language:轉譯語言
- import:轉譯為java 後要匯入的包,不同的包用逗號間隔
- pageencoding:jsp 的編碼格式
- contenttype:響應給瀏覽器的格式和編碼
- session:session 支援,預設為true 是開啟的
- errorpage:jsp 執行錯誤跳轉的頁面
- extends:轉譯後的 servlet 要繼承的類(包名+類名)
(5)關於亂碼:本質的原因就是檔案 讀 和 寫 的編碼不一致造成的
3、java程式碼塊-----區域性程式碼塊 | 全域性程式碼塊 | 輸出程式碼塊
(1)區域性程式碼塊
- 格式:<% java程式碼 %>
- 上面的java 程式碼最終都是轉譯到 service 方法中
- 和 html 元素配合使用用類似於拼接的方式實現邏輯判斷,可讀性很差
- 開發中通常是 jsp 少做邏輯的處理,儘量在servlet 中來完成
(2)全域性程式碼塊
- 格式:<%! code %>
- 轉譯後是全域性程式碼
- 使用:全域性進行方法的宣告,區域性來呼叫
(3)輸出程式碼塊
- 語法:<%= %>
- 實質就是一個輸出,等價與 out.write()
- 結束不用寫分號
- 可以在 html 的任意位置來使用
4、jsp 和動態引入和靜態引入
(1)靜態引入(include 指令引入)
- 語法:<%@include file="相對路徑"%>
- 原理:多個jsp 合成為1個一起轉譯為一個servlet
- 注意:靜態引入同名變數很可能會引起衝突
(2)動態引入(通過 include 動作標籤來引入)
- 語法:<jsp:include page=" ">
- 原理:引入的檔案會單獨轉譯,最後在當前jsp 轉譯後的 servlet 中呼叫
- 注意:動態引入和靜態引入最後的效果都是一樣的;動態引入無需注意變數的同名問題
(3)總結
- 作用:都是降低程式碼冗餘,提升維護性;
- 效果一模一樣;
- 根據同名變數的多少來決定選用誰;
- 直接用動態引入更好;
5、forward 轉發標籤(動作標籤)
(1)作用:和 sevlet 中的轉發功能是一樣的
(2)語法:
<jsp:forward page="path">
<jsp:param name="" value=""/>
</jsp:forward>
(3)注意:
- forward 標籤中間只能是 param 標籤,寫其他的任何字元會報錯;
- 其中的引數會拼接在地址?後面和get請求的類似;
- 在轉發後的jsp 和servlet 中能夠獲取相應的引數;
6、jsp 九大內建物件 | 資源路徑
(1)內建物件:jsp 在轉譯為 servlet後自動生成並宣告的物件,我們在 jsp 頁面可以直接使用
(2)注意:9 個物件都是在service 方法中宣告的,所以使用的時候只能在區域性程式碼塊中使用
(3)九個物件(request、response、out、session、page、pageContext、application、config、exception)
- pageContext:頁面上下文物件,裡面封裝了其他的8個物件,包含了jsp頁面執行的資訊;一個jsp 一個pc物件,作用域為當前頁面;
- request:封裝請求資料,伺服器建立,一次請求;
- response:請求處理結果響應給瀏覽器,可以設定響應頭和實現重定向;
- out:輸出物件,在jsp 基本被輸出的標籤取代;
- session:儲存使用者不同次請求的共享資料,一次會話;
- application:就是 servletContext物件,一個專案一個,存不同使用者的共享資料,作用域為專案內;
- page:就是 this,本jsp
- config:就是servletConfig,用來獲取 web xml 配置的資料,完成初始化引數的讀取;
- exception:異常物件,要用的話需要在 page 指令中設定 iserrorpage = true來開啟;
(4)四個作用域物件(資料流轉)
- request、session、application、pageContext;
- 通用的方法:get/setAttribute();
(5)jsp資源的路徑問題
- 相對路徑:相對位置不能變,檔案一移動就會出現問題;../ 跳出資料夾比較麻煩;
- 絕對路徑1(動態):/虛擬專案名/資源;第一個 / 直接定位到 webapps 目錄;
- 絕對路徑2(動態):使用 myEclipse 開發建立 jsp 檔案自動生成3行程式碼,構建一個 basepath,後面只需直接寫相對於 webroot 的目錄即可;
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/";
%>
<base href="<%=basePath%>"/> <!-- base放在 head 標籤裡 -->
- 總結:一般就使用絕對路徑;
- 補充:servlet 中的路徑問題
- 轉發:/resource,第一個斜槓代表專案根目錄;
- 重定向:/proname/resource,第一個斜槓代表伺服器根目錄;
- 補充:其他路徑
- 加斜槓就是預設 classpath 目錄;
- 不加就是從當前的包下找;