欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解JavaWeb過濾器(Filter)

 更新時間:2023年05月11日 09:12:01   作者:禿頭披風俠.  
本文主要介紹了一文詳解JavaWeb過濾器(Filter),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

基本介紹

過濾器,顧名思義就是對事物進行過濾的,在Web中的過濾器,當然就是對請求進行過濾,我們使用過濾器,就可以對請求進行攔截,然后做相應的處理,實現(xiàn)許多特殊功能。如登錄控制,權限管理,過濾敏感詞匯等.

過濾器原理

當我們使用過濾器時,過濾器會對游覽器的請求進行過濾,過濾器可以動態(tài)的分為3個部分,1.放行之前的代碼,2.放行,3.放行后的代碼,這3個部分分別會發(fā)揮不同作用。

  • 第一部分代碼會對游覽器請求進行第一次過濾,然后繼續(xù)執(zhí)行
  • 第二部分代碼就是將游覽器請求放行,如果還有過濾器,那么就繼續(xù)交給下一個過濾器
  • 第三部分代碼就是對返回的Web資源再次進行過濾處理

我們使用過濾器,也就是說,不止請求會經(jīng)過過濾器,我們的響應也會經(jīng)過過濾器。

過濾器(Filter)接口

我們學習過濾器,肯定就要先看一下官方給我們提供的過濾器接口。下面我們使用Idea來查看Filter。

我們通過官方提供的過濾器可以看出過濾器(Filter)使用起來還是比較簡單的,下面我們就來學習如何使用過濾器(Filter)

使用過濾器(Filter)

我們使用過濾器肯定要導入相應的jar包才行,F(xiàn)ilter就在servlet-api.jar中,我們將該jar包放到WEB-INF下的lib目錄下面,然后加入項目。

創(chuàng)建過濾器(Fliter)

我們創(chuàng)建Filter,只需要繼承Filter接口就行。

import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }
}

Filter接口有3個方法,但是只有一個方法沒有實現(xiàn),我們只需要實現(xiàn)這個方法就行。我們可以發(fā)現(xiàn),我們實現(xiàn)了一個doFilter方法,這個方法就是我們寫過濾代碼的地方,具體邏輯就是和上面介紹的過濾器原理一樣的。

使用過濾器(Filter)

我們先來感受一下如何使用過濾器,細節(jié)我們后面慢慢說明。我們在上面創(chuàng)建的類中寫入以下代碼,并且加一個WebFIlter注解

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("對request進行過濾");
        //下面這行代碼就是放行
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("對response進行過濾");
    }
}

我簡單介紹下上面的代碼,WebFilter("/*")表示對所有請求進行過濾,而在doFilter中的放行代碼,也就是filterChain.doFilter(servletRequest,servletResponse);這行代碼就是對攔截進行放行,細節(jié)我們后面講,現(xiàn)在先怎么理解就行。

啟動服務器,然后我們在游覽器中輸入http://localhost:8080/filter/abc,注意,filter是我們自己配置的web工程路徑,后面的abc隨便輸入的。我們下面來查看游覽器后控制臺輸出。

游覽器輸出 

控制臺輸出 

現(xiàn)在,我們就已經(jīng)可以得出兩個結論了,過濾器并不會管資源是否存在,而只會對配置的攔截路徑進行攔截。攔截不僅會對請求進行攔截,而且還會對相應進行攔截。

配置過濾器(Filter)攔截路徑 

配置Filter的攔截路徑有2種方式,一種是注解,一種是xml方式,我們分別進行講解。

注解方式

我們如果使用注解來進行配置,那么我們就需要使用@WebFilter,我們不說廢話,直接看該注解的源碼。

里面的配置項還是有很多的,下面我對常用配置項進行說明:

  • filterName:該filter的名字
  • initParams:初始化參數(shù)
  • displayName:filter顯示名稱
  • servletNames:指定對哪些servlet進行過濾
  •  asyncSupported:是否支持異步模式
  • urlPatterns:指定攔截路徑
  • value:指定攔截路徑

注意:urlPatterns和value是一樣的。urlPatterns和value只能配置一個,不能兩個都配置,兩個都配置就會報錯。

對于使用@WebFilter,里面的多個參數(shù)用 , 進行分隔。 

說明:如果我們僅僅需要配置一個攔截路徑,那么我們可以直接簡寫@WebLister("攔截路徑"),如@WebFilter("/*")就是攔截所有請求。 

xml方式 

xml方式可以說是和Servlet使用xml配置方式一樣了,這里就不廢話,直接配置一個。

    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>com.clucky.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

這個就是xml配置方式,只不過把注解換成了xml標簽來配置,里面屬性都是一樣的,這個和Servlet的配置方式基本一樣,這里就不再贅述了。

過濾器(Filter)生命周期

 我們都知道Servlet有一個生命周期,當然Filter也有一個生命周期,下面我們就來探討一下Filter的生命周期。

Filter的生命周期和Servlet也十分相似,如果大家對Servlet的生命周期不怎么熟悉,那么可以看一下這篇文章Servlet生命周期。

我們創(chuàng)建一個類,實現(xiàn)Filter的所有方法。

import javax.servlet.*;
import java.io.IOException;
public class LifeCycleFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }
    @Override
    public void destroy() {
    }
}

理論說明 

Filter有3個階段,分別是初始化,攔截和過濾,銷毀。

  • 初始化階段:當服務器啟動時,我們的服務器(Tomcat)就會讀取配置文件,掃描注解,然后來創(chuàng)建我們的Filter。
  • 攔截和過濾階段:只要請求資源的路徑和攔截的路徑相同,那么過濾器就會對請求進行過濾,這個階段在服務器運行過程中會一直循環(huán)。
  • 銷毀階段:當服務器(Tomcat)關閉時,服務器創(chuàng)建的Filter也會隨之銷毀。

代碼演示

Filter的三個階段就對應著Filter的3個方法,init方法會在Filter創(chuàng)建時調用,doFilter方法會在請求和攔截匹配時調用,destroy方法會在Filter銷毀時調用。我們來對這些方法進行編寫驗證。

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class LifeCycleFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //這個方法就是初始化方法,在Filter創(chuàng)建時調用
        System.out.println("調用了init()方法");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //這個方法就是過濾和攔截的方法,當請求和攔截匹配時調用
        System.out.println("調用了doFilter()方法");
    }
    @Override
    public void destroy() {
        //這個方法就是銷毀方法,在Filter銷毀前調用
        System.out.println("調用了destroy()方法");
    }
}

啟動服務器控制臺輸出

進行攔截時控制臺輸出 

關閉服務器控制臺輸出 

都和我們預想的一樣,到此,我們就成功驗證了Filter的生命周期。 

FilterConfig和FilterChain說明

FilterConfig和FilterConfig這2個對象是由服務器(Tomcat)在創(chuàng)建和調用Filter對象時所傳入的,這2個對象十分有用,F(xiàn)ilterConfig對象可以讀取我們配置的初始參數(shù),F(xiàn)ilterChain可以實現(xiàn)多個Filter之間的連接。

FilterConfig

老規(guī)矩,我們要學習一個對象,首先查看類圖和源代碼

里面的方法就4個,下面我們分別進行講解

  • getFilterName():獲取filter的名稱
  • getServletContext():獲取ServletContext
  • getInitparamter(String var1):獲取配置的初始參數(shù)的值
  • getInitParamterNames():獲取配置的所有參數(shù)名稱

FilterConfig實例運用

我們在init方法中使用FilterConfig來讀取配置的數(shù)據(jù)庫的信息,然后輸出。

java代碼

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class MyFilterConfig implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("-----------獲取全部key:value------------");
        //得到所有配置參數(shù)的名字
        Enumeration<String> names = filterConfig.getInitParameterNames();
        while (names.hasMoreElements()) {
            //得到每一個名字
            String name = names.nextElement();
            System.out.println(name+" = "+filterConfig.getInitParameter(name));
        }
        System.out.println("-----------end.....------------");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }
    @Override
    public void destroy() {
    }
}

xml配置 

<filter>
        <filter-name>myFilterConfig</filter-name>
        <filter-class>com.clucky.filter.MyFilterConfig</filter-class>
        <init-param>
            <param-name>driver</param-name>
            <param-value>com.mysql.jdbc.Driver</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/equip_employ_manage?serverTimezone=GMT</param-value>
        </init-param>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>root</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>myFilterConfig</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

啟動服務器,控制臺輸出

我們使用FilterConfig提供的方法就成功實現(xiàn)了功能,F(xiàn)ilterConfig就是用來讀取配置文件的。

FilterChain 

一樣,我們還是先來查看源代碼以及類圖

我們查看類圖,可以發(fā)現(xiàn)FilterChain就只有一個方法,其實這個方法就是用來對攔截進行放行的,如果有多個攔截器,那么就會繼續(xù)調用下一個Filter進行攔截。doFilter方法需要傳入個參數(shù),一個是ServletRequest,一個是ServletResponse參數(shù),這個直接傳入進行。

Tomcat在調用過濾器時,默認就會傳入Request和Response,這個參數(shù)封裝了請求和響應,我們直接使用就行。ServletResquest和ServletResponse可以直接強轉成HttpServletRequest和HttpServletResponse,然后使用相應的方法。

 將ServletRequest轉成HttpServletRequest

FilterChain應用實例

我們前面一直都是一個Filter,現(xiàn)在我們來配置2個Filter,通過FilterChain來進行多個過濾。

第一個Filter

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class Filter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("調用過濾器01對請求進行過濾~~~~");
        //放行,如果還有過濾器,那么就執(zhí)行下一個過濾器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("調用過濾器01對響應進行過濾~~~~");
    }
    @Override
    public void destroy() {
    }
}

第二個過濾器

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class Filter02 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("調用過濾器02對請求進行過濾~~~~");
        //放行,如果還有過濾器,那么就執(zhí)行下一個過濾器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("調用過濾器02對響應進行過濾~~~~");
    }
    @Override
    public void destroy() {
    }
}

啟動服務器,然后我們游覽器輸入http://localhost:8080/filter/abc(filter是我配置的web工程路徑)來進行訪問,查看控制臺輸出。

我們可以看見Filter01先進行過濾,然后交給Filter02,然后訪問資源,然后Filter02對響應進行過濾,然后Filter01對響應進行過濾。圖示如下:

我們先使用Filter01對請求進行過濾,那么很自然的,我們就是使用Filter02先對響應進行過濾。 

 多個Filter的執(zhí)行順序

上面我們配置了2個過濾器,那么我們怎么知道那個過濾器先執(zhí)行呢?其實大家可以直接使用代碼進行驗證,培養(yǎng)獨立思考的習慣,這里我就直接給出答案了。

  • 如果我們是在web.xml中配置的過濾器,那么過濾器的執(zhí)行順序就是<filter-mapping>在web配置的順序,配置在上面那么就會先執(zhí)行。
  • 如果我們是使用@WebFilter進行配置的,那么執(zhí)行順序就是字符比較順序來執(zhí)行,例如有2個過濾器,一個是AFilter,一個是BFilter,那么AFilter就會先執(zhí)行。
  • 如果注解和xml混用,那么在web.xml中配置的會先執(zhí)行。

執(zhí)行順序驗證

我這里就驗證第一條,也就是web.xml中配置的順序和<filter-mapping>順序一樣,其他大家感興趣自己驗證。

xml配置順序 3->1->2

    <filter>
        <filter-name>filter03</filter-name>
        <filter-class>com.clucky.filter.Filter03</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter03</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>filter01</filter-name>
        <filter-class>com.clucky.filter.Filter01</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter01</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>filter02</filter-name>
        <filter-class>com.clucky.filter.Filter02</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter02</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Filter01

import javax.servlet.*;
import java.io.IOException;
public class Filter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("調用過濾器01對請求進行過濾~~~~");
        //放行,如果還有過濾器,那么就執(zhí)行下一個過濾器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("調用過濾器01對響應進行過濾~~~~");
    }
    @Override
    public void destroy() {
    }
}

Filter02

import javax.servlet.*;
import java.io.IOException;
public class Filter02 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("調用過濾器02對請求進行過濾~~~~");
        //放行,如果還有過濾器,那么就執(zhí)行下一個過濾器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("調用過濾器02對響應進行過濾~~~~");
    }
    @Override
    public void destroy() {
    }
}

Filter03

import javax.servlet.*;
import java.io.IOException;
public class Filter03 implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("調用過濾器03對請求進行過濾~~~~");
        //放行,如果還有過濾器,那么就執(zhí)行下一個過濾器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("調用過濾器03對響應進行過濾~~~~");
    }
    @Override
    public void destroy() {
    }
}

我們啟動服務器,游覽器訪問,然后查看控制臺輸出是不是我們配置的3->1->2的順序

發(fā)現(xiàn)執(zhí)行順序果然是這樣,另外2個的驗證大家感興趣可以自己驗證,我這里就不驗證了,如果嫌麻煩,那么記住就行了。

Filter應用實例(實現(xiàn)敏感詞匯過濾) 

我們學了那么多,現(xiàn)在來做一個實例,我們寫一個評論頁面,可以進行評論,如果評論中含有我們定義的敏感詞匯,那么我們就進行過濾,使用**來進行代替。

代碼實現(xiàn)

jsp頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>評論</title>
</head>
<body>
<h1>輸入評論內容</h1>
<form action="${pageContext.request.contextPath}/comment" method="post">
    <textarea name="message" cols="30" rows="10"></textarea>
    <input type="submit" value="提交">
</form>
<p >${requestScope.get("name")}<span style="color: red">${requestScope.get("comment")}</span></p>
</body>
</html>

Filter代碼

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebFilter(servletNames = {"comment"},initParams = {@WebInitParam(name = "sensitiveWord", value = "zz")})
public class CommentFilter implements Filter {
    private List<String> sensitiveWords = new ArrayList<>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //得到敏感詞匯
        String word = filterConfig.getInitParameter("sensitiveWord");
        //加入集合
        sensitiveWords.add(word);
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //設置編碼
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        //得到評論
        String message = servletRequest.getParameter("message");
        for (String sensitiveWord : sensitiveWords) {
            //對所有敏感詞匯進行過濾
            if (message.contains(sensitiveWord)){
                //替換敏感詞匯
                message = message.replace(sensitiveWord, "**");
            }
        }
        //存入request域
        servletRequest.setAttribute("comment",message);
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
    }
}

Servlet代碼

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.HashSet;
@WebServlet(name = "comment",value = "/comment")
public class CommentServlet extends HttpServlet {
    //記錄評論敏感詞匯的ip
    private HashSet<String> hashSet = new HashSet<>();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String message = request.getParameter("message");
        String comment = (String) request.getAttribute("comment");
        if (message.equals(comment)){
            System.out.println("沒有敏感詞匯.....");
            //設置名字
            request.setAttribute("name","good boy:");
        }else {
            //有敏感詞匯,記錄IP
            String localAddr = request.getLocalAddr();
            System.out.println(localAddr);
            hashSet.add(localAddr);
            //設置名字
            request.setAttribute("name","bad boy:");
        }
        //轉發(fā)到comment.jsp頁面
        request.getRequestDispatcher("/comment.jsp").forward(request,response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

代碼驗證

我們輸入http://localhost:8080/filter/comment.jsp,來訪問jsp頁面.

         輸入評論內容:你好?。。?

下面顯示了我們的評論,我們再來輸入:你真是個zz

 顯示你真是個**,我們的評論過濾就成功了。

總結 

到此這篇關于一文詳解JavaWeb過濾器(Filter)的文章就介紹到這了,更多相關Java 過濾器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家

相關文章

最新評論