首頁 > Java > java教程 > 主體

Java中關於Filter與Servlet以及Listener的具體介紹

黄舟
發布: 2017-07-30 13:18:36
原創
1454 人瀏覽過

這篇文章主要為大家詳細介紹了Filter、Servlet、Listener的學習資料,具有一定的參考價值,有興趣的夥伴們可以參考一下

Java中Filter、Servlet、Listener的學習資料,希望大家喜歡

1、Filter的功能

filter功能,它使用戶可以改變一個request和修改一個response. Filter 不是一個servlet,它不能產生一個response,它能夠在一個request到達servlet之前預處理request,也可以在離開servlet時處理response.換種說法,filter其實是一個」servlet chaining」(servlet 鏈).

一個Filter包含:

1)、在servlet被呼叫之前截獲;
2)、在servlet被呼叫之前檢查servlet request;
3)、根據需要修改request頭和request資料;
4)、根據需要修改response頭和response資料;
5)、在servlet被調用之後截獲.

伺服器每次只調用setFilterConfig方法一次準備filter 的處理;呼叫doFilter方法多次以處理不同的請求.FilterConfig介面有方法可以找到filter名字及初始化參數資訊.伺服器可以設定FilterConfig為空來指明filter已經終結。
每一個filter從doFilter()方法得到目前的request及response.在這個方法裡,可以進行任何的針對request及response的操作.(包括收集資料,包裝資料等).filter呼叫chain.doFilter ()方法把控制權交給下一個filter.一個filter在doFilter()方法中結束.如果一個filter想停止request處理而獲得對response的完全的控制,那它可以不調用下一個filter
例子:
首先新建一個Filter


/** 
 * 
 */ 
package com.ee.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogFilter implements Filter { 
 private FilterConfig filterConfig; 
 
 public FilterConfig getFilterConfig() { 
  System.err.println("...getFilterConfig..."); 
  return filterConfig; 
 } 
 
 public void setFilterConfig(FilterConfig filterConfig) { 
  System.err.println("...setFilterConfig..."); 
  this.filterConfig = filterConfig; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#destroy() 
  */ 
 @Override 
 public void destroy() { 
  System.err.println("...filter destroy..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) 
  */ 
 @Override 
 public void doFilter(ServletRequest request, ServletResponse response, 
   FilterChain chain) throws IOException, ServletException { 
  System.err.println("...doFilter..."); 
  chain.doFilter(request, response);//看到这没,这只要是传递下一个Filter 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 
  */ 
 @Override 
 public void init(FilterConfig filterConfig) throws ServletException { 
  System.err.println("...init Filter..."); 
  this.filterConfig = filterConfig; 
 } 
 
}
登入後複製

在web.xml裡配置


<filter> 
 <filter-name>LogFilter</filter-name> 
 <filter-class>com.ee.filter.LogFilter</filter-class> 
</filter> 
 
<filter-mapping> 
 <filter-name>LogFilter</filter-name> 
 <url-pattern>/*</url-pattern> 
</filter-mapping>
登入後複製

啟動運行
可以看到...init Filter...首先在TOMCAT啟動時即被列印,然後在運行裡面再看到...doFilter...被列印。 

2、servlet功能

1). Servlet 是什麼?

  Servlet是使用Java Servlet 應用程式設計介面(API)及相關類別與方法的 Java 程式。除了 Java Servlet API,Servlet 還可以使用用於擴充和新增到 API 的 Java 類別軟體包。 Servlet 在啟用 Java 的 Web 伺服器上或應用程式伺服器上運行並擴展了該伺服器的能力。 Java servlet對於Web伺服器好像Java applet對於網頁瀏覽器。 Servlet裝入網頁伺服器並在網頁伺服器內執行,而applet裝入網頁瀏覽器並在網頁瀏覽器內執行。 Java Servlet API 定義了一個servlet 和Java使能的伺服器之間的一個標準接口,這使得Servlets具有跨伺服器平台的特性。

  Servlet 透過建立一個框架來擴充伺服器的能力,以提供在 Web 上進行請求和回應服務。當客戶端發送請求至伺服器時,伺服器可以將請求資訊傳送給 Servlet,並讓 Servlet 建立起伺服器傳回給客戶機的回應。 當啟動 Web 伺服器或用戶端第一次要求服務時,可以自動裝入 Servlet。裝入後, Servlet 繼續運作直到其它客戶機發出請求。 Servlet 的功能涉及範圍很廣。例如,Servlet 可完成以下功能:

  (1) 建立並傳回一個包含基於客戶請求性質的動態內容的完整的 HTML頁面。
  (2) 建立可嵌入現有 HTML 頁面中的一部分 HTML 頁面(HTML 片段)。
  (3) 與其它伺服器資源(包括資料庫和基於 Java 的應用程式)進行通訊。
  (4) 用多個客戶機處理連接,接收多個客戶機的輸入,並將結果廣播到多個客戶機上。例如,Servlet 可以是多參與者的遊戲伺服器。
  (5) 當允許在單一連接方式下傳送資料的情況下,在瀏覽器上開啟伺服器至applet的新連接,並將該連
接保持在開啟狀態。當允許客戶機和伺服器簡單、有效率地執行會話的情況下,applet也可以啟動客戶瀏覽器和伺服器之間的連線。可以透過定制協議或標準(如 IIOP)進行通訊。
  (6) 對特殊的處理採用 MIME 類型過濾數據,例如影像轉換和伺服器端包含(SSI)。
  (7) 將客製化的處理提供給所有伺服器的標準例行程序。例如,Servlet 可以修改如何認證使用者。

2). Servlet 的生命週期
  Servlet 的生命週期始於將它裝入 Web 伺服器的記憶體時,並在終止或重新裝入 Servlet 時結束。

(1) 初始化
 在下列時刻裝入Servlet:
 如果已配置自動裝入選項,則在啟動伺服器時自動裝入
 在伺服器啟動後,當客戶機首次向Servlet 發出請求時
 重新裝入Servlet 時裝入Servlet 後,伺服器建立一個Servlet 實例並且呼叫Servlet 的init() 方法。在初始化階段,Servlet 初始化參數會傳遞給 Servlet 設定物件。

(2) 請求處理
 對於到達伺服器的客戶機請求,伺服器會建立特定於請求的一個「請求」物件和一個「回應」物件。伺服器呼叫 Servlet 的 service() 方法,該方法用於傳遞「請求」和「回應」物件。 service() 方法從「請求」物件取得請求資訊、處理該請求並以「回應」物件的方法以將回應傳回客戶機。 service() 方法可以呼叫其它方法來處理請求,例如 doGet()、doPost() 或其它的方法。

(3) 終止
 當伺服器不再需要 Servlet, 或重新裝入 Servlet 的新實例時,伺服器會呼叫 Servlet 的 destroy() 方法。

3). Java Servlet API
 Java Servlet 開發工具(JSDK)提供了多個軟體包,在編寫 Servlet 時需要用到這些軟體包。其中包括兩個用於所有 Servlet 的基本軟體包:javax.servlet 和 javax.servlet.http。可從sun公司的Web網站下載 Java Servlet 開發工具。 以下主要介紹javax.servlet.http提供的HTTP Servlet應用程式介面。
 HTTP Servlet 使用一個 HTML 表格來傳送和接收資料。若要建立一個 HTTP Servlet,請擴充 HttpServlet 類, 該類別是用專門的方法來處理 HTML 表格的 GenericServlet 的子類別。 HTML 表單是由

標籤定義的。表單中典型地包含輸入欄位(如文字輸入欄位、複選框、單選按鈕和選擇清單)和用於提交資料的按鈕。當提交資訊時,它們還指定伺服器應執行哪一個Servlet(或其它的程式)。 HttpServlet 類別包含 init()、destroy()、service() 等方法。其中 init() 和 destroy() 方法是繼承的。

(1) init() 方法

  在 Servlet 的生命期中,只執行一次 init() 方法。它是在伺服器裝入 Servlet 時執行的。 可設定伺服器,以在啟動伺服器或用戶端首次存取 Servlet 時裝入 Servlet。 無論有多少客戶機存取 Servlet,都不會重複執行 init() 。
  缺省的 init() 方法通常是符合要求的,但也可以用自訂 init() 方法來覆寫它,典型的是管理伺服器端資源。 例如,可能編寫一個定制 init() 來只用於一次裝入 GIF 圖像,改進 Servlet 返回 GIF 圖像和含有多個客戶機請求的效能。另一個範例是初始化資料庫連接。預設的 init() 方法設定了 Servlet 的初始化參數,並用它的 ServletConfig 物件參數來啟動配置, 因此所有覆寫 init() 方法的 Servlet 應呼叫 super.init() 以確保仍然執行這些任務。在呼叫 service() 方法之前,應確保已完成了 init() 方法。

(2) service() 方法
  service() 方法是 Servlet 的核心。每當一個客戶請求一個HttpServlet 對象,該對象的service() 方法就要被調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對像作為參數。 在 HttpServlet 中已存在 service() 方法。預設的服務功能是呼叫與 HTTP 請求的方法對應的 do 功能。例如, 如果 HTTP 請求方法為 GET,則預設會呼叫 doGet() 。 Servlet 應該為 Servlet 支援的 HTTP 方法覆寫 do 功能。因為 HttpServlet.service() 方法會檢查請求方法是否呼叫了適當的處理方法,不必要覆寫 service() 方法。只需覆蓋相應的 do 方法就可以了。
 當一個客戶透過HTML 表單發出一個HTTP POST請求時,doPost()方法被呼叫。與POST請求相關的參數會作為一個單獨的HTTP 請求從瀏覽器傳送到伺服器。當需要修改伺服器端的資料時,應該使用doPost()方法。
 當一個客戶透過HTML 表單發出一個HTTP GET請求或直接請求一個URL時,doGet()方法被呼叫。與GET請求相關的參數加到URL的後面,並與這個請求一起發送。當不會修改伺服器端的資料時,應該使用doGet()方法。
  Servlet的回應可以是下列幾種類型:
  一個輸出流,瀏覽器根據它的內容類型(如text/HTML)來解釋。
  一個HTTP錯誤回應, 重新導向到另一個URL、servlet、JSP。

(3) destroy() 方法
  destroy() 方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。
当服务器卸装 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个Servlet 在运行service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。

(4) GetServletConfig()方法
  GetServletConfig()方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和  ServletContext。ServletContext 接口提供有关servlet 的环境信息。

(5) GetServletInfo()方法
  GetServletInfo()方法是一个可选的方法,它提供有关servlet 的信息,如作者、版本、版权。
  当服务器调用sevlet 的Service()、doGet()和doPost()这三个方法时,均需要 “请求”和“响应”对象作为参数。“请求”对象提供有关请求的信息,而“响应”对象提供了一个将响应信息返回给浏览器的一个通信途径。javax.servlet 软件包中的相关类为ServletResponse和ServletRequest,而javax.servlet.http 软件包中的相关类为HttpServletRequest 和 HttpServletResponse。Servlet 通过这些对象与服务器通信并最终与客户机通信。Servlet 能通过调用“请求”对象的方法获知客户机环境,服务器环境的信息和所有由客户机提供的信息。Servlet 可以调用“响应”对象的方法发送响应,该响应是准备发回客户机的。

例子:
创建一个servlet


/** 
 * 
 */ 
package com.ee.servlet; 
 
import java.io.IOException; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogServlet extends HttpServlet { 
 
 /** 
  * 
  */ 
 private static final long serialVersionUID = 1L; 
 
 @Override 
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  doPost(req, resp); 
 } 
  
 @Override 
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  System.err.println("...doPost(req, resp)..."); 
 } 
}
登入後複製

在web.xml中的配置:


<servlet> 
 <servlet-name>LogServlet</servlet-name> 
 <servlet-class>com.ee.servlet.LogServlet</servlet-class> 
</servlet> 
 
<servlet-mapping> 
 <servlet-name>LogServlet</servlet-name> 
 <url-pattern>/*</url-pattern><!-- 看到此没有,这个拦截所有路径 --> 
</servlet-mapping>
登入後複製

它的拦截规则:

当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:
1.精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。
2.最长路径匹配。例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
3.扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action
4.如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet

3、Listener功能

它是基于观察者模式设计的,Listener 的设计对开发 Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个纵向维度控制程序和数据。目前 Servlet 中提供了 5 种两类事件的观察者接口,它们分别是:4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。如下图所示:

Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。常用的监听接口有以下几个:

ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。
HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

下面我们开发一个具体的例子,这个监听器能够统计在线的人数。在ServletContext初始化和销毁时,在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息。
要获得以上的功能,监听器必须实现以下3个接口:

HttpSessionListener
ServletContextListener
ServletContextAttributeListener

例子:


/** 
 * 
 */ 
package com.ee.listener; 
 
import javax.servlet.ServletContextAttributeEvent; 
import javax.servlet.ServletContextAttributeListener; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class OnlineUserListener implements HttpSessionListener, 
  ServletContextListener, ServletContextAttributeListener { 
 private long onlineUserCount = 0; 
 
 public long getOnlineUserCount() { 
  return onlineUserCount; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeAdded(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeAdded(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeRemoved(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeReplaced(ServletContextAttributeEvent attributeEvent) { 
  System.err.println("...attributeReplaced..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextDestroyed(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextInitialized(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionCreated(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount ++; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount --; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 private void toUpdateCount(HttpSessionEvent httpSessionEvent){ 
  httpSessionEvent.getSession().setAttribute("onlineUserCount", onlineUserCount); 
 } 
}
登入後複製

Web.xml


<listener> 
 <listener-class>com.ee.listener.OnlineUserListener</listener-class> 
</listener>
登入後複製

JSP页面:


<%@ page language="java" contentType="text/html; charset=UTF-8" 
 pageEncoding="UTF-8"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>主页</title> 
</head> 
<body> 
 <h4>你好!</h4> 
 在线人数:<h1><%=request.getSession().getAttribute("onlineUserCount") %></h1> 
</body> 
</html>
登入後複製

以上是Java中關於Filter與Servlet以及Listener的具體介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!