1. 程式人生 > >Java學習筆記14--Servlet

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域物件進行資料共享,只能用轉發技術!!!