http://blog.csdn.net/cendy_69576750/article/details/7930973
1、In Action
(1)寫一個類繼承HttpServlet;
(2)重寫其中的方法。
1、TIPS
(1)Servlet生命周期
每個Servlet都有自己的生命周期。Servlet的生命周期由web伺服器維護。
伺服器在啟動時(配置了load-on-startup,且值不為0)或第一次請求servlet時(若沒有設定load-on-startup,或值為0)初始化一個Servlet對象,然後用這個Servlet對象處理所有用戶端請求。伺服器關閉時才銷毀這個Servlet對象。
無論請求多少次Servlet,最多隻有一個Servlet執行個體。多個用戶端并發請求Servlet時,伺服器會啟動多個線程分别執行該Servlet的service()方法。service()方法裡通過請求的方法來決定是調用doGet()還是doPost()方法。
從Java EE 5開始,servlet增加了兩個影響servlet生命周期的注解:@PostConstruct和@PreDestroy。這兩個注解用來修飾非靜态的void()方法,且此方法不能抛出異常聲明。
PreDestroy中的Destroy指的是servlet的銷毀,而不是destroy()方法。
servlet的生命周期:
伺服器加載servlet——servlet構造函數——@PostConstruct修飾的方法——init()方法——service()方法——destroy()方法——@PreDestroy修飾的方法——伺服器解除安裝servlet完畢。
支援@PostConstruct和@PreDestroy注解的伺服器要支援到servlet2.5及以上規範。Tomcat 5僅支援到servlet2.4規範。
伺服器啟動時,會周遊web應用的WEB-INF/classes下的所有class檔案與WEB-INF/lib下的所有jar檔案,以檢查哪些類使用了注解。不支援注解的伺服器不會這樣做。若應用程式中沒有使用任何注解,可在web.xml中設定<web-app>的metadata-complete屬性為true來關閉伺服器啟動時例行的注解檢查。
(2)servlet之間的跳轉
servlet之間可以互相跳轉,從一個servlet程式跳轉到另一個servlet。servlet的跳轉可以實作程式子產品化。MVC架構中都使用了servlet跳轉。
轉向(Forward)是通過RequestDispatcher對象的forward()方法實作的。RequestDispatcher通過HttpServletRequest(或者ServletContext對象)的getRequestDispatcher()方法獲得,其中的參數必須以/開始,/表示本webApp的根目錄。可以Forward到servlet、jsp頁面,甚至可以跳轉到另外一個檔案或WEB-INF檔案夾下的檔案。
重定向(Redirect):重定向是利用伺服器傳回的狀态碼實作的。用戶端浏覽器請求伺服器時,伺服器端會傳回一個狀态碼。伺服器端通過response的setStatus()方法設定狀态碼。
狀态碼:
200表示一切正确; 301、302表示該資源已不存在或換了位址,用戶端需重定向到一個新的資源,伺服器響應中會附帶這個新資源位址;401表示沒有權限通路;404表示資源不存在;
HttpServletResponse把setStatus()和setHeader()方法封裝成sendRedirect()方法;
如:response.setStatus(302);
response.setHeader("Location","http://www.baidu.com");
現在可以直接調用response.sendRedirect("http://www.baidu.com");
自動重新整理(Refresh):
不僅可以實作一段時間後自動跳轉到另一個頁面,還可以實作一段時間後自動重新整理本頁面。如:
response.setHeader("Refresh", "1000; URL=http://www.baidu.com" );
URL指定的網址是1s後跳轉的頁面。當URL設定的路徑為servlet自己的路徑時,就會每隔1s自動重新整理本頁面一次。自動實作和重定向原理一樣,當為時間設為0,URL設為一個網址,效果就是重定向。
(3)servlet是線程不安全的。要謹慎使用類的變量。
線程安全:指多線程并發執行時,會不會出現問題。若有問題,則是線程不安全的。
多個使用者同時請求同一個servlet時,Tomcat會派生出多條線程執行servlet的代碼。是以servlet是線程不安全的。
多線程并發的讀寫會導緻資料不同步的問題。
多線程并發的讀寫servlet類屬性會導緻資料不同步,但若隻是并發地讀取屬性而不寫入,則不存在資料不同步問題。是以servlet裡的隻讀屬性最好定義為final類型。
(4)一個servlet類隻會有一個執行個體。
(5)Filter
Filter、Listener是servlet規範裡德兩個進階特性。不同于servlet,它們不用于處理用戶端請求,隻用于對request、response進行修改或者對context、session、request事件進行監聽。
多個Filter就組成了一個FilterChain。
一個Filter必須實作javax.servlet.Filter接口。Filter需要配置在web.xml中才能生效。其中<dispatcher>配置到達servlet的方式。預設為request。
request:表示僅當直接請求servlet時才生效。
forward:表示僅當某servlet通過forward到該servlet時才生效。
多個Filter的執行有先後順序,規則是<filter-mapping>配置在前面的Filter執行要早于配置在後面的Filter。
頁面編碼方式與Filter編碼方式必須一緻。此外,若表單是get方式送出的,需要修改Tomcat的/conf/server.xml檔案,指定URIEncoding,預設為ISO-8859-1,否則依然會亂碼。
Filter中,若在chain.doFilter()上加一個try....catch語句,就能捕捉servlet中抛出的異常,然後根據不同的異常進行不同的異常處理。
Filter和特定的URL關聯,隻有當客戶請求通路此URL時,才會觸發過濾器調用doFilter方法!
過濾器的初始化,即被調用init()方法是webApp應用被Tomcat加載就執行。
Filter配置多個url-pattern:
http://weidongke123-126-com.iteye.com/blog/1032546
(6)Listener
Listener用于監聽Java Web程式中的事件,如建立、屬性修改、删除session、request、context等,并觸發相應的事件。Servlet2.5規範中共有8種Listener,分别完成對不同僚件的監聽。其中兩個Listener能監聽存放在session中的對象。共有6種Event。
Java web程式隻要記住該類事件觸發時一定會調用相應的Listener相應方法,并傳回一個Event對象。觸發時,伺服器會順次執行各個Listener的相應方法。
HttpSessionListener接口、ServletContextListener、ServletRequestListener分别用于監控session、context、request的建立和銷毀。
HttpSessionListener:監聽session的建立和銷毀。建立session時執行sessionCreated()方法。逾時或執行session.invalidate()時執行sessionDestroyed()方法。
ServletContextListener:監聽context的建立和銷毀。context代表目前的web應用程式。伺服器啟動或熱部署war包時執行contextInitialized()方法。伺服器關閉或隻關閉該web時會執行contextDestroyed()方法。該listener可用于啟動時擷取web.xml裡配置的初始化參數。
ServletRequestListener:監聽request的建立和銷毀。使用者每次請求request都會執行requestInitialized()方法。request處理完畢自動銷毀前執行requestDestroyed()方法。
HttpSessionAttributeListener、ServletContextAttributeListener、ServletRequestAttributeListener用于監聽session、context、request的屬性變化。當向被監聽對象中添加、修改、删除屬性時,會分别執行對應的方法。
HttpSessionBindingListener和HttpSessionActivationListener用于監控session内的對象。此兩個Listener不需要在web.xml中聲明。
HttpSessionBindingListener:當對象被放到session裡時,執行valueBound()方法。當對象被從session裡移除時,執行valueUnbound()方法。對象必須實作該Listener接口。
HttpSessionActivationListener:伺服器關閉時,會将session裡的内容儲存到硬碟上。伺服器重新啟動時,會将session内容從硬碟上重新加載。當session裡的對象被鈍化時,執行sessionWillPassivate()方法。當對象被重新加載時,執行sessionDidActtivate()。對象必須實作該Listener接口。
<listener>标簽一般配置在<servlet>标簽的前面。
四個session監聽器接口和與之關聯的兩個session事件。
(7)ServletContext
servlet容器在啟動時會加載web應用,并為每個web應用建立唯一的ServletContext對象,被同一個web應用中所有元件共享。
在web運作期間,ServletContext設定的屬性一直存在。當web應用被關閉時(如關閉Tomcat),servlet容器銷毀ServletContext對象。
(8)cookie
通過cookie的setMaxAge()方法設定cookie的有效期。
(9)filter、listener、servlet啟動順序
http://www.iteye.com/topic/1133753
2、PS
(1) servlet
init() service() destroy()
其中init()、destroy()方法隻會被伺服器執行一次。
(2) ServletContext Listener
contextInitialized() contextDestroyed()
(3) Filter
init() doFilter() destroy()
其中init()是web程式啟動時調用此方法,用于初始化該Filter;
chain.doFilter()将請求傳給下一個Filter或servlet;是以,在doFilter()方法中一定要執行chain.doFilter(),否則reqeust不會交給後面的Filter或servlet。
web程式關閉時調用destroy()方法;
init()和destroy()方法隻會被調用一次,doFilter()方法每次有用戶端請求都會被調用一次。
(4)
所有HTTP頭資料都可以通過request相應的方法得到。
servlet規範是建立在HTTP規範基礎上的。
servlet有一個方法getLastModified(),傳回該文檔的最後修改時間,預設為-1,表示該文檔永遠是最新的。
(5)Java web目錄結構
web程式部署在Tomcat的/webapps下面。如webapps/web1、webapps/web2。
這兩個不同的web應用分别稱為兩個context,路徑/web1、/web2稱為上下文路徑(ContextPath)。
若不使用上下文路徑,web程式需放到webapps/ROOT下面,ROOT檔案夾下的程式使用http://localhost:8080/通路。
根據servlet規範,web程式有自己特定的結構,部署時必須按照這樣的結構部署。WEB-INF檔案夾,裡面有classes和lib檔案夾,web.xml檔案。
Java web應用程式的WEB-INF有個特性:任何人都不能通過浏覽器直接擷取其檔案夾下面的檔案。WEB-INF下的檔案是受保護的,這保證了檔案的安全性。WEB-INF下的檔案不能通過浏覽器直接擷取到,但可以通過程式讀取到。
(6)以get方式通路時,會執行doGet方法,但執行前會先執行getLastModified方法,若浏覽器發現此方法傳回的值與上次通路時傳回的值相同,則認為此文檔沒有更新,浏覽器采用緩存而不執行doGet方法。若此方法傳回-1,則認為是時刻更新的,總是執行doGet方法。
以post方式通路時,會執行doPost方法,執行前不會執行getLastModified方法。
(7)在web.xml中,<servlet>标簽裡可以使用<init-param>标簽配置初始化參數,
包括一個參數名稱<param-name>和一個參數值<param-value>。
servlet中可使用getServletContext().getInitParameter()取得配置的初始化參數值。
在servlet中,通過getInitParameter()來擷取初始化參數值。
還可以使用getInitParameterNames()方法傳回所有的參數名稱。
這些初始化的參數,也可由ServletConfig對象取得。Servlet提供getServletConfig()傳回ServletConfig對象。
(8)上下文參數(context-param)
由于init-param是配置在<servlet>标簽裡的,隻能由這個servlet來讀取。它不是全局的參數,不能被其它的servlet讀取。若要配置一個所有servlet都能讀取的參數,需要用到上下文參數。使用标簽<context-param>配置。如:
<context-param>
<param-name>name</param-name>
<param-value>aaa</param-value>
</context-param>
擷取context-param可使用ServletContext對象。Servlet中通過getServletConfig().getServletContext()來擷取一個ServletContext對象。使用ServletContext的getInitParameter()方法來擷取指定名稱的全局初始化參數,通過getInitParameterNames()擷取所有的context-param參數名稱。
servletContext.getRealPath();傳回web應用程式内相對網址對應的絕對路徑;
(9)從Java EE 5開始,<servlet-mapping>标簽可以配置多個<url-pattern>。*表示任意長度的字元串。
web程式設計的過程就是通過請求分析客戶需要什麼資訊或者進行了什麼操作,然後進行一系列的處理,最後通過響應結果顯示給客戶。
用戶端浏覽器發出的請求被封裝成為一個HttpServletRequest對象。
伺服器對用戶端浏覽器做出的響應被封裝成了一個HttpServletResponse對象。
response.getWriter()用于寫字元型資料,response.getOutputStream()用于寫二進制資料。
不同的輸出類型需要聲明不同的ContentType屬性。
(10)圖檔驗證碼的原理:
伺服器生成一個包含随機的字元串的圖檔發給用戶端,用戶端送出資料時需要填寫字元串作為驗證。由于字元串儲存在圖檔中,機器很難識别,進而可防止有人使用計算機程式惡意發送資訊的目的。
<img src=""/>顯示圖檔驗證碼,如:<img src="servlet/IdentityServlet"/>。
(11)資源注射(@Resource):是Java EE5規範,Tomcat6開始支援的功能。
即不需要servlet主動去讀取資源,Tomcat啟動時會把web.xml裡配置的資訊主動注射到servlet裡。
注解是一種特殊的接口。
如:
@Resource(name="messageNameInWebXml")
private String message;
表示message的值會在servlet運作時動态注入。web.xml中配置一個名為messageNameInWexXml的參數。在web.xml中使用标簽<env-entry>配置。
(12)get送出時URL總長度不能超過255個字元。
(13)解析二進制資料流比較麻煩,有很多類庫以及完成了這項工作。如Apache Commons Fileupload類庫。是以使用Apache的commons-fileupload實作檔案上傳。commons-fileupload從1.2版本開始支援上傳監聽器,能實時監聽上傳情況。
(14)實時顯示上傳進度的原理
伺服器在處理上傳檔案的同時,将上傳檔案的資訊如檔案總長度、已上傳多少、傳輸速率等寫入session。用戶端浏覽器利用ajax技術新開一個獨立的線程從session中擷取上傳進度資訊,并實時顯示。ajax技術能不重新整理頁面擷取伺服器資料。
commons-fileupload1.2版本支援上傳監聽。監聽器需要實作ProgressListener接口。并需要把監聽器添加到上傳元件上。
添加了監聽器後,上傳元件在上傳檔案時,會不斷回調方法,回傳資料。
上傳檔案時,若不對表單做特别處理,送出表單後會轉到另一個頁面,造成頁面的重新整理。在新頁面顯示之前,浏覽器會因等待而顯示白屏。可以對表單做一些處理,使送出表單後原頁面内容不變,同時顯示進度條,直到檔案上傳結束。方法是更改form的target屬性。target屬性預設為_self。若target為預設值,則送出後的新頁面會在目前視窗顯示,造成目前視窗短暫白屏。在頁面内添加一個隐藏的iframe(指定iframe的寬高為0實作隐藏),把target屬性指定為該iframe,則送出後的新頁面會在iframe内顯示。故上傳檔案時目前頁面看不出任何變化。
(15)内容替換Filter
内容替換Filter的工作原理是:在servlet将内容輸出到response時,response将内容緩存起來,在Filter中進行替換,然後再輸出到用戶端浏覽器。由于預設的response不能嚴格緩存輸出内容,是以需要自定義一個具備緩存功能的response。可以通過繼承javax.servlet.http.HttpServletResponseWrapper類實作。該類覆寫了getWriter()方法,當Servlet中使用該response對象調用getWriter()來輸出内容時,内容将被輸出到CharArrayWriter對象(字元數組Writer)中,達到緩存的效果。
自定義的response重寫getWriter()方法:
public PrintWriter getWriter() throws IOException {
return new PrintWriter(charArrayWriter);
}
Filter中将自定義的response傳進servlet中。如:
HttpCharacterResponseWrapper response = new HttpCharacterResponseWrapper((HttpServletResponse)res);
chain.doFilter(req, response);
String output = response.getCharArrayWriter().toString();
//對output進行處理
PrintWriter out = res.getWriter();
out.write(output);
(16)GZIP壓縮Filter
網站常使用GZIP壓縮算法對網頁内容進行壓縮,然後傳給浏覽器,以減少資料傳輸量、提高響應速度。浏覽器收到GZIP壓縮資料後會自動解壓并正确顯示。GZIP加速常用來解決網速慢的瓶頸。
判斷浏覽器是否支援GZIP自動解壓的依據是浏覽器提供的Header資訊(Accept-Encoding),
(17)使用Filter在圖像上動态加上一個Logo
工作原理和GZIP類似,先把圖像資料緩存起來,然後對圖像資料進行水印處理後輸出到浏覽器。