JavaWeb 三大器--Listener、Filter 和Interceptor 總結


說明:web.xml的加載順序是:【Context-Param】->【Listener】->【Filter】->【Servlet】,而同個類型之間的實際程序調用的時候的順序是根據對應的Mapping的順序進行調用。

詳細介紹:web.xml加載順序與web.xml常用節點解析

一、背景

這段時間因為工作不忙,所以有時間來總結整理一下之前遇到的一些問題。在之前項目開發過程中碰到過關於攔截器、過濾器之類的問題(發現自己基礎真的薄弱,不過沒關系知識一點一滴積累),索性就記錄下來。由於筆者知識水平有限,如有不對的地方歡迎批評指正。

二、概念

在講解三大器之前,我們需要對Servlet 有所了解,因為這個通常是我們在接觸Javaweb 時最先了解到的知識點。

1. Servlet

Servlet 是sun 公司提供的一門用於開發動態web 資源的技術,主要功能在於交互式地瀏覽和修改數據,生成動態Web 頁面,我們實際開發應用中,一般不需要去研究Http 協議,只要擴展servlet 接口,即可實現web 服務器應用程序的開發。通俗來講,就是這個技術可以實現一個由客戶端發起請求-->服務器端處理-->客戶端得到響應的功能。額。。。還不是很有概念,那Servlet 得生命周期總有印象吧?

這里說個題外話,提到Servlet 的生命周期,首先,這個在面試時經常被問到。

Servlet 生命周期可被定義為從創建直到毀滅的整個過程。以下是 Servlet 遵循的過程(三個重要方法):

init () 方法進行初始化:

 在Servlet的生命周期中,僅執行一次init()方法,它是在服務器裝入Servlet時執行的,可以配置服務器,以在啟動服務器或客戶機首次訪問Servlet 時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重復執行init();

②Servlet 調用 service() 方法來處理客戶端的請求:

它是Servlet的核心,每當一個客戶請求一個HttpServlet 對象,該對象的Service() 方法就要調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對象作為參數。在HttpServlet 中已存在Service()方法。默認的服務功能是調用與HTTP請求的方法相應的do功能。

③Servlet 通過調用 destroy() 方法終止(結束):

僅執行一次,在服務器端停止且卸載Servlet 時執行該方法,有點類似於C++ delete 方法。一個Servlet 在運行service() 方法時可能會產生其他的線程,因此需要確認在調用destroy() 方法時,這些線程已經終止或完成。

Servlet 的生命周期的話還需要加上在init() 之前有一個加載和實例化Servlet(反射機制)的過程。

整個過程大概是這樣的:

其次,還記得在大三那會去實習,組長給我們講解Java 知識的時候就有提到過Servlet。記得當時是做一個登錄跳轉的功能,寫一個Java 類,實現Servlet 接口,然后寫doGet() 和doPost() 方法,因為這里要處理亂碼來着,搞了半天。。。至此,這兩點大概是我對Servlet 的最深印象了吧。那么,之后的工作中為什么仿佛徹底與這東西無緣了一樣。時至今日,再次提起這個東西才知道一直有在用,只是自己不知道而已。

回到正題,現在我們的Servlet 哪里去了呢?沒錯,它沒有消失,而是在我們的web.xml 文件:

     <!-- spring mvc servlet -->
	<servlet>
		<description>spring mvc servlet</description>
		<servlet-name>springMvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<description>spring mvc 配置文件</description>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springMvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping> 

通過這種方式我們就實現對*.do 這樣的請求進行統一處理,通常我們也把實現了servlet 接口的java 程序,稱之為Servlet。如果換成以前的寫法,就是這樣的:

Servlet 類:

/**
 * 用戶登錄校驗
 * Servlet implementation class LoginServlet
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public LoginServlet() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//String username = request.getParameter("username");
		//String password = request.getParameter("password");
		//...
		// success
		doGet(request, response);
	}

}

web.xml 配置:

<servlet>
		<!-- Servlet的注冊名稱 -->
		<servlet-name>LoginServlet</servlet-name>
		<!-- Servlet的完整類名 -->
		<servlet-class>com.github.servlet.LoginServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<!-- Servlet的注冊名稱 -->
		<servlet-name>LoginServlet</servlet-name>
		<!-- Servlet的對外訪問路徑 -->
		<url-pattern>/servlet/loginServlet</url-pattern>
	</servlet-mapping>

訪問路徑

看到這里終於明白,現在每天都在用的DispatcherServlet 正是以前所接觸過得Servlet。進一步跟蹤DispatcherServlet 發現果然,他確實是實現了HttpServlet 接口

2.Listener 

監聽器,從字面上可以看出listener 主要用來監聽時用。通過listener 可以監聽web 服務器中某一個執行動作,並根據其要求作出相應的響應。通俗的語言說就是在application,session,request三個對象創建消亡或者往其中添加修改刪除屬性時自動執行代碼的功能組件。

3.Filter

過濾器,是一個可以復用的代碼片段,可以用來轉換HTTP請求、響應和頭信息。Filter不像Servlet,它不能產生一個請求或者響應,它只是修改對某一資源的請求,或者修改從某一的響應。

4.Interceptor

攔截器,是在面向切面編程的,就是在你的service 或者一個方法,前調用一個方法,或者在方法后調用一個方法。比如動態代理就是攔截器的簡單實現,在你調用方法前打印出字符串(或者做其它業務邏輯的操作),也可以在你調用方法后打印出字符串,甚至在你拋出異常的時候做業務邏輯的操作。

5.配置方式

servlet、filter、listener是配置到web.xml中,interceptor不配置到web.xml中,struts的攔截器配置到struts.xml中,spring的攔截器配置到spring.xml中。

三、生命周期

1、servlet:servlet的生命周期始於它被裝入web服務器的內存時,並在web服務器終止或重新裝入servlet時結束。servlet一旦被裝入web服務器,一般不會從web服務器內存中刪除,直至web服務器關閉或重新結束。
(1)、裝入:啟動服務器時加載Servlet的實例; 
(2)、初始化:web服務器啟動時或web服務器接收到請求時,或者兩者之間的某個時刻啟動。初始化工作有init()方法負責執行完成; 
(3)、調用:從第一次到以后的多次訪問,都是只調用doGet()或doPost()方法; 
(4)、銷毀:停止服務器時調用destroy()方法,銷毀實例。 

2、filter:(一定要實現javax.servlet包的Filter接口的三個方法init()、doFilter()、destroy(),空實現也行) 
(1)、啟動服務器時加載過濾器的實例,並調用init()方法來初始化實例; 
(2)、每一次請求時都只調用方法doFilter()進行處理; 
(3)、停止服務器時調用destroy()方法,銷毀實例。

3、listener:類似於servlet和filter

  web.xml 的加載順序是:context- param -> listener -> filter -> servlet 

4、interceptor:以struts的攔截器為例,加載了struts.xml以后,初始化相應攔截器。當action請求來時調用intercept方法,服務器停止銷毀interceptor。

四、總結

三大器對比:

ps:

1.平時所用的框架(Spring、Structs2等)其實都是基於JavaWeb 這四個知識點來做文章的,如果對原始的JavaWeb 不是很了解,那么在理解這些框架(框架是大牛們對原始JavaWeb進行封裝的結果,沒有原始JavaWeb開發基礎是很難真正學會框架的)上只能是知道是這樣做,而不知道為什么要這樣做,這種對框架的理解也只是存在表面上,稍微深入一點就得懵逼。

2.自己在實際工作中很多東西做完了就沒了,還是缺少一種獨立思考的能力。求學,不應該只是不求甚解,更應該有一種知之者不如好之者,好之者不如樂之者的心態,主動學習。

3.站在巨人的肩膀,能看的更遠。

 

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM