1. 程式人生 > >關於Servlet的個人心得

關於Servlet的個人心得

1,servlet 的生命週期

1>無參構造
2>初始化init(),含有唯一的一個引數,servletConfig,可以通過其獲取servletContext
3>service()
4>銷燬destroy()
5>單例多執行緒
6>load-on-startup讓servlet在伺服器啟動時已經實力初始化

2,web容器中的兩個map

3,ServletConfig

ServletConfig 是個介面,就相當於時servlet配置檔案。
一般而言,servletConfig物件只是只讀的,不可修改,故不存線上程安全問題
不同的servlet會建立不同的servletConfig物件,一個servlet就會存在一個servletConfig物件,二者的物件關係為一對一。

4個方法(parameter,引數)
1>getInitParameter(String name);獲得當前指定引數的值
2>getInitParameters();獲得一個列舉,裡邊放置所有的初始化引數名稱
3>getServletContext();獲得servlet上下文,便於獲得當前servlet上下文中設定的屬性等
4>getServletName();在web.xml檔案中配置的servletName標籤中值,即servlet的名字

4,servletContext(相當於一個application域)

servletContext,即servlet上下文,是個介面,是web應用中所有servlet在web容器中執行的上下文環境,隨著web應用啟動而啟動,隨著銷燬而銷燬。
其所含有的所有的servlet共享,均可以通過servletConfig獲得的servletContext對servlet上下文環境進行讀取和配置。
換句話而言,servletContext可以代表整個應用。故又名安排application

方法(attribute,屬性)
1>getInitParameter(String name);獲得當前指定引數的值
2>getInitParameters();獲得一個列舉,裡邊放置所有的初始化引數名稱
3>setAttribute();
4>getAttribute();
5>removeAttribute();這三個方法,在同一個servlet中不會同時執行,例如,添加了一個屬性後,然後刪除,再次檢視,該屬性依舊存在。
		  同時,設定的屬性不會放置XML檔案中,每重啟一次web容器後,即會失效。需重新設定。
6>getRealPath();獲取當前web應用下檔案的絕對路徑,基於碟符
7>getContextPath();獲得當前應用在web應用的名稱,相當於web應用的名稱,因為一個servletContext就相當於代表一個web應用。如:/Test01-servlet

5,歡迎頁面的設定

在<welcome-file-list>中設定<welcome-file>即可
當將其全部刪除後,容器也會存在預設歡迎頁面,在tomcat安裝目錄下的conf/web.xml檔案中。

6,關於servlet的url

1,精確路徑
2,萬用字元路徑,如/test/*
3,全路徑,/*或者/,其中/*會對所有的請求進行攔截,/除了動態的jsp請求不攔截,其他均攔截。在監聽器,過濾器中會涉及到對請求的攔截。
4,字尾名,如/*.do,/*.test,類似於上邊的萬用字元路徑。
5,一個servlet可以配置多個url,值得注意的是,萬用字元不能與字尾名同時存在,同時存在將導致伺服器無法啟動。
6,關於路徑的匹配原則,@1,路徑字尾優先匹配;@2,精確路徑優先匹配;@3,最長路徑優先匹配。   

7,GenericServlet

除了service()方法需要程式設計師的手動重寫,其他方法均空實現。

8,HttpServlet

9,HttpServletRequest(相當於一個request域)

1,請求的生命週期,太過短暫,對伺服器發出請求的時候建立,伺服器做出response相應後,請求over(),然後被destory();
2,請求引數,通過map這種集合框架進行接受,即所謂的鍵值對,key為String型別,value為String型別陣列,因為表單中的多選屬性可能會有多個值。
	方法:1>getParameterMap();
	          2>getParameterNames();
	          3>getParameterValues(String name);
	          4>getParameter(String name); 值得注意的是,如果name對應的是多個值,則其所得的值相當於getParameterValues(String name)[0]
3,關於request域
	方法:1>setAttribute();
	          2>getAttribute();
	          3>removeAttribute();
	          4>getRequestDispatcher(String path).forward(HttpServletRequest request, HttpServletResponse response);請求轉發
		關於請求轉發,我們會發現存在中文亂碼的問題,參照第6條。

4,關於doGet(),doPost(),還有service(),前兩者與後者同時執行的話,後者執行,前二者不執行。原因是重寫service方法的時候,未呼叫doget,這種方法,
     如果需要的話,在重寫的service中新增super.service()

5,關於獲取服務端相關資訊的方法。
	方法:1>getRequestURL();獲取請求的url,從請求協議開始的絕對路徑。如:http://127.0.0.1/Test01-servlet/test01
	          2>getRequestURI();獲取請求的uri,從專案開始的請求路徑。如:/Test01-servlet/test01
	          3>getContextPath(); 獲取當前web專案的名稱。如:/Test01-servlet,這個與通過servletContext的getContextPath獲得的web名稱一致。
	          4>getServletPath();   獲取當前servlet的名稱。如:/test01		
	          5>getPathInfo();       獲取當前萬用字元路徑的*號所代表的名稱。如:/aa/bb/cc或者null
		值得注意的是,URL = 協議+地址+URI
		                        URI = ContextPath + servletPath + PathInfo
	          6>getMethod();       獲得請求方式
                          7>getRemoteAddr(); 獲得客戶端瀏覽器的IP地址。
6,關於request請求的中文亂碼問題。關於請求轉發的亂碼問題也通過該方法去處理。
	username=%E9%A9%AC%E6%9E%97
	關於get,post的兩種提交方式。推送出不同的在方法。
	方法:Post ,setCharacterEncoding("編碼格式");
	          Get ,TomCat/conf/servlet.xml/8080埠號下新增encoding = “編碼格式”。
	          萬能解決方案,先解碼,在組碼。
		String username = request.getParameter("username");
		byte[] bytes = username.getBytes("iso8859-1");//解碼
		username = new String(bytes, "utf-8");//組碼 
7,關於響應的中文亂碼問題。
	當我們需要將Java程式碼處理後的結果向網頁中寫入時,我們需要通過response的getWriter(),獲得向網頁寫內容的流。
	但是當響應中文的時候,會出現中文亂碼問題,相應的解決方案為,response.setContextType("MIME型別;編碼格式");
	如編碼格式:charset = utf-8;
	值得注意的是:此設定需要在獲得PrintWriter之前,否則將無法對得到的流作用。

10,請求轉發與重定向

1,請求轉發。
	相當於在伺服器內進行跳轉。一次傳送,一次請求。	
	通過request.getRequestDispatcher(path).forward(request,response);
	達到請求轉發的效果,但此方法會導致惡意重新整理導致伺服器宕機等。
	這種情況不存在請求資料丟失的情況。

2,重定向。
	相當於在伺服器外進行跳轉。執行完請求之後,重定向至指定的路徑。
	通過response.sendRedirect(String location)達到重定向的效果。
	這種方式有效防止了惡意重新整理,但是因為重定向後又是一次新的請求,故會導致原始請求中的資料丟失。

3,關於重定向的資料傳輸,請參考get提交方式的引數提交形式,之後在其sendRedirect()時,將其按照物件格式寫入。

4,重定向的中文亂碼問題。
	首先,亂碼問題是出現在URL中的URI中,因為在換為URI的時候,已經發生亂碼現象了。
	故其解決方案:在正常解決亂碼問題的時候,對字串進行先解碼,在組碼。
	URLEncoder.encode(username,"utf-8");這個步驟在重定向之前執行。
	URLDecoder.decode(username,"utf-8");這個步驟在重定向後的檔案中執行。
	需要注意的是,重定向後的那個請求方式是get,而非post,故在其解決請求的中文亂碼問題時,需要使用萬能解決方案。
	
5,關於二者的選擇
	1,跳轉到其他應用,重定向
	2,重型應用執行完畢後,重定向。
	3,servlet之間的跳轉,重定向。防止表單重複提交,惡意重新整理
	4,其餘,一般請求轉發。

11,關於RequestDispatcher的兩個方法

1,forward()
	使用該方法,當前的servlet只能進行業務的處理,不能向瀏覽器傳送需要顯示的資料。只有請求轉發後的servlet具有向瀏覽器輸出的能力。
2,include()
	使用該方法,當前的servlet將整合請求轉發後的資源,將二者向瀏覽器傳送的資料進行合併(按照順序),然後傳送給瀏覽器

3,關於二者的不同
	forward()方法是在請求轉發後到達的頁面上開啟輸出流。而include()是在當前頁面開啟輸出流。
	如果在include()的情況下,在請求轉發後的頁面將輸出流進行了關閉,則導致之後的內容無法寫入。

12,關於訪問路徑的大問題

1,訪問路徑的組成。
	由資源路徑+資源名稱(最後一個/後的名稱)。組成
	資源路徑:協議+主機名:埠號+專案名 ;如http://127.0.0.1/Test01-servlet
	資源名稱: 如:/test01
	二者相加就是所謂的URL。
2,絕對路徑。
	就是URL,統一資源定位符
3,相對路徑
	需要注意的是,絕對路徑=參照路徑+相對路徑。
	根據相對路徑是否以/開頭,路徑出現的檔案位置不同,預設的參照路徑是不同的。
	1,以/開頭的相對路徑
		1>前臺路徑,其主要作用是查詢
			值得注意的是,前臺路徑的參照路徑為http://localhost:8080。
			所以在表單中的action需要填寫具體的專案名/servlet,例如:/Test01-servlet/one
		2>後臺路徑,其主要作用是標識
			後臺路徑的參照路徑為:http://localhost:8080/Test01-servlet
			其中,重定向中的路徑如果填寫/開頭的相對路徑,其參照路徑為tomcat的根,而非當前專案的根,所以重定向時,需要加上request.getContextPath()
	
	2,以路徑開頭的相對路徑
		其參照路徑均為當前訪問路徑的資源路徑。

13,Servlet的執行緒問題(同多執行緒安全解決方案基本一致)。

1,將需要的變數宣告為區域性變數
2,將使用成員變數的方法使用synchronized修飾。

14,Cookie

1,一種web開發技術。

2,其底層的資料結構相當於一個Map。鍵一般為name ,值一般為value,均為String字串。

3,cookie構造, Cookie(String name,String Value)
     將cookie新增至響應頭,addCookie(Cookie cookie)

4,修改繫結路徑
     cookie.setPath();一旦發生修改後,除非訪問與之對應的Path,否則該cookie將無法展示在請求頭上。

5,修改cookie的有效時間。(enpiry 逾期)
     cookie.setMaxAge(int enpiry),單位為秒
     如果不進行修改的話,其隨著session的失效而失效。
     值得注意的是,enpiry等於0 的時候,cookie產生後直接失效。

6,服務端讀取請求中的Cookie
      getCookies()

15,session

1,會話,一種web開發技術,開啟瀏覽器,傳送請求,直到瀏覽器關閉後,一次會話完成。

2,session物件的建立
	當需要使用session存放資料的時候,使用getSession(true)或者getSession()方法得到session。
	當需要使用session檢視資料的時候,使用getSession(false)的到session。

3,關於session域的操作(每個域基本上都有這個操作)
	方法:1>setAttribute();
	          2>getAttribute();
	          3>removeAttribute();

4,Session的工作原理
	不同的會話,對應不同的Session物件,系統使用神奇的JSessionID(32位長的隨機字串,這個東西相當於一個cookie,可以通過cookie檢視)
	一般客戶端不關閉,cookie就不會失效,所以瀏覽器中的cookie快取就不會消失,這就保證了會話的穩定,可以確保我們追蹤到該會話。

5,Session 的失效
	如果某個會話在指定的時間範圍內一直未發生訪問,session將失效。
	預設失效時間未30分鐘。從最後一次訪問session時開始計時。
	1,通過<session-config>
		<session-timeout>120</session-timeout>
	      </session-config>
	     控制其失效時間
	2,呼叫invalide()也會使session失效。
	
	3,cookie禁用後的session會話跟蹤。
		在會話欄的最後新增  ;jsessionid="當前會話的jsessionid"跟蹤會話,但是如此將導致會話的不安全。

16,關於域屬性。

servlet 中含有4大域,範圍從大到小分別是:
servletContext(application),可以完成跨會話共享資料
sessionContext,	              可以完成跨請求共享資料
requestContext,	              可以完成跨servlet共享資料,相當於跨page
pageContext	              最小的域,一般不用。

以上為自己的一些整理,原因無二,看過之後未曾記在心底,故整理一番。
同時,警醒自己一段話:不要著急,穩紮穩打,多多練習,會成功的。加油,親愛的自己,為了你規劃的未來。
                                                                                                       2018/11/15