據說你改bug很厲害,幫我改一個吧
????
html
上一章咱們講到了Servlet請求
,能夠經過瀏覽器發送的請求,來進行數據的處理並返回相應的響應給瀏覽器。前端
在咱們的實際開發中,經常會遇到一些對全部方法都須要的驗證方法,好比登陸驗證等,這個時候咱們在每一個方法中都編寫一樣的功能代碼,既浪費時間也不利於維護。java
幸虧,Servlet給咱們提供了過濾器
解決這個問題。web
Servlet 過濾器
能夠動態地攔截請求和響應
,以變換或使用包含在請求或響應中的信息。編程
能夠將一個或多個 Servlet 過濾器附加到一個 Servlet 或一組 Servlet。調用 Servlet 前調用全部附加的 Servlet 過濾器。後端
Servlet 過濾器能夠實現如下目的:瀏覽器
在客戶端的請求訪問後端資源以前,攔截這些請求。服務器
在服務器的響應發送回客戶端以前,處理這些響應。app
一樣的,Servlet過濾器是可用於 Servlet 編程的 Java 類,也須要在XML中聲明的。Filter執行順序和在web.xml中聲明的順序一致,一般把Filter配置在全部邏輯Servlet以前。學習
Servlet經過javax.servlet.Filter
接口來實現過濾器,接口提供了三個方法:
該方法完成實際的過濾操做,當客戶端請求方法與過濾器設置的URL匹配時,Servlet容器將先調用過濾器的doFilter
方法。FilterChain
用戶訪問後續過濾器。
web 應用程序啓動時,web 服務器將建立Filter 的實例對象,並調用其init
方法,讀取web.xml配置,完成對象的初始化功能,從而爲後續的用戶請求做好攔截的準備工做(filter對象只會建立一次,init
方法也只會執行一次)。開發人員經過init
方法的參數,可得到表明當前filter配置信息的FilterConfig對象
。
Servlet容器在銷燬過濾器實例前調用該方法,在該方法中釋放Servlet過濾器佔用的資源。
節點 | 說明 |
---|---|
<filter> |
指定這個過濾器 |
<filter-name> |
過濾器的名稱 |
<filter-class> |
過濾器完整類名 |
<init-param> |
元素用於爲過濾器指定初始化參數,它的子元素<param-name> 指定參數的名字,<param-value> 指定參數的值。 |
<filter-mapping> |
元素用於設置一個 Filter 所負責攔截的資源。一個Filter攔截的資源可經過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑 |
<filter-name> |
子元素用於設置filter的註冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字 |
<url-pattern> |
設置 filter 所攔截的請求路徑(過濾器關聯的URL樣式) |
咱們接着上一章的小栗子繼續擴展咱們的應用。
package com.filter; //導入必要的依賴庫 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*; //實現Filter類 public class FirstFilter implements Filter { public void init(FilterConfig config) throws ServletException { //獲取web.xml中初始化的參數 String name = config.getInitParameter("name"); //輸出 System.out.println("請關注:"+ name); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException { System.out.println("我在doFilter中"); String message = "我跨越過濾器來跟你說"; // 設置響應內容類型 response.setContentType("text/html;charset=utf-8"); // 實際的邏輯是在這裏 PrintWriter out = response.getWriter(); out.println("<h1>" + message + "</h1>"); //把請求傳回過濾鏈 chain.doFilter(request, response); } public void destroy(){ //do something } }
<web-app> <filter> <filter-name>FirstFilter</filter-name> <filter-class>com.filter.FirstFilter</filter-class> <init-param> <param-name>name</param-name> <param-value>野生前端攻城獅</param-value> </init-param> </filter> <filter-mapping> <filter-name>FirstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.servletLearn.HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
能夠看到,咱們在項目啓動的時候,執行了Filter的init()方法,因此在服務器日誌中看到了打印請關注野生前端攻城獅
字符串。
使用瀏覽器打開對應的連接時,一樣在服務器日誌中也出現了咱們打印的字符串。而在瀏覽器中,則同時出現了咱們在過濾器和HelloWorld方法中返回的字符串。
因此,咱們在過濾器中返回的值,並無影響原來Servlet方法的執行。
過濾器在平常開發中適用範圍很是普遍,因此是咱們學習servlet所必需要掌握的一個知識點。
PS:過濾器和攔截器是兩個徹底不一樣的概念。過濾器是原生servlet的類,攔截器是Spring及struts2裏的概念