關於Servlet的個人心得
阿新 • • 發佈:2018-11-17
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