Java學習筆記14--Servlet
如何開發一個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>gz.itcast.a_servlet.FirstServlet</servlet-class> </servlet> <!-- servlet的對映配置 --> <servlet-mapping> <!-- servlet的內部名稱,一定要和上面的內部名稱保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的對映路徑(訪問servlet的名稱) --> <url-pattern>/first</url-pattern> </servlet-mapping>
前提:
- tomcat伺服器啟動時,首先載入webapps中的每個web應用的web.xml配置檔案。
- http://: http協議
- localhost: 到本地的hosts檔案中查詢是否存在該域名對應的IP地址
127.0.0.1 - 8080: 找到tomcat伺服器
- /day10 在tomcat的webapps目錄下找 day10的目錄
- /first 資源名稱。
-
1)在day10的web.xml中查詢是否有匹配的url-pattern的內容(/first)
-
2)如果找到匹配的url-pattern,則使用當前servlet-name的名稱到web.xml檔案中查詢是否相同名稱的servlet配置
-
3)如果找到,則取出對應的servlet配置資訊中的servlet-class內容:
字串: gz.itcast.a_servlet.FirstServlet -
通過反射:
a)構造FirstServlet的物件
b)然後呼叫FirstServlet裡面的方法
-
Servlet的對映路徑
<servlet-mapping> <!-- servlet的內部名稱,一定要和上面的內部名稱保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的對映路徑(訪問servlet的名稱) --> <url-pattern>/first</url-pattern> </servlet-mapping>
url-pattern 瀏覽器輸入
精確匹配 /first http://localhost:8080/day10/first
/itcast/demo1 http://localhost:8080/day10/itcast/demo1
模糊匹配 /* http://localhost:8080/day10/任意路徑
/itcast/* http://localhost:8080/day10/itcast/任意路徑
*.字尾名 http://localhost:8080/day10/任意路徑.do
*.do
*.action
*.html(偽靜態)
注意:
- 1)url-pattern要麼以 / 開頭,要麼以*開頭。 例如, itcast是非法路徑。
- 2)不能同時使用兩種模糊匹配,例如 /itcast/*.do是非法路徑
- 3)當有輸入的URL有多個servlet同時被匹配的情況下:
- 3.1 精確匹配優先。(長的最像優先被匹配)
- 3.2 以後綴名結尾的模糊url-pattern優先順序最低!!!
servlet預設路徑
servlet的預設路徑(/)是在tomcat伺服器內建的一個路徑。該路徑對應的是一個DefaultServlet(預設Servlet)。這個預設的Servlet的作用是用於解析web應用的靜態資原始檔。
問題: URL輸入http://localhost:8080/day10/index.html 如何讀取檔案????
- 1)到當前day10應用下的web.xml檔案查詢是否有匹配的url-pattern。
- 2)如果沒有匹配的url-pattern,則交給tomcat的內建的DefaultServlet處理
- 3)DefaultServlet程式到day10應用的根目錄下查詢是存在一個名稱為index.html的靜態檔案。
- 4)如果找到該檔案,則讀取該檔案內容,返回給瀏覽器。
- 5)如果找不到該檔案,則返回404錯誤頁面。
結論: 先找動態資源,再找靜態資源。
Sevlet的生命週期
Servlet的生命週期: servlet類物件什麼時候建立,什麼時候呼叫什麼方法,什麼時候銷燬。
以前的物件: new Student(); stu.study(); stu=null;
Servlet程式的生命週期由tomcat伺服器控制的!!!!
Servlet重要的四個生命週期方法
- 構造方法: 建立servlet物件的時候呼叫。預設情況下,第一次訪問servlet的時候建立servlet物件 只調用1次。證明servlet物件在tomcat是單例項的。
- init方法: 建立完servlet物件的時候呼叫。只調用1次。
- service方法: 每次發出請求時呼叫。呼叫n次。
- destroy方法: 銷燬servlet物件的時候呼叫。停止伺服器或者重新部署web應用時銷燬servlet物件。只調用1次。
用時序圖來演示servlet的生命週期
Servlet的自動載入
預設情況下,第一次訪問servlet的時候建立servlet物件。如果servlet的構造方法或init方法中執行了比較多的邏輯程式碼,那麼導致使用者第一次訪問sevrlet的時候比較慢。
改變servlet建立物件的時機: 提前到載入web應用的時候!!!
在servlet的配置資訊中,加上一個即可!!
<servlet>
<servlet-name>LifeDemo</servlet-name>
<servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>
<!-- 讓servlet物件自動載入 -->
<load-on-startup>1</load-on-startup> 注意: 整數值越大,建立優先順序越低!!
</servlet>
有參的init方法和無參的init方法
有引數的init方法
- 該方法是servlet的生命週期方法,一定會被tomcat伺服器呼叫
無引數的init方法
- 該方法是servlet的編寫初始化程式碼的方法。是Sun公司設計出來專門給開發者進行覆蓋,然後在裡面編寫servlet的初始邏輯程式碼的方法。
注意:如果要編寫初始程式碼,不需要覆蓋有引數的init方法。因為有參的init方法中會呼叫無參的init方法
Servlet的多執行緒併發問題
注意: servlet物件在tomcat伺服器是單例項多執行緒
的。
因為servlet是多執行緒的,所以當多個servlet的執行緒同時訪問了servlet的共享資料,如成員變數,可能會引發執行緒安全問題。
解決辦法:
-
1)把使用到共享資料的程式碼塊進行同步(使用synchronized關鍵字進行同步)
-
2)建議在servlet類中儘量不要使用成員變數。如果確實要使用成員,必須同步。而且儘量縮小同步程式碼塊的範圍。(哪裡使用到了成員變數,就同步哪裡!!),以避免因為同步而導致併發效率降低。
Servlet學習的物件: HttpServletRequest 請求物件:獲取請求資訊 HttpServletResponse 響應物件: 設定響應物件 ServletConfig物件 servlet配置物件 ServletContext物件; servlet的上下文物件
ServletConfig物件
作用
ServletConfig物件: 主要是用於載入servlet的初始化引數。在一個web應用可以存在多個ServletConfig物件(一個Servlet對應一個ServletConfig物件)
物件建立和得到
建立時機: 在建立完servlet物件之後,在呼叫init方法之前建立。
得到物件: 直接從有引數的init方法中得到!!!
servlet的初始化引數配置
<servlet>
<servlet-name>ConfigDemo</servlet-name>
<servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>
<!-- 初始引數: 這些引數會在載入web應用的時候,封裝到ServletConfig物件中 -->
<init-param>
<param-name>path</param-name>
<param-value>e:/b.txt</param-value>
</init-param>
</servlet>
注意: servlet的引數只能由當前的這個sevlet獲取!!!!
ServletConfig的API:
java.lang.String getInitParameter(java.lang.String name) 根據引數名獲取引數值
java.util.Enumeration getInitParameterNames() 獲取所有引數
ServletContext getServletContext() 得到servlet上下文物件
java.lang.String getServletName() 得到servlet的名稱
ServletContext物件
引入
ServletContext物件 ,叫做Servlet的上下文物件。表示一個當前的web應用環境。一個web應用中只有一 個ServletContext物件。
物件建立和得到
建立時機:載入web應用時建立ServletContext物件。
得到物件: 從ServletConfig物件的getServletContext方法得到
ServletContext物件的核心API(作用)
java.lang.String getContextPath() --得到當前web應用的路徑
java.lang.String getInitParameter(java.lang.String name) --得到web應用的初始化引數
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) --域物件有關的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) --轉發(類似於重定向)
java.lang.String getRealPath(java.lang.String path) --得到web應用的資原始檔
java.io.InputStream getResourceAsStream(java.lang.String path)
得到web應用路徑
java.lang.String getContextPath() 用在請求重定向的資源名稱中
得到web應用的初始化引數(全域性)
java.lang.String getInitParameter(java.lang.String name) --得到web應用的初始化引數
java.util.Enumeration getInitParameterNames()
web應用引數可以讓當前web應用的所有servlet獲取!!!
域物件有關的方法
域物件:作用是用於儲存資料,獲取資料。可以在不同的動態資源之間共享資料。
案例:
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域物件
轉發
RequestDispatcher getRequestDispatcher(java.lang.String path)
1)轉發
a)位址列不會改變
b)轉發只能轉發到當前web應用內的資源
c)可以在轉發過程中,可以把資料儲存到request域物件中
2)重定向
a)位址列會改變,變成重定向到地址。
b)重定向可以跳轉到當前web應用,或其他web應用,甚至是外部域名網站。
c)不能再重定向的過程,把資料儲存到request中。
結論: 如果要使用request域物件進行資料共享,只能用轉發技術!!!