過濾器
過濾器可以動態的攔截請求和相應,以變換或使用包含在請求或響應中的信息。
過濾器是可用于 Servlet 編程的 Java 類,可以實現以下目的:
- 在客戶端的請求訪問后端資源之前,攔截這些請求。
- 在服務器的響應發送回客戶端之前,處理這些響應。
根據規范建議的各種類型的過濾器:
- 身份驗證過濾器(Authentication Filters)。
- 數據壓縮過濾器(Data compression Filters)。
- 加密過濾器(Encryption Filters)。
- 觸發資源訪問事件過濾器。
- 圖像轉換過濾器(Image Conversion Filters)。
- 日志記錄和審核過濾器(Logging and Auditing Filters)。
- MIME-TYPE 鏈過濾器(MIME-TYPE Chain Filters)。
- 標記化過濾器(Tokenizing Filters)。
- XSL/T 過濾器(XSL/T Filters),轉換 XML 內容。
Servlet 過濾器方法
過濾器是一個實現了 javax.servlet.Filter 接口的 Java 類。javax.servlet.Filter 接口定義了三個方法:
- public void doFilter (ServletRequest, ServletResponse, FilterChain)
該方法完成實際的過濾操作,當客戶端請求方法與過濾器設置匹配的URL時,Servlet容器將先調用過濾器的doFilter方法。FilterChain用戶訪問后續過濾器。 - public void init(FilterConfig filterConfig)
web 應用程序啟動時,web 服務器將創建Filter 的實例對象,并調用其init方法,讀取web.xml配置,完成對象的初始化功能,從而為后續的用戶請求作好攔截的準備工作(filter對象只會創建一次,init方法也只會執行一次)。開發人員通過init方法的參數,可獲得代表當前filter配置信息的FilterConfig對象。 - public void destroy()
Servlet容器在銷毀過濾器實例前調用該方法,在該方法中釋放Servlet過濾器占用的資源。
FilterConfig 使用
Filter 的 init 方法中提供了一個 FilterConfig 對象。
web.xml 文件配置如下:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.runoob.test.LogFilter</filter-class>
<init-param>
<param-name>Site</param-name>
<param-value>Lisy</param-value>
</init-param>
</filter>
在 init 方法使用 FilterConfig 對象獲取參數:
public void init(FilterConfig config) throws ServletException {
// 獲取初始化參數
String site = config.getInitParameter("Site");
// 輸出初始化參數
System.out.println("網站名稱: " + site);
}
過濾器的應用順序
web.xml 中的 filter-mapping 元素的順序決定了 Web 容器應用過濾器到 Servlet 的順序。若要反轉過濾器的順序,您只需要在 web.xml 文件中反轉 filter-mapping 元素即可。
web.xml配置各節點說明
- <filter>指定一個過濾器。
- <filter-name>用于為過濾器指定一個名字,該元素的內容不能為空。
- <filter-class>元素用于指定過濾器的完整的限定類名。
- <init-param>元素用于為過濾器指定初始化參數,它的子元素<param-name>指定參數的名字,<param-value>指定參數的值。
- 在過濾器中,可以使用FilterConfig接口對象來訪問初始化參數。
- <filter-mapping>元素用于設置一個 Filter 所負責攔截的資源。一個Filter攔截的資源可通過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑
- <filter-name>子元素用于設置filter的注冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字
- <url-pattern>設置 filter 所攔截的請求路徑(過濾器關聯的URL樣式)
- <servlet-name>指定過濾器所攔截的Servlet名稱。調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認REQUEST。用戶可以設置多個
- <dispatcher>子元素用來指定 Filter 對資源的多種調用方式進行攔截。
- <dispatcher>子元素可以設置的值及其意義
- REQUEST:當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問時,那么該過濾器就不會被調用。
- INCLUDE:如果目標資源是通過RequestDispatcher的include()方法訪問時,那么該過濾器將被調用。除此之外,該過濾器不會被調用。
- FORWARD:如果目標資源是通過RequestDispatcher的forward()方法訪問時,那么該過濾器將被調用,除此之外,該過濾器不會被調用。
- ERROR:如果目標資源是通過聲明式異常處理機制調用時,那么該過濾器將被調用。除此之外,過濾器不會被調用。
Cookie處理
Cookie是存儲在客戶機的文本文件,它們保存了大量軌跡信息。在servlet技術基礎上,JSP顯然能夠提供對HTTP cookie的支持。
通常有三個步驟來識別回頭客:
- 服務器腳本發送一系列cookie至瀏覽器。比如名字,年齡,ID號碼等等。
- 瀏覽器在本地機中存儲這些信息,以備不時之需。
- 當下一次瀏覽器發送任何請求至服務器時,它會同時將這些cookie信息發送給服務器,然后服務器使用這些信息來識別用戶或者干些其它事情。
Cookie 剖析
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2015 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=runoob; expires=Friday, 04-Feb-07 22:03:38 GMT;
path=/; domain=runoob.com
Connection: close
Content-Type: text/html
Set-Cookie信息頭包含一個鍵值對,一個GMT(格林尼治標準)時間,一個路徑,一個域名。鍵值對會被編碼為URL。有效期域是個指令,告訴瀏覽器在什么時候之后就可以清除這個cookie。
如果瀏覽器被配置成可存儲cookie,那么它將會保存這些信息直到過期。如果用戶訪問的任何頁面匹配了cookie中的路徑和域名,那么瀏覽器將會重新將這個cookie發回給服務器。
Servlet Cookie 方法
- public void setDomain(String pattern)
設置cookie的域名,比如w3cschool.cc - public String getDomain()
獲取cookie的域名,比如w3cschool.cc - public void setMaxAge(int expiry)
設置cookie有效期,以秒為單位,默認有效期為當前session的存活時間 - public int getMaxAge()
獲取cookie有效期,以秒為單位,默認為-1 ,表明cookie會活到瀏覽器關閉為止 - public String getName()
返回 cookie的名稱,名稱創建后將不能被修改 - public void setValue(String newValue)
設置 cookie的值 - public String getValue()
獲取cookie的值 - public void setPath(String uri)
設置cookie 的路徑,默認為當前頁面目錄下的所有URL,還有此目錄下的所有子目錄 - public String getPath()
獲取cookie 的路徑 - public void setSecure(boolean flag)
指明cookie是否要加密傳輸 - public void setComment(String purpose)
設置注釋描述 cookie的目的。當瀏覽器將cookie展現給用戶時,注釋將會變得非常有用 - public String getComment()
返回描述cookie目的的注釋,若沒有則返回null
使用JSP設置Cookie
使用JSP設置cookie包含三個步驟:
(1)創建一個Cookie對象: 調用Cookie的構造函數,使用一個cookie名稱和值做參數,它們都是字符串。
Cookie cookie = new Cookie("key","value");
請務必牢記,名稱和值中都不能包含空格或者如下的字符:[ ] ( ) = , " / ? @ : ;
(2) 設置有效期:調用setMaxAge()函數表明cookie在多長時間(以秒為單位)內有效。下面的操作將有效期設為了24小時。
cookie.setMaxAge(60*60*24);
(3) 將cookie發送至HTTP響應頭中:調用response.addCookie()函數來向HTTP響應頭中添加cookie。
response.addCookie(cookie);
Session
HTTP是無狀態協議,這意味著每次客戶端檢索網頁時,都要單獨打開一個服務器連接,因此服務器不會記錄下先前客戶端請求的任何信息。
有三種方法來維持客戶端與服務器的會話:
- Cookies
網絡服務器可以指定一個唯一的session ID作為cookie來代表每個客戶端,用來識別這個客戶端接下來的請求。
這可能不是一種有效的方式,因為很多時候瀏覽器并不一定支持cookie,所以我們不建議使用這種方法來維持會話。 - 隱藏表單域
一個網絡服務器可以發送一個隱藏的HTML表單域和一個唯一的session ID,就像下面這樣:
<input type="hidden" name="sessionid" value="12345">
這個條目意味著,當表單被提交時,指定的名稱和值將會自動包含在GET或POST數據中。每當瀏覽器發送一個請求,session_id的值就可以用來保存不同瀏覽器的軌跡。
這種方式可能是一種有效的方式,但點擊<A HREF>標簽中的超鏈接時不會產生表單提交事件,因此隱藏表單域也不支持通用會話跟蹤。
- 重寫URL
可以在每個URL后面添加一些額外的數據來區分會話,服務器能夠根據這些數據來關聯session標識符。舉例來說,http://w3cschool.cc/file.htm;sessionid=12345, session標識符為sessionid=12345,服務器可以用這個數據來識別客戶端。
相比而言,重寫URL是更好的方式來,就算瀏覽器不支持cookies也能工作,但缺點是您必須為每個URL動態指定session ID,就算這是個簡單的HTML頁面。
session對象
除了以上幾種方法外,JSP利用servlet提供的HttpSession接口來識別一個用戶,存儲這個用戶的所有訪問信息。
默認情況下,JSP允許會話跟蹤,一個新的HttpSession對象將會自動地為新的客戶端實例化。禁止會話跟蹤需要顯式地關掉它,通過將page指令中session屬性值設為false來實現,就像下面這樣:
<%@ page session="false" %>
JSP引擎將隱含的session對象暴露給開發者。由于提供了session對象,開發者就可以方便地存儲或檢索數據。
下表列出了session對象的一些重要方法:
- public Object getAttribute(String name)
返回session對象中與指定名稱綁定的對象,如果不存在則返回null - public Enumeration getAttributeNames()
返回session對象中所有的對象名稱 - public long getCreationTime()
返回session對象被創建的時間, 以毫秒為單位,從1970年1月1號凌晨開始算起 - public String getId()
返回session對象的ID - public long getLastAccessedTime()
返回客戶端最后訪問的時間,以毫秒為單位,從1970年1月1號凌晨開始算起 - public int getMaxInactiveInterval()
返回最大時間間隔,以秒為單位,servlet 容器將會在這段時間內保持會話打開 - public void invalidate()
將session無效化,解綁任何與該session綁定的對象 - public boolean isNew()
返回是否為一個新的客戶端,或者客戶端是否拒絕加入session - public void removeAttribute(String name)
移除session中指定名稱的對象 - public void setAttribute(String name, Object value)
使用指定的名稱和值來產生一個對象并綁定到session中 - public void setMaxInactiveInterval(int interval)
用來指定時間,以秒為單位,servlet容器將會在這段時間內保持會話有效