過濾器

Filter簡介

Filter也稱之為過濾器,WEB開發人員通過Filter技術,對web服務器管理的所有web資源:例如Jsp,Servlet,靜態圖片文件或靜態html文件等進行攔截,從而實現一些特殊的功能。
Servlet API中提供了一個Filter接口,開發web應用時,如果編寫的類實現了這個接口,則把這個java類稱之為過濾器Filter。通過Filter技術,開發人員可以實現用戶在訪問某個目標資源之前,對訪問的請求和響應進行攔截,如下所示:


image.png

Filter開發入門

Filter開發步驟

Filter開發分為二個步驟:

  • 編寫java類實現Filter接口,并實現其doFilter方法。
  • 在web.xml文件中使用<filter><filter-mapping>元素對編寫的filter類進行注冊,并設置它所能攔截的資源。

過濾器范例:

@WebFilter(filterName = "TestFilter",urlPatterns = "/index.do")
public class TestFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        System.out.println("FilterTest1執行之前!!!");
        // 攔截下目標資源,然后放行(目標資源也會執行)
        chain.doFilter(req, resp); // 放行
        System.out.println("FilterTest1執行之后!!!");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

代表網站首頁的index.do的代碼:

@WebServlet(name = "IndexServlet",urlPatterns = "/index.do")
public class IndexServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("index!!!");
    }
}

在瀏覽器輸入地址[http://localhost:8080/index.do],控制臺打印如下:

image.png

Filter是如何實現攔截的?

Filter接口中有一個doFilter方法,當我們編寫好Filter,并配置對哪個web資源進行攔截后,WEB服務器每次在調用web資源的service方法之前,都會先調用一下filter的doFilter方法,因此,在該方法內編寫代碼可達到如下目的:

調用目標資源之前,讓一段代碼執行。
是否調用目標資源(即是否讓用戶訪問web資源)
web服務器在調用doFilter方法時,會傳遞一個filterChain對象進來,filterChain對象是filter接口中最重要的一個對象,它也提供了一個doFilter方法,開發人員可以根據需求決定是否調用此方法,調用該方法,則web服務器就會調用web資源的service方法,即web資源就會被訪問,否則web資源不會被訪問。
調用目標資源之后,讓一段代碼執行。

過濾器的生命周期

Filter對象何時被創建?
服務器一啟動的時候,就會針對這個web應用將所有的Filter對象(攔截器)創建出來,并且以后訪問的時候,都是使用同一個攔截器進行攔截。也即一個攔截器會被所有的請求所共享,每一次請求來了之后,都會導致doFilter()方法被調用一次,Filter對象只有一個,而doFilter()方法會被多次調用。
問:Filter對象在內存里面有幾個?
答:一個。服務器并不會針對請求創建新的Filter對象(攔截器)。
Filter對象何時被摧毀?
移除掉web服務器里面這個web應用(或停掉服務器),就會摧毀這個web應用對應的攔截器。

過濾器應用之統一全站編碼

filter可以在放行之前,對request和response進行預處理,從而實現一些全局性的設置。如:

@WebFilter(filterName = "TestFilter",urlPatterns = "/index.do")
public class TestFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        System.out.println("FilterTest1執行之前!!!");
        // 攔截下目標資源,然后放行(目標資源也會執行)
        chain.doFilter(req, resp); // 放行
        System.out.println("FilterTest1執行之后!!!");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

過濾器應用之二

Java web過濾器驗證登錄(避免未經登錄進入管理后臺主頁)
舉例:admin.jsp 這個網頁是需要管理員通過登錄后才可以訪問的,現在有一個用戶沒有登錄,直接訪問admin.jsp成功了。那么,這樣的網站是不是覺得不安全呢?

過濾器實現登錄驗證

image.png

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<a href="index.admin">進入后臺</a>
  <a href="login.jsp">去登錄</a>
  </body>
</html>

AdminServlet.java

@WebServlet(name = "AdminServlet",urlPatterns = "/index.admin")
public class AdminServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/admin.jsp").forward(request,response);
    }
}

admin.jsp要放在WEB-INF目錄下保護起來

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    我是管理后臺
</body>
</html>

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form method="post" action="login.do">
    用戶名:<input type="text" name="user">
    密碼:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

LoginServlet.java

@WebServlet(name = "LoginServlet",urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String user = request.getParameter("user");
        String pwd = request.getParameter("pwd");
        if(user.equals("zhangsan") && pwd.equals("123"))
        {
            request.getSession().setAttribute("username",user);
            request.getRequestDispatcher("/WEB-INF/admin.jsp").forward(request,response);
        }
        else
        {
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

AuthorFilter.java

@WebFilter(filterName = "AuthorFilter",urlPatterns = "*.admin")
public class AuthorFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)req;
        String url = httpServletRequest.getServletPath();
        if(url.contains("login.do"))
        {
            chain.doFilter(req, resp);
            return;
        }
        String username = (String)httpServletRequest.getSession().getAttribute("username");
        if(username != null)
        {
            chain.doFilter(req, resp);
            return;
        }
        else
        {
            httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest,resp);
        }


    }

    public void init(FilterConfig config) throws ServletException {

    }

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容