JavaWeb學習筆記

楓林逢夜雨發表於2020-10-24

本文轉自喻志強的部落格

原文地址:https://yuzhiqiang.blog.csdn.net/article/details/81288912

JavaWeb之過濾器(Filter)

今天學習JavaWeb的過濾器時,發現了一篇關於JavaWeb的過濾器的部落格很好,對像我這樣IT小白很有用!

首先解釋一下什麼是過濾器?

過濾器實際上就是對web資源進行攔截,做一些處理後再交給下一個過濾器或servlet處理
通常都是用來攔截request進行處理的,也可以對返回的response進行攔截處理
大致的工作原理

應用場景為:

  1. 登入過濾
  2. 字元編碼設定

建立一個Filter

在Servlet中我們一般都會對request和response中的字符集編碼進行配置,如果Servlet過多字符集編碼發生變化時修改起碼會很麻煩,這些通用的字符集編碼配置等工作我們可以放到Filter中來實現。
下面我們來建立一個處理字符集編碼的Filter。

右鍵包名—>new ---->Filter
在這裡插入圖片描述
輸入過濾器名稱,跟建立Servlet一樣,這裡我們直接使用 @WebFilter 註解,不再去web,xml中進行配置了。
在這裡插入圖片描述
建立完成後預設程式碼,可以看到,CharsetFilter實現了Filter介面,實現了3個方法。3個方法的作用已經在註釋中寫清楚了。

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "CharsetFilter")
public class CharsetFilter implements Filter {
    public void destroy() {
        /*銷燬時呼叫*/
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        /*過濾方法 主要是對request和response進行一些處理,然後交給下一個過濾器或Servlet處理*/
       
        chain.doFilter(req, resp);//交給下一個過濾器或servlet處理
    }

    public void init(FilterConfig config) throws ServletException {

        /*初始化方法  接收一個FilterConfig型別的引數 該引數是對Filter的一些配置*/

    }

}


配置Filter

可以配置這些
在這裡插入圖片描述
常用配置項
urlPatterns
配置要攔截的資源
1.以指定資源匹配。例如"/index.jsp"
2.以目錄匹配。例如"/servlet/"
3.以字尾名匹配,例如"
.jsp"
4.萬用字元,攔截所有web資源。"/*"

**initParams **
配置初始化引數,跟Servlet配置一樣

例如

initParams = {
        @WebInitParam(name = "key",value = "value")
}

dispatcherTypes **
配置攔截的型別,可配置多個。預設為DispatcherType.REQUEST**
例如

dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR}

其中DispatcherType是個列舉型別,有下面幾個值

	FORWARD,//轉發的
    INCLUDE,//包含在頁面的
    REQUEST,//請求的
    ASYNC,//非同步的
    ERROR;//出錯的

下面我們來對CharsetFilter 程式碼進行一下修改

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;

@WebFilter(filterName = "CharsetFilter",
        urlPatterns = "/*",/*萬用字元(*)表示對所有的web資源進行攔截*/
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8")/*這裡可以放一些初始化的引數*/
        })
public class CharsetFilter implements Filter {
    private String filterName;
    private String charset;

    public void destroy() {
        /*銷燬時呼叫*/

        System.out.println(filterName + "銷燬");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        /*過濾方法 主要是對request和response進行一些處理,然後交給下一個過濾器或Servlet處理*/
		System.out.println(filterName + "doFilter()");
        req.setCharacterEncoding(charset);
        resp.setCharacterEncoding(charset);
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

        /*初始化方法  接收一個FilterConfig型別的引數 該引數是對Filter的一些配置*/

        filterName = config.getFilterName();
        charset = config.getInitParameter("charset");

        System.out.println("過濾器名稱:" + filterName);
        System.out.println("字符集編碼:" + charset);

    }

}


這樣一個簡單的字符集編碼處理的過濾器就完成了
我們看看執行列印的結果
在這裡插入圖片描述
需要注意的是
過濾器是在伺服器啟動時就會建立的,只會建立一個例項,常駐記憶體,也就是說伺服器一啟動就會執行Filter的init(FilterConfig config)方法.
當Filter被移除或伺服器正常關閉時,會執行destroy方法

多個Filter的執行順序

在我們的請求到達Servle之間是可以經過多個Filter的,一般來說,建議Filter之間不要有關聯,各自處理各自的邏輯即可。這樣,我們也無需關心執行順序問題。
如果一定要確保執行順序,就要對配置進行修改了,執行順序如下

1.在web.xml中,filter執行順序跟<filter-mapping>的順序有關,先宣告的先執行
2.使用註解配置的話,filter的執行順序跟名稱的字母順序有關,例如AFilter會比BFilter先執行
3.如果既有在web.xml中宣告的Filter,也有通過註解配置的Filter,那麼會優先執行web.xml中配置的Filter

我們寫個小例子看一下

新建3個Filter,加上之前的CharsetFilter一共四個
在這裡插入圖片描述
其中CharsetFilter和ABFilter是通過註解宣告的

CharsetFilter註解配置


@WebFilter(filterName = "CharsetFilter",
        urlPatterns = "/*",/*萬用字元(*)表示對所有的web資源進行攔截*/
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8")/*這裡可以放一些初始化的引數*/
        })

ABFilter

@WebFilter(filterName = "ABFilter",urlPatterns = "/*")

AFilter和BFilter是在web.xml配置的。
執行順序跟filter的順序無關
filter-mapping的順序才決定執行順序

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>AFilter</filter-name>
        <filter-class>filter.AFilter</filter-class>
    </filter>
    <filter>
        <filter-name>BFilter</filter-name>
        <filter-class>filter.BFilter</filter-class>
    </filter>

    <!--這裡BFilter在AFilter之前-->
    <filter-mapping>
        <filter-name>BFilter</filter-name>
        <url-pattern>/filter.jsp</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>AFilter</filter-name>
        <url-pattern>/filter.jsp</url-pattern>
    </filter-mapping>

   
</web-app>

每個Filter新增了列印語句,如下
以ABFilter為例

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ABFilter",urlPatterns = "/*")
public class ABFilter implements Filter {
    private String filterName;

    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println(filterName + "  doFilter()");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        filterName= config.getFilterName();
        System.out.println("過濾器名稱:" + filterName +" init");
    }

}


列印結果
在這裡插入圖片描述

可以看到,執行結果符合預期。
BFilter和AFilter是在web.xml中宣告的,且BFilter的filter-mapping在前,故BFilter在AFilter之前執行。
ABFilter和CharsetFilter是通過註解宣告的,故他倆在BFilter和AFilter之後執行,但是ABFilter的名稱以A開頭,故在CharsetFilter之前執行

祝願IT行業各位“1024”程式設計師節,節日快樂!!!

相關文章