總結:
一、servlet的生命週期
Servlet程序的生命週期由tomcat服務器控制的!!!servlet的四個重要的方法是自身的無參構造函數、init方法、service(或者是doGet、doPost方法,其中三個功能我測試的時候是一樣的,三者有你沒我,都有隻會執行service的方法)、destory方法(當servlet重啓或者tomcat關閉的時候會運行)
二、servlet是懶加載的,只有請求到來時,纔會反射生成對象,執行業務邏輯
三、servlet是單實例(單例)多線程(這個可以從它的init方法只會執行一遍可以看出),要注意線程安全型的問題
四、域對象:作用範圍在整個web應用中有效!!!
servlet中的所有域對象:
HttpServletRequet 域對象
ServletContext域對象
HttpSession 域對象
PageContext域對象
深入理解Servlet
課程目標
動態資源與靜態資源區別
1. servlet三及相關接口簡介
2. servet 執行過程
3. servlet路徑映射
4. servlet生命週期(重點) --理解(重點)
5. Servlet自動加載
6. Servlet線程安全
7. Servlet相關接口詳解
8. ServletContext對象 --知識點
一、Web項目結構
|- WebRoot : web應用的根目錄
|- 靜態資源(html+css+js+image+vedio)STATIC
|- WEB-INF : 固定寫法。
|-classes: (可選)固定寫法。存放class字節碼文件
|-lib: (可選)固定寫法。存放jar包文件。
|-web.xml
注意:
1)WEB-INF目錄裏面的資源不能通過瀏覽器直接訪問
2)如果希望訪問到WEB-INF裏面的資源,就必須把資源配置到一個叫web.xml的文件中。
練習:
1)在webapps下建立一個mybbs目錄
2)創建兩個文件
2.1 index.html 裏面隨便寫內容 ,有超鏈接-連接到test.html
2.2 test.html 裏面隨便寫
3)通過瀏覽器訪問到。
二、手動開發動態資源
2.1靜態資源和動態資源的區別
靜態資源: 當用戶多次訪問這個資源,資源的源代碼永遠不會改變的資源。
動態資源:當用戶多次訪問這個資源,資源的源代碼可能會發送改變。
2.2源的開發技術
Servlet : 用java語言來編寫動態資源的開發技術。
Servlet特點:
1)普通的java類,繼承HttpServlet類,覆蓋doGet方法
2)Servlet類只能交給tomcat服務器運行!!!!(開發者自己不能運行!!!)
Servlet手動編寫步驟:
1)編寫一個servlet程序,繼承HttpServlet
/** * 第一個servlet程序 * @author APPle * */ public class HelloServlet extends HttpServlet{
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解決中文亂碼問題 resp.setCharacterEncoding("utf-8");// 內容編碼,防止出現中文亂碼 resp.setContentType("text/html;charset=utf-8"); //向瀏覽器輸出內容 resp.getWriter().write("這是第一個servlet程序。當前時間爲:"+new Date()); } } |
2)找到HelloServlet類的class字節碼,然後把拷貝到tomcat的一個web應用中WEB-INF/classes目錄下。
3)在當前web應用下的web.xml文件配置Servlet。
<!-- 配置一個servlet程序 --> <servlet> <!-- servlet的內部名稱 ,可以自定義--> <servlet-name>HelloServlet</servlet-name> <!-- servlet類名: 包名+簡單類名--> <servlet-class>com.itmayiedu.HelloServlet</servlet-class> </servlet>
<servlet-mapping> <!-- servlet的內部名稱,和上面的名稱保持一致!!!--> <servlet-name>HelloServlet</servlet-name> <!-- servlet的訪問名稱: /名稱 --> <url-pattern>/hello</url-pattern> </servlet-mapping> |
4)啓動tomcat服務器,運行訪問
訪問servlet: http://localhost:8080/myweb/ hello
三、工具開發動態資源
1)創建web project (javaweb工程)
2)在WebRoot下建立靜態資源文件,
3)在src下建立動態資源文件
3.1 new -> Servlet( servlet的代碼生成器)
3.2 寫pacakge -> class名 -> 修改mapping url
4)關聯tomcat服務器
4.1 window-> Preferences - > MyEcplise -> servers -> Tomcat 6.x (注意一定要enable)
5)部署web project應用。(拷貝web應用到tomcat的webapps目錄下)
6)啓動tomcat服務器
7)訪問servlet
http://localhost:8081/myWeb /hello
3.1 如何開發一個Servlet
1.1 步驟:
1)編寫java類,繼承HttpServlet類
2)重新doGet和doPost方法
3)Servlet程序交給tomcat服務器運行!!
3.1 servlet程序的class碼拷貝到WEB-INF/classes目錄
3.2 在web.xml文件中進行配置
<!-- 配置一個servlet --> <!-- servlet的配置 --> <servlet> <!-- servlet的內部名稱,自定義。儘量有意義 --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的類全名: 包名+簡單類名 --> <servlet-class>com.itmayiedu.FirstServlet</servlet-class> </servlet>
<!-- servlet的映射配置 --> <servlet-mapping> <!-- servlet的內部名稱,一定要和上面的內部名稱保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的映射路徑(訪問servlet的名稱) --> <url-pattern>/first</url-pattern> </servlet-mapping> |
問題:訪問次URL: http://localhost:8080/myweb /first
前提: tomcat服務器啓動時,首先加載webapps中的每個web應用的web.xml配置文件。
http://: http協議
localhost: 到本地的hosts文件中查找是否存在該域名對應的IP地址
127.0.0.1
8080: 找到tomcat服務器
/day10 在tomcat的webapps目錄下找 day10的目錄
/first 資源名稱。
1)在myweb的web.xml中查找是否有匹配的url-pattern的內容(/first)
2)如果找到匹配的url-pattern,則使用當前servlet-name的名稱到web.xml文件中查詢是否相同名稱的servlet配置
3)如果找到,則取出對應的servlet配置信息中的servlet-class內容:
字符串: com.itmayiedu.a_servlet.FirstServlet
通過反射:
a)構造FirstServlet的對象
b)然後調用FirstServlet裏面的方法
3.3 Servlet 註解版本
Servlet3.0以上使用 註解自動映射@webServlet.
3.4 Sevlet的生命週期(重點)
4.1 引入
Servlet的生命週期: servlet類對象什麼時候創建,什麼時候調用什麼方法,什麼時候銷燬。
以前的對象: new Student(); stu.study(); stu=null;
Servlet程序的生命週期由tomcat服務器控制的!!!!
4.2 Servlet重要的四個生命週期方法
構造方法: 創建servlet對象的時候調用。默認情況下,第一次訪問servlet的時候創建servlet對象 只調用1次。證明servlet對象在tomcat是單實例的。
init方法: 創建完servlet對象的時候調用。只調用1次。
service方法: 每次發出請求時調用。調用n次。
destroy方法: 銷燬servlet對象的時候調用。停止服務器或者重新部署web應用時銷燬servlet對象。
只調用1次。
4.3 僞代碼演示servlet的生命週期
Tomtcat內部代碼運行:
1)通過映射找到到servlet-class的內容,字符串: com.itmayiedu.a_servlet.FirstServlet
2)通過反射構造FirstServlet對象
2.1 得到字節碼對象
Class clazz = class.forName("com.itmayiedu.a_servlet.FirstServlet");
2.2 調用無參數的構造方法來構造對象
Object obj = clazz.newInstance(); ---1.servlet的構造方法被調用
3)創建ServletConfig對象,通過反射調用init方法
3.1 得到方法對象
Method m = clazz.getDeclareMethod("init",ServletConfig.class);
3.2 調用方法
m.invoke(obj,config); --2.servlet的init方法被調用
4)創建request,response對象,通過反射調用service方法
4.1 得到方法對象
Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
4.2 調用方法
m.invoke(obj,request,response); --3.servlet的service方法被調用
5)當tomcat服務器停止或web應用重新部署,通過反射調用destroy方法
5.1 得到方法對象
Method m = clazz.getDeclareMethod("destroy",null);
5.2 調用方法
m.invoke(obj,null); --4.servlet的destroy方法被調用
1、執行順序:
先執行自己的無參構造函數
然後init方法
執行service或者doGet方法(每次請求到來時都會執行這個方法,service方法重寫的時候,doGEt或者doPost 方法不會執行)
最後重啓的時候執行destrory方法
4.4 用時序圖來演示servlet的生命週期
3.5 Servlet的自動加載
默認情況下,第一次訪問servlet的時候創建servlet對象。如果servlet的構造方法或init方法中執行了比較多的邏輯代碼,那麼導致用戶第一次訪問sevrlet的時候比較慢。
改變servlet創建對象的時機: 提前到加載web應用的時候!!!
在servlet的配置信息中,加上一個<load-on-startup>即可!!
<servlet> <servlet-name>LifeDemo</servlet-name> <servlet-class>com.itmayiedu.life.LifeDemo</servlet-class> <!-- 讓servlet對象自動加載 --> <load-on-startup>1</load-on-startup> 注意: 整數值越大,創建優先級越低!! </servlet> |
3.6 Servlet的多線程併發問題
注意: servlet對象在tomcat服務器是單實例多線程的,要注意線程安全型的問題。
因爲servlet是多線程的,所以當多個servlet的線程同時訪問了servlet的共享數據,如成員變量,可能會引發線程安全問題。
解決辦法:
1)把使用到共享數據的代碼塊進行同步(使用synchronized關鍵字進行同步)
2)建議在servlet類中儘量不要使用成員變量。如果確實要使用成員,必須同步。而且儘量縮小同步代碼塊的範圍。(哪裏使用到了成員變量,就同步哪裏!!),以避免因爲同步而導致併發效率降低。
Servlet學習:
HttpServletRequest 請求對象:獲取請求信息
HttpServletResponse 響應對象: 設置響應對象
ServletConfig對象 servlet配置對象
ServletContext對象; servlet的上下文對象
線程安全代碼:
package com.servlet;
import java.io.IOException; import java.util.Date;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
/** * * @classDesc: 功能描述:(線程安全演示) * @author: 餘勝軍 * @createTime: 2017年8月31日 下午11:47:20 * @version: v1.0 * @copyright:上海每特教育科技有限公司 */ public class ServetlDemo4 extends HttpServlet { private int i = 1;
@Override public void init() throws ServletException { System.out.println("ServetlDemo4...init()"); }
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設置編碼格式 // resp.setContentType("text/html;charset=utf-8"); resp.setCharacterEncoding("utf-8");// 內容編碼,防止出現中文亂碼 resp.setContentType("text/html;charset=utf-8"); synchronized (ServetlDemo4.class) { // 向瀏覽器輸出內容 resp.getWriter().write("這是第" + i + "次訪問..."); try { Thread.sleep(5000); } catch (Exception e) { // TODO: handle exception }
i++; }
}
@Override public void destroy() { System.out.println("ServetlDemo4...destroy()");
}
}
|
四、 ServletContext對象
4.1得到web應用路徑
java.lang.String getContextPath() 用在請求重定向的資源名稱中
4.2域對象有關的方法
域對象:作用是用於保存數據,獲取數據。可以在不同的動態資源之間共享數據。
案例:
Servlet1 Servlet2
name=eric
response.sendRedirect("/Servlet2?name=eric") String request.getParameter("name");
保存到域對象中 從域對象獲取
Student
方案1: 可以通過傳遞參數的形式,共享數據。侷限:只能傳遞字符串類型。
方案2: 可以使用域對象共享數據,好處:可以共享任何類型的數據!!!!!
ServletContext就是一個域對象!!!!
保存數據:void setAttribute(java.lang.String name, java.lang.Object object)
獲取數據: java.lang.Object getAttribute(java.lang.String name)
刪除數據: void removeAttribute(java.lang.String name)
ServletContext域對象:作用範圍在整個web應用中有效!!!
所有域對象:
HttpServletRequet 域對象
ServletContext域對象
HttpSession 域對象
PageContext域對象
4.3轉發與重定向
RequestDispatcher getRequestDispatcher(java.lang.String path)
1)轉發
a)地址欄不會改變
b)轉發只能轉發到當前web應用內的資源
c)可以在轉發過程中,可以把數據保存到request域對象中
2)重定向
a)地址欄會改變,變成重定向到地址。
b)重定向可以跳轉到當前web應用,或其他web應用,甚至是外部域名網站。
c)不能再重定向的過程,把數據保存到request中。
自定義重定向:
response.setStatus(302); response.setHeader("Location","OtherServlet");
|
結論: 如果要使用request域對象進行數據共享,只能用轉發技術!!!
總結:
Servlet編程:
Servlet生命週期(重點)
其他都是應用的東西(敲代碼練習)
第一個熟悉作用域區別
第二個目標就是熟悉重定向底層原理。
.
代碼: