1.概述:
Servlet是sun公司提供的一門用於開發動態web資源的技術。
Sun公司在其API中提供了一個servlet接口,用戶若想用發一個動態web資源
(即開發一個Java程序向瀏覽器輸出數據),需要完成以下2個步驟:
1.編寫一個Java類,實現servlet接口。
2.把開發好的Java類部署到web服務器中。按照一種約定俗成的稱呼習慣,通
常我們也把實現了servlet接口的java程序,稱之爲Servlet。
Servlet是JavaWeb的三大組件之一,它屬於動態資源。Servlet的作用是處理請求,
服務器會把接收到的請求交給Servlet來處理,在Servlet中通常需要:
1.接收請求數據;
2.處理請求;
3.完成響應.
2.Servlet原理分析:
生命週期: Servlet從創建到銷燬的一個過程
1. 系統默認在用戶第一次發送對這個servlet的請求時, 對服務器發起一個請求.
服務器會判斷是不是第一次訪問這個serlvet,如果是,截取用戶的請求路徑,
aa, 通過aa在配置文件中找到和aa對應的serlvet-name,FirstServlet,在
通過FirstServlet尋找到FirstServlet對應的class路徑,
com.itcast.servlets.FrisrServlet
2. tomcate服務器加載FirstServlet對應的字節碼到內存中.用反射創建這個字節碼對應
的一個實例. 調用FirstServlet的構造函數.
3. 創建好FirstServlet的實例之後,調用init方法,而且是隻調用一次.
4. 調用FirstServlet下的service方法對用戶進行相應. 當用戶後期不停的訪問這個
FirstServlet時,只要是發送對這個FirstServlet的請求,那麼FirstServlet都會用
Service方法對請求進行響應
5. 當服務器關閉的時候,調用FirstServlet下的destroy方法,而且僅調用一次.之後
FirstServlet對應的生成的實例從內存中退出.生命週期結束
3.GenericServlet
1.爲什麼要有GenericServlet?
我們在項目中實現一個動態資源,有時候更多的時候關注如何響應.沒有必要
關注太多的其他方法,例如servlet接口中的destroy,init…. 如果通過實現serlvet
接口的方式來實現Servlet資源文件,比較麻煩.所以有了GenericServlet.通過
GenericServlet實現Servlet動態資源,我們只需要重些service方法即可
2.GenericServlet深入研究
l GenericSevlet實現了3個接口Servlet,ServletConfig,Serializable
l GenericServlet實現了SerletConfig接口下的4個方法.
在GenericServlet中提供了一個成員變量:ServletConfig
GericServlet重些了Servlet接口下的init()方法,並且在這個方法
中,將tomcate服務器傳遞過來的config對象賦值給了GericServlet
下的實例成員
l GericServlet重些了Servlet接口的getServletConfig()方法,這個方法
就將GericServlet下的成員變量configServlet返回.
l GenericServlet重些了ServletConfig下的所有方法,就是通過
getServletConfig()來獲取這個配置對象的.
3.GenericServlet的init方法概述
GericServlet重些了Serlvet接口下的init方法. 但是同時還自身還提供了另外的一個
沒有參數的init方法.如果我們在編程中,需要重些init方法.重寫的是沒有參數的init
方法,如果重寫有參數的init方法,GenericSerlvet下的很多通過servletConfig對象進行
的操作都無法有效進行.
4.ServletContext
1. ServletContext概述
*在Tomcate啓動的時候會爲每個web應用,創建一個對應的ServletContext,
*每個應用都只有唯一的一個ServletContext,
*Tomcate關閉的時候,會銷燬每個web應用對應的ServletContext對象
ServletContext作用: 就是爲每個web應用中的動態資源之間共享數據,我們可以通過AServlet想當前應用
對應的ServletContext對象放入數據,BServlet可以從當前應用對應的ServletContext中獲取AServlet放入
的數據
2. 如何獲取ServletContext
目前爲止,實現Servlet一共有3種方式.
* 實現Servlet接口
在實現了Serlvet接口中的init方法中.利用Tomcate傳遞過來的config對象進行獲取ServletContext
* 繼承GenericSerlvet抽象類
getServletConfig().getServletContext();
getServletContext();
this.getServletContext();
* 繼承HttpServlet
getServletConfig().getServletContext();
getServletContext();
this.getServletContext();
3. ServletContext作爲域對象的功能
JavaWeb中有4個核心域對象 SerlvetContext HtttpSession ServletRequest PageContext
這4個核心域對象都具有存儲數據的功能,因爲域對象內部包裝了一個map.
ServletContext.setAttribute(key,vlaue);
如果重複向ServletContext中存放鍵一樣的鍵值對數據:eg: “k”èv1 “k”èv2 “k”èv3
那麼後邊放入的對象會覆蓋前期放入的對象的值
ServletContext.getAttribute(“key”);
ServletContext.getAttributeNames();
ServletContext.removeAttribute(“key”);
如果SerlvetContext這個域中沒有對應的key,那麼removeAttribute(“key”);這個方法什麼也不做.
4. 如何利用SerletContext對象獲取應用的初始化參數
通過Servlet獲取當前Servlet的配置參數
<servlet>
<servlet-name></servlet-name><servlet-class></servlet-class>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/school</param-value>
</init-param>
</servlet>
其他的Servlet無法獲取當前Servlet的配置參數.
如果我們想在多個Servlet之間獲取一些初始化的參數,只能通過SerlvetContext這個對象
5. 如何利用ServletContext獲取資源的相關方法
* 獲取web應用下指定資源的真實路徑
StringrealPath1=sc.getRealPath("/cc.txt");
StringrealPath2=sc.getRealPath("/WEB-INF/dd.txt");
* 獲取web應用下指定資源的輸入流
InputStreamis=sc.getResourceAsStream("/cc.txt");
InputStream is=sc.getResourceAsStream("/WEB-INF/dd.txt");
* 獲取web應用下指定目錄下的所有路徑
Set s=sc.getResourcePaths("/WEB-INF");
5、Response
1.Resonse的繼承結構:ServletResponse--HttpServletResponse2.Response代表響應,於是響應消息中的 狀態碼、響應頭、實體內容都可以由它進行操作,由此引伸出如下實驗:3.利用Response輸出數據到客戶端response.getOutputStream().write("中文".getBytes())輸出數據,這是一個字節流,是什麼字節輸出什麼字節,而瀏覽器默認用平臺字節碼打開服務器發送的數據,如果服務器端使用了非平臺碼去輸出字符的字節數據就需要明確的指定瀏覽器編碼時所用的碼錶,以防止亂碼問題。response.addHeader("Content-type","text/html;charset=gb2312")response.getWriter().write(“中文”);輸出數據,這是一個字符流,response會將此字符進行轉碼操作後輸出到瀏覽器,這個過程默認使用ISO8859-1碼錶,而ISO8859-1中沒有中文,於是轉碼過程中用?代替了中文,導致亂碼問題。可以指定response在轉碼過程中使用的目標碼錶,防止亂碼。response.setCharcterEncoding("gb2312");其實response還提供了setContentType("text/html;charset=gb2312")方法,此方法會設置content-type響應頭,通知瀏覽器打開的碼錶,同時設置response的轉碼用碼錶,從而一行代碼解決亂碼。4.利用Response 設置 content-disposition頭實現文件下載設置響應頭content-disposition爲“attachment;filename=xxx.xxx”利用流將文件讀取進來,再利用Response獲取響應流輸出如果文件名爲中,一定要進行URL編碼,編碼所用的碼錶一定要是utf-85.refresh頭控制定時刷新設置響應頭Refresh爲一個數值,指定多少秒後刷新當前頁面設置響應頭Refresh爲 3;url=/Day05/index.jsp,指定多少秒後刷新到哪個頁面可以用來實現註冊後“註冊成功,3秒後跳轉到主頁”的功能在HTML可以利用<meta http-equiv= "" content="">標籤模擬響應頭的功能。6.利用response設置expires、Cache-Control、Pragma實現瀏覽器是否緩存資源,這三個頭都可以實現,但是由於歷史原因,不同瀏覽器實現不同,所以一般配合這三個頭使用6.1控制瀏覽器不要緩存(驗證碼圖片不緩存)設置expires爲0或-1設置Cache-Control爲no-cache、Pragma爲no-cache6.2控制瀏覽器緩存資源。即使不明確指定瀏覽器也會緩存資源,這種緩存沒有截至日期。當在地址欄重新輸入地址時會用緩存,但是當刷新或重新開瀏覽器訪問時會重新獲得資源。如果明確指定緩存時間,瀏覽器緩存是,會有一個截至日期,在截至日期到期之前,當在地址欄重新輸入地址或重新開瀏覽器訪問時都會用緩存,而當刷新時會重新獲得資源。7.Response實現請求重定向7.1古老方法:response.setStatus(302);response.addHeader("Location","URL");7.2快捷方式:response.sendRedirect("URL");8.Response注意的內容:8.1對於一次請求,Response的getOutputStream方法和getWriter方法是互斥,只能調用其一,特別注意forward後也不要違反這一規則。8.2利用Response輸出數據的時候,並不是直接將數據寫給瀏覽器,而是寫到了Response的緩衝區中,等到整個service方法返回後,由服務器拿出response中的信息組成HTTP響應消息返回給瀏覽器。8.3service方法返回後,服務器會自己檢查Response獲取的OutputStream或者Writer是否關閉,如果沒有關閉,服務器自動幫你關閉,一般情況下不要自己關閉這兩個流。
6、Request:
Request代表請求對象,其中封裝了對請求中具有請求行、請求頭、實體內容的操作的方法1.獲取客戶機信息getRequestURL方法返回客戶端發出請求完整URLgetRequestURI方法返回請求行中的資源名部分,在權限控制中常用getQueryString 方法返回請求行中的參數部分getRemoteAddr方法返回發出請求的客戶機的IP地址getMethod得到客戶機請求方式getContextPath 獲得當前web應用虛擬目錄名稱,特別重要!!!,工程中所有的路徑請不要寫死,其中的web應用名要以此方法去獲得。2.獲取請求頭信息getHeader(name)方法 --- String ,獲取指定名稱的請求頭的值getHeaders(String name)方法 --- Enumeration<String> ,獲取指定名稱的請求頭的值的集合,因爲可能出現多個重名的請求頭getHeaderNames方法 --- Enumeration<String> ,獲取所有請求頭名稱組成的集合getIntHeader(name)方法 --- int ,獲取int類型的請求頭的值getDateHeader(name)方法 --- long(日期對應毫秒) ,獲取一個日期型的請求頭的值,返回的是一個long值,從1970年1月1日0時開始的毫秒值*實驗:通過referer信息防盜鏈String ref = request.getHeader("Referer");if (ref == null || ref == "" || !ref.startsWith("http://localhost")) {response.sendRedirect(request.getContextPath() + "/homePage.html");} else {this.getServletContext().getRequestDispatcher("/WEB-INF/fengjie.html").forward(request, response);}3.獲取請求參數getParameter(name) --- String 通過name獲得值getParameterValues(name) --- String[ ] 通過name獲得多值 checkboxgetParameterNames --- Enumeration<String> 獲得所有請求參數名稱組成的枚舉getParameterMap --- Map<String,String[ ]> 獲取所有請求參數的組成的Map集合,注意,其中的鍵爲String,值爲String[]獲取請求參數時亂碼問題:瀏覽器發送的請求參數使用什麼編碼呢?當初瀏覽器打開網頁時使用什麼編碼,發送就用什麼編碼。服務器端獲取到發過來的請求參數默認使用ISO8859-1進行解碼操作,中文一定有亂碼問題對於Post方式提交的數據,可以設置request.setCharacterEncoding("gb2312");來明確指定獲取請求參數時使用編碼。但是此種方式只對Post方式提交有效。對於Get方式提交的數據,就只能手動解決亂碼:String newName = new String(name.getBytes("ISO8859-1"),"gb2312");此種方法對Post方式同樣有效。在tomcat的server.xml中可以配置http連接器的URIEncoding可以指定服務器在獲取請求參數時默認使用的編碼,從而一勞永逸的決絕獲取請求參數時的亂碼問題。也可以指定useBodyEncodingForURI參數,令request.setCharacterEncoding也對GET方式的請求起作用,但是這倆屬性都不推薦使用,因爲發佈環境往往不允許修改此屬性。4.利用請求域傳遞對象生命週期:在service方法調用之前由服務器創建,傳入service方法。整個請求結束,request生命結束。作用範圍:整個請求鏈。作用:在整個請求鏈中共享數據,最常用的:在Servlet中處理好的數據要交給Jsp顯示,此時參數就可以放置在Request域中帶過去。5.request實現請求轉發ServletContext可以實現請求轉發,request也可以。在forward之前輸入到response緩衝區中的數據,如果已經被髮送到了客戶端,forward將失敗,拋出異常在forward之前輸入到response緩衝區中的數據,但是還沒有發送到客戶端,forward可以執行,但是緩衝區將被清空,之前的數據丟失。注意丟失的只是請求體中的內容,頭內容仍然有效。在一個Servlet中進行多次forward也是不行的,因爲第一次forward結束,response已經被提交了,沒有機會再forward了總之,一條原則,一次請求只能有一次響應,響應提交走後,就再沒有機會輸出數據給瀏覽器了。