1. 程式人生 > >servlet 和 jsp 技術(01)

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 程式:

url 對映要寫專案的名稱

(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 目錄;
  • 不加就是從當前的包下找;