Servlet基礎學習指導

一、Servlet
1.servlet的概念:
sun提供的開發動態web資源的技術,本質上是一段java小程序。可以配置到    web應用中在servlet容器中運行。
2.Servlet開發步驟
寫一個java類Servlet接口
在web.xml中對這個Servlet進行配置
二、Servlet繼承結構
Servlet -- 接口 定義了Servlet的基本的方法
|
|--GenericServlet 抽象類 通用Servlet 實現了Servlet接口中的大部分     方法,只有service方法沒有實現
|
|--HttpServlet 類 繼承了GenericServlet,在GenericServlet的基礎上增加了很多和HTTP協議相關的支持,實現了Service方法,在service方法中判斷當前的請求         方式,調用對應的doXXX方法。我們繼承HttpServlet,不會直接覆蓋service,只需要覆蓋doGet 和 doPost,針對get和post提交做處理即可。
三、Servlet調用過程圖及生命週期:

Servlet會在第一次被訪問時創建出來。創建出來後立即調用init方法執行初始化的操作。從此以後駐留在內存中爲後續的請求服務。每當由請求訪問該Servlet時,都會導致     service方法執行。直到服務器關閉或web應用移除出容器時,隨着web應用的銷燬,Servlet被銷燬,在銷燬Servlet之前調用destory方法執行一些善後的工作。


四、Servlet在web.xml中配置細節
<servlet> -- 配置一個Servlet
<servlet-name>SecondServlet</servlet-name> -- 爲Servlet起一個名字
<servlet-class>cn.com.tarena.web.SecondServlet</servlet-class> -- Servlet處理類的全路徑名稱
<init-param> -- 配置初始化參數,可以不想在Servlet中寫死的內容配置在此處,通過ServletConfig對象可以獲取,可以配置多個
<param-name>name1</param-name> --參數名
<param-value>value1</param-value> --參數值
</init-param>
<load-on-startup>1</load-on-startup> -- 可選項,一旦配置了這個選項,則這個Servlet會在web應用加載時立即創建。
</servlet>
<servlet-mapping> -- 一個Servlet可以 配置多個Servlet-Mapping
<servlet-name>SecondServlet</servlet-name> -- 爲哪個名字的Servlet配置
<url-pattern>/servlet/SecondServlet</url-pattern> -- 配置爲哪個虛擬路徑,通過這個虛擬路徑就可以訪問這個Servlet
</servlet-mapping>


<url-pattern>配置的細節:
可以直接寫一個路徑
可以使用*匹配符,但是隻能時/開頭/*結尾 或 *.後綴 的形式
由於*號匹配符的引入,可能會造成一個訪問路徑被多個url-pattern所匹配,那到底哪一個起作用呢?
匹配的規則是 哪個最像找哪個,*.後綴 永遠優先級最低。


如果某一個Servlet的對外訪問路徑被配置爲了一根正斜槓,則改Servlet成爲缺省Servlet,其他Servlet不處理的請求由他來處理。
其實訪問任何資源最終都時由Servlet輸出的,包括靜態資源和404也是由在tomcat中conf文件中的web.xml中配置的缺省Servlet輸出的
一般不要自己配置缺省Servlet,配了就無法訪問靜態web資源和404頁面了
五、ServletConfig
代表當前Servlet在web.xml中的配置信息
獲取當前Servlet中配置的初始化參數
getInitParameter
getInitParameterNames
獲取ServletContext對象

六、Request
ServletRequest--通用的Request,提供了一個Request應該具有的基本方法
|
|--HttpServletRequest -- 在ServletRequest的基礎上增加了一些和Http協議相關的方法 HttpServletRequest是一個接口,被HttpServletRequestWrapper類實現。
同時HttpServletRequestWrapper類繼承ServletRequestWrapper,在重寫HttpServletRequest接口中的方法,調用ServletRequestWrapper中的方法。


代表一個請求


獲取客戶機信息
getRequestURL 方法返回客戶端發出請求完整URL
getRequestURI 方法返回請求行中的資源名部分
getQueryString 方法返回請求行中的參數部分
getRemoteAddr方法返回發出請求的客戶機的IP地址
getMethod 得到客戶機請求方式
getContextPath 獲得當前web應用虛擬目錄名稱
獲取請求頭信息
getHeader(name)方法 --- String 
getHeaders(String name)方法 --- Enumeration<String>
getHeaderNames方法 --- Enumeration<String>
getIntHeader(name)方法  --- int
getDateHeader(name)方法 --- long(日期對應毫秒)
請求參數信息
getParameter(name) --- String 通過name獲得值
getParameterValues  --- String[ ] 通過name獲得多值 checkbox
getParameterNames  --- Enumeration<String> 獲得所有name
getParameterMap  --- Map<String,String[ ]> key :name value: 多值


請求參數的亂碼原理及解決:
瀏覽器用什麼碼錶打開表單就用什麼碼錶提交請求參數。所以我們可以通過控制瀏覽器打開表單頁面時的碼錶來控制瀏覽器提交請求參數時的碼錶。
而服務器如果不指定默認用iso8859-1來解碼請求參數,而iso8859-1中沒有中文,從而產生亂碼。
解決方法:
如果是POST提交,可以在獲取請求參數之前執行request.setCharacterEncoding("xxx");解決亂碼。注意這行代碼必須寫在獲取任何請求參數之前,如果這行代碼之前        獲取過任何請求參數則這行代碼無效。
這種方式只對請求的實體內容起作用,所以對GET提交的請求參數無效。
對於GET提交的請求參數,可以手動的編解碼來解決亂碼。
username = new String(username.getBytes("iso8859-1"),"utf-8");
這種方法從原理上解決亂碼,對於GET和POST提交均有效。


路徑難題:
在web程序中,當我們需要讀取資源文件時,發現,如果寫相對路徑就到程序的啓動目錄 tomcat/bin 下找資源了,如果寫絕對路徑 就到 tomcat所在的根目錄下找資源,如     果寫盤符開始的路徑可以找到資源,但是一旦換了一個發佈環境這個路徑很可能是錯的。


七、ServletContext
代表當前web應用
當服務器啓動,web應用加載完成後,立即創建一個ServletContext對象代表當前web應用。從此駐留在內存中唯一的代表當前web應用。直到服務器關閉或web應用移除出容器時,   隨着web應用的銷燬而銷燬。

1.獲取ServletContext
servletConfig.getServletContext();
this.getServletContext();
2.加載資源文件
路徑難題

ServletContext.getRealPath("xxxxx");//會在傳入的路徑前拼接上當前web應用的硬盤路徑。


~另外在沒有ServletContext的環境下,我們可以使用類加載器加載資源。但是要注意,類加載器加載資源時,路徑要相對於平常加載類的位置進行計算。
ClassLoader.getResource().getPath();
ClassLoader.getResourceAsStream();
3.讀取web應用的初始化參數
我們可以在web.xml的根目錄下爲整個web應用配置一些初始化參數。
<Context-param>
可以通過ServletContext對象來讀取這些整個web應用的初始化參數。
servletContext.getInitParamter();
servletContext.getInitParamterNames();


4.作爲域對象使用
域:一個對象具有了一個可以被看見的範圍,那麼利用這個對象身上的Map,可以在這個範圍內共享數據,這樣的對象叫做域對象。
javaweb中一共有四大作用域,其中ServletContext就是其中最大的一個。


setAttribute(String name,Object value);
getAttribute(String name);
removeAttribute(String name);
getAttributeNames();


ServletContext域的
作用範圍:
在整個web應用中共享數據
生命週期:
服務器啓動web應用加載ServletContext創建,直到服務器關閉或web應用移除出容器時隨着web應用的銷燬,ServletContext銷燬。
主要的作用:
在整個web應用中共享數據。




paramter -- 請求參數
initparamter -- 初始化參數
attribute -- 域屬性
八、Response
1.Response的繼承結構
ServletResponse -- 最基本的響應對象,只有最近本響應應該具有的方法
|
|--HttpServletResponse -- 在ServletResponse的基礎上增加了很多和Http協議相關的方法。
2.常用方法
設置狀態碼:
setStatus(int sc)
setStatus(int sc, String sm)
設置相應頭:
setIntHeader(String name, int value)
setHeader(String name, String value)
setDateHeader(String name, long date)
設置實體內容:
PrintWriter getWriter()
ServletOutputStream getOutputStream();


3.輸出數據到客戶端
getOutputStream 輸出數據產生亂碼,時因爲服務器發送數據時採用的編碼和瀏覽器打開時採用的編碼不一致造成的。(瀏覽器默認用平臺碼打開)。可以通過設置Content-    Type相應頭通知瀏覽器用指定編碼打開數據,解決亂碼問題。
getWriter 如果不指定編碼服務器用默認的iso8859-1將字符轉換爲字節,在服務器端就產生亂碼。可以通過response.setCharacterEncoding()來指定服務器用什麼編碼將   字符轉換爲字節,從而解決這種亂碼,同時也要保證通過設置Content-Type頭來通知瀏覽器用對應碼錶打開,就沒有亂碼
response.setContentType(),即會通知瀏覽器打開用的編碼,也會通知服務器用什麼編碼發送,一行代碼搞定響應亂碼。


response輸出數據時的細節問題:
getOutputStream和getWriter這兩個方法互相排斥,調用了其中的任何一個方法後,就不能再調用另一方法。
getOutputStream和getWriter獲取的流服務器會幫我們關閉,不需要我們手動關閉。


4.禁止緩存
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
九、資源跳轉的三種方式
1.定時刷新
原理:refresh頭

response.getWriter().write("恭喜您註冊成功,3後後回到主頁。。。");
response.setHeader("refresh", "3;url="+request.getContextPath()+"/index.html");


2.重定向
原理:302+Location


        方式一:
 response.setStatus(302);
 response.setHeader("Location", "/Day06/index.jsp");
        方式二:
 response.sendRedirect("http://www.baidu.com");


兩次請求兩次響應
地址欄發生變化
可以跨站點進行資源跳轉


3.請求轉發
原理:服務器內部的資源跳轉
request.getRequestDispatcher("xxxx").forward(request,response);


只有一次請求一次響應,對於瀏覽器來說它不知道也不關心所獲得的響應是否經過請求轉發。
地址欄不發生變化
不可以跨站點進行資源跳轉,只能時當前web應用內部纔可以。


注意事項:
轉發類似於方法調用,轉發之後的代碼在轉發執行結束後仍然會執行。


鏈式轉發允許1->2->3->。。。
轉發不能形成環 1->2->3->1
一個Serlvet不允許多次轉發 1->2
1->3


轉發前,如果已經由數據寫入了響應的實體內容,則在轉發時首先清空這些內容。
轉發前,如果已經有數據被打給了瀏覽器,則轉發不成功。


4.利用Request域在請求轉發時傳遞參數
Request是一個域對象
setAttribute
getAttribute
removeAttribute
getAttributeNames


作用範圍:
在整個請求鏈上都可以操作
生命週期:
一次請求開始創建出request對象,一次響應結束request對象被銷燬,在這個期間request域存活。
主要作用:
在請求轉發時在整個請求鏈上傳遞信息。


5.請求包含
請求包含可以將多個資源的輸出合併爲一個輸出。
request.getRequestDispatcher("xxx").include(request,response);


注意:被包含的Servlet程序不能改變響應消息的狀態碼和響應頭,如果它裏面存在這樣的語句,這些語句的執行結果將被忽略

6.重定向和轉發的比較
請求重定向:兩次請求兩次響應 地址欄會發生變化 可以跨站點進行資源的跳轉 兩個request 
請求轉發:一次請求一次響應 地址欄不會發生變化 不可以誇站點進行資源跳轉 一個request


如果在資源跳轉的時候,希望通過request域傳遞數據,必須用請求轉發
如果想要在資源跳轉時,改變地址欄,必須用請求重定向。
如果是要跨站點資源跳轉必須用請求重定向。
如果想要更新刷新操作,必須用請求重定向。


如果轉發和重定向都可以的情況下,優先用請求轉發,可以減少訪問服務器的次數,減輕服務器的壓力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章