亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java Filter過濾器的使用教程

 更新時間:2023年01月13日 10:34:53   作者:@每天都要敲代碼  
Filter也稱之為過濾器,它是Servlet技術(shù)中最實用的技術(shù),Web開發(fā)人員通過Filter技術(shù),對web服務(wù)器管理的所有web資源:例如Jsp, Servlet, 靜態(tài)圖片文件或靜態(tài) html 文件等進行攔截,從而實現(xiàn)一些特殊的功能

一、過濾器的使用以及實現(xiàn)原理

當(dāng)前的oa項目還存在什么缺陷

①對于DeptServlet、EmpServlet、OrderServlet,每一個Servlet都是處理自己相關(guān)的業(yè)務(wù);在這些Servlet執(zhí)行之前都是需要判斷用戶是否登錄了。如果用戶登錄了,可以繼續(xù)操作,如果沒有登錄,需要用戶登錄。

②這段判斷用戶是否登錄的代碼是固定的,并且在每一個Servlet類當(dāng)中都需要編寫,顯然代碼沒有得到重復(fù)利用。包括每一個Servlet都要解決中文亂碼問題,也有公共的代碼。這些代碼目前都是重復(fù)編寫,并沒有達到復(fù)用。

③怎么解決這個問題?

可以使用Servlet規(guī)范中的Filter過濾器來解決這個問題。

Filter作用與執(zhí)行原理

①Filter是過濾器。

②Filter可以在Servlet這個目標(biāo)程序執(zhí)行之前添加代碼,也可以在目標(biāo)Servlet執(zhí)行之后添加代碼;之前之后都可以添加過濾規(guī)則!

③一般情況下,都是在過濾器當(dāng)中編寫公共代碼。

過濾器怎么寫

(1)編寫一個Java類實現(xiàn)javax.servlet.Filter接口,并且實現(xiàn)這個接口當(dāng)中所有的方法;有三個方法:

①init方法:在Filter對象第一次被創(chuàng)建之后調(diào)用,并且只調(diào)用一次。

②doFilter方法:只要用戶發(fā)送一次請求,則執(zhí)行一次;發(fā)送N次請求,則執(zhí)行N次。在這個方法中編寫過濾規(guī)則!

③destroy方法:在Filter對象被釋放/銷毀之前調(diào)用,并且只調(diào)用一次。

package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:MyFilter
 */
public class MyFilter implements Filter {
    public MyFilter() {
        System.out.println("無參數(shù)構(gòu)造方法執(zhí)行");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法執(zhí)行");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("Filter1 doFilter方法開始執(zhí)行");
    }
    @Override
    public void destroy() {
        System.out.println("destroy方法執(zhí)行");
    }
}

(2)在web.xml文件中對Filter進行配置,這個配置和Servlet很像。

或者使用注解:@WebFilter({"*.do"})

<?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>myfilter</filter-name>
        <filter-class>com.bjpowernode.javaweb.servlet.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <url-pattern>/a.do</url-pattern>
    </filter-mapping>
</web-app>

(3)打開服務(wù)器,無參構(gòu)造方法和init方法都會執(zhí)行;訪問時doFilter方法才會執(zhí)行。

①Servlet對象默認情況下,在服務(wù)器啟動的時候是不會新建對象的。

②Filter對象默認情況下,在服務(wù)器啟動的時候會新建對象,執(zhí)行無參構(gòu)造方法。

③Servlet是單例的,F(xiàn)ilter也是單例的。

(4)編寫兩個類AServlet和BServlet繼承HttpServlet,并且AServlet路徑定義為/a.do(和上面一樣),BServlet路徑定義為/b.do

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:Aservlet
 */
@WebFilter("/a.do")
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("AServlet中的doGet方法執(zhí)行了。");
    }
}

BServlet類

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:BServlet
 */
@WebFilter("/b.do")
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("BServlet中的doGet方法執(zhí)行了。");
    }
}

發(fā)送請求:http://localhost:8080/servlet14/a.do發(fā)現(xiàn)只有過濾器MyFilter類中的doFilter方法執(zhí)行了;而AServlet中的方法并沒有執(zhí)行:

(5)按理說我們發(fā)送http://localhost:8080/servlet14/a.doAservlet和MyFilter都會執(zhí)行,因為路徑都是/a.do ;實際上目標(biāo)Servlet(Aservlet)是否執(zhí)行,取決于兩個條件:

①第一:在過濾器當(dāng)中是否編寫了:chain.doFilter(request, response); 代碼。

②第二:用戶發(fā)送的請求路徑是否和Servlet的請求路徑一致。

注意:chain.doFilter(request, response); 這行代碼的作用:執(zhí)行下一個過濾器,如果下面沒有過濾器了,執(zhí)行最終的Servlet。

注意:Filter的優(yōu)先級,天生的就比Servlet優(yōu)先級高。/a.do 對應(yīng)一個Filter,也對應(yīng)一個Servlet。那么一定是先執(zhí)行Filter,然后再執(zhí)行Servlet!

所以不妨重寫一下doFilter方法,然后再次去訪問:

package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:MyFilter
 */
public class MyFilter implements Filter {
    public MyFilter() {
        System.out.println("無參數(shù)構(gòu)造方法執(zhí)行");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法執(zhí)行");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 在請求的時候添加過濾規(guī)則。
        System.out.println("Filter1 doFilter方法開始執(zhí)行");
        // 執(zhí)行下一個過濾器,如果下一個不是過濾器了,則執(zhí)行目標(biāo)程序Servlet
        // 簡單理解就是向下走
        chain.doFilter(request,response);
        // 在響應(yīng)的時候添加過濾規(guī)則。
        System.out.println("Filter1 doFilter方法執(zhí)行結(jié)束。");
    }
    @Override
    public void destroy() {
        System.out.println("destroy方法執(zhí)行");
    }
}

執(zhí)行結(jié)果如下:

三句話都執(zhí)行了,所以現(xiàn)在對于上面那個圖就更加容易理解了:

①發(fā)送請求的時候,經(jīng)過了過濾器;

②執(zhí)行chain.doFilter(request, response); 執(zhí)行下一個過濾器或者Servlet;

③進行響應(yīng)也會經(jīng)過過濾器;

補充:

①@WebFilter("/a.do") 精確匹配,只有發(fā)送a.do才會經(jīng)過這個過濾器。

②@WebFilter({"/a.do", "/b.do"}) 匹配一個數(shù)組,發(fā)送a.do和b.do都可以經(jīng)過這個過濾器。

③@WebFilter("*.do") 模糊匹配中的擴展匹配。以星號開始,注意這種路徑不要以/開始。

④@WebFilter("/dept/*")屬于前綴匹配。要以/開始。

⑤@WebFilter("/*")匹配所有的路徑。

過濾器的調(diào)用順序

過濾器的調(diào)用順序,遵循棧數(shù)據(jù)結(jié)構(gòu)。 下面通過一個例子來理解:

注意:在web.xml文件中進行配置的時候,F(xiàn)ilter的執(zhí)行順序是什么?

依靠filter-mapping標(biāo)簽的配置位置,越靠上優(yōu)先級越高。

注意:使用注解@WebFilter的時候,F(xiàn)ilter的執(zhí)行順序是怎樣的呢?

執(zhí)行順序是:比較Filter這個類名。

比如:FilterA和FilterB,則先執(zhí)行FilterA

比如:Filter1和Filter2,則先執(zhí)行Filter1

定義一個MyFilter1過濾器

package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法執(zhí)行");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {       
        System.out.println("Filter1 doFilter方法開始執(zhí)行");
        chain.doFilter(request,response);
        System.out.println("Filter1 doFilter方法執(zhí)行結(jié)束。");
    }
    @Override
    public void destroy() {
        System.out.println("destroy方法執(zhí)行");
    }
}

定義一個MyFilter2過濾器

package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Filter2 doFilter begin");
        chain.doFilter(request, response);
        System.out.println("Filter2 doFilter end");
    }
    @Override
    public void destroy() {
    }
}

選擇在xml文件中配置,對應(yīng)的web.xml文件

<?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>myfilter</filter-name>
        <filter-class>com.bjpowernode.javaweb.servlet.MyFilter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>myfilter2</filter-name>
        <filter-class>com.bjpowernode.javaweb.servlet.MyFilter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter2</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
</web-app>

定義一個AServlet類,路徑通過注解的方式

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/a.do")
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("AServlet中的doGet方法執(zhí)行了。");
    }
}

Filter的優(yōu)先級是比Servlet高的,所以當(dāng)進行訪問時:http://localhost:8080/servlet14/a.do會先按照web.xml文件中的filter-mapping標(biāo)簽位置進行訪問,遇到chain.doFilter(request, response)就會跳轉(zhuǎn)到下一個Filter或者Servlet;所以最終結(jié)果如下:

Filter的生命周期

①Filter的生命周期和Servlet對象生命周期一致。

②唯一的區(qū)別:Filter默認情況下,在服務(wù)器啟動階段就實例化;而Servlet不會。

二、責(zé)任鏈設(shè)計模式改造oa項目

(1)我們先看一段java代碼;這段代碼也能實現(xiàn)過濾器的效果,遵循棧數(shù)據(jù)結(jié)構(gòu)。但是這個程序的問題:在編譯階段已經(jīng)完全確定了調(diào)用關(guān)系。 如果你想改變他們的調(diào)用順序,必須修改以下java源代碼。java代碼修改,需要重新編譯,項目需要重新測試,項目需要重新發(fā)布。這是一個繁瑣的過程。顯然,這種設(shè)計違背了:OCP原則。(開閉原則)

package com.bjpowernode.javaweb.servlet;
public class Test {
    public static void main(String[] args) {
        System.out.println("main begin");
        m1();
        System.out.println("main over");
    }
    private static void m1() {
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }
    private static void m2() {
        System.out.println("m2 begin");
        m3();
        System.out.println("m2 over");
    }
    private static void m3() {
        System.out.println("目標(biāo)正在執(zhí)行中。。。。");
    }
}

(2)Filter過濾器里有一個設(shè)計模式 :責(zé)任鏈設(shè)計模式。

過濾器最大的優(yōu)點: 在程序編譯階段不會確定調(diào)用順序。因為Filter的調(diào)用順序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的順序就可以調(diào)整Filter的執(zhí)行順序。顯然Filter的執(zhí)行順序是在程序運行階段動態(tài)組合的。那么這種設(shè)計模式被稱為責(zé)任鏈設(shè)計模式。

注:責(zé)任鏈設(shè)計模式最大的核心思想:在程序運行階段,動態(tài)的組合程序的調(diào)用順序!

tip:對于過濾器Filter的配置一般是配置到web.xml文件當(dāng)中,不要使用注解的方式;這樣更加的容易修改它們的執(zhí)行順序。

(3)使用過濾器改造OA項目

①首先配置web.xml文件

    <filter>
        <filter-name>loginfilter</filter-name>
        <filter-class>com.bjpowernode.oa.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

②編寫一個過濾器,作為判斷的登錄

目前寫的路徑是:/* 表示所有的請求均攔截,所以要先分析一下,什么情況下不能攔截?

??用戶訪問 index.jsp的時候不能攔截

??用戶已經(jīng)登錄了,這個需要放行,不能攔截。

??用戶要去登錄,這個也不能攔截。

??WelcomeServlet也不能攔截。

package com.bjpowernode.oa.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.oa.filter
 * @Project:JavaWeb
 * @name:LoginFilter
 */
public class LoginFilter implements Filter {
    // 也可以只重寫其中一個方法
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        // 注意這里要先進行強轉(zhuǎn)為HttpServlet,后面才能調(diào)用對應(yīng)的方法
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 獲取請求路徑
        String servletPath = request.getServletPath();
        // 獲取當(dāng)前session對象,獲取不到就返回null
        HttpSession session = request.getSession(false);
        if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath)
                || (session != null && session.getAttribute("username") != null)){
            // 經(jīng)過上面過濾,只有上面的路徑才會直接通過;其它的操作都要先跳轉(zhuǎn)到登錄頁面
            // 繼續(xù)往下走
            chain.doFilter(request, response);
        }else{
            response.sendRedirect(request.getContextPath() + "/index.jsp");
        }
    }
}

這個過濾器寫好以后,以后其它類也可以調(diào)用這個過濾器,都不用驗證登錄了;例如:一個員工的Servlet(EmpServlet)

package com.bjpowernode.oa.web.action;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
/**
 * 員工管理的。
 * 員工管理的前提也是需要先登錄。
 */
public class EmpServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 亂碼問題也可以寫入過濾器當(dāng)中
        // post請求亂碼問題
        request.setCharacterEncoding("UTF-8");
        // 響應(yīng)中文亂碼問題
        response.setContentType("text/html;charset=UTF-8");
        HttpSession session = request.getSession(false);
        if(session != null && session.getAttribute("username") != null){
            String servletPath = request.getServletPath();
            //...
        }else{
            response.sendRedirect(request.getContextPath() + "/index.jsp");
        }
    }
}

對于原來的DeptServlet類也可以進行修改了:

        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("username") != null){ // session對象不一定為null
            // 獲取servlet path
            String servletPath = request.getServletPath();
            if ("/dept/list".equals(servletPath)){
                doList(request,response);
            }else if("/dept/detail".equals(servletPath)){
                doDetail(request,response);
            }else if("/dept/delete".equals(servletPath)) {
                doDel(request, response);
            }else if("/dept/add".equals(servletPath)) {
                doAdd(request, response);
            }else if("/dept/modify".equals(servletPath)) {
                doModify(request, response);
            }
        }else{
            // 跳轉(zhuǎn)到登錄頁面
            response.sendRedirect(request.getContextPath()+"/index.jsp");
        }

修改為:

        String servletPath = request.getServletPath();
        if ("/dept/list".equals(servletPath)){
            doList(request,response);
        }else if("/dept/detail".equals(servletPath)){
            doDetail(request,response);
        }else if("/dept/delete".equals(servletPath)) {
            doDel(request, response);
        }else if("/dept/add".equals(servletPath)) {
            doAdd(request, response);
        }else if("/dept/modify".equals(servletPath)) {
            doModify(request, response);
        }

到此這篇關(guān)于Java Filter過濾器的使用教程的文章就介紹到這了,更多相關(guān)Java Filter過濾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 前端存token后端獲取token代碼實例(Spring?Boot)

    前端存token后端獲取token代碼實例(Spring?Boot)

    Token其實就是訪問資源的憑證,一般是用戶通過用戶名和密碼登錄成功之后,服務(wù)器將登陸憑證做數(shù)字簽名,加密之后得到的字符串作為token,這篇文章主要給大家介紹了關(guān)于前端存token,Spring?Boot后端獲取token的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • 實例分析java對象中淺克隆和深克隆

    實例分析java對象中淺克隆和深克隆

    在本篇文章中我們給大家分享了關(guān)于java對象中淺克隆和深克隆的相關(guān)知識點和相關(guān)代碼內(nèi)容,有興趣的朋友們學(xué)習(xí)下。
    2018-10-10
  • 如何在Spring?Boot框架中使用攔截器實現(xiàn)URL限制

    如何在Spring?Boot框架中使用攔截器實現(xiàn)URL限制

    在Spring?Boot框架中,您可以使用攔截器(Interceptor)來控制限制URL列表,本文通過一個簡單的示例給大家介紹Spring?Boot?攔截器實現(xiàn)URL限制的操作方法,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • 基于Intellij Idea亂碼的解決方法

    基于Intellij Idea亂碼的解決方法

    下面小編就為大家分享一篇基于Intellij Idea亂碼的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • java中staticclass靜態(tài)類詳解

    java中staticclass靜態(tài)類詳解

    這篇文章主要介紹了java中staticclass靜態(tài)類詳解,具有一定借鑒價值,需要的朋友可以了解下。
    2017-12-12
  • 詳解java中的Collections類

    詳解java中的Collections類

    這篇文章主要為大家詳細介紹了java中的Collections類,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 詳解Springboot整合ActiveMQ(Queue和Topic兩種模式)

    詳解Springboot整合ActiveMQ(Queue和Topic兩種模式)

    這篇文章主要介紹了詳解Springboot整合ActiveMQ(Queue和Topic兩種模式),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Java中的ReentrantLock使用解析

    Java中的ReentrantLock使用解析

    這篇文章主要介紹了Java中的ReentrantLock使用解析,ReentrandLock即可重入鎖,可重入鎖解決的是重入鎖定的問題,重入鎖定指的是當(dāng)一個線程執(zhí)行邏輯時,需要兩次獲取鎖,而該鎖不可重入就會導(dǎo)致內(nèi)部嵌套無法獲取鎖導(dǎo)致Reentrance Lockout發(fā)生,需要的朋友可以參考下
    2023-11-11
  • SpringMVC接收復(fù)雜集合對象(參數(shù))代碼示例

    SpringMVC接收復(fù)雜集合對象(參數(shù))代碼示例

    這篇文章主要介紹了SpringMVC接收復(fù)雜集合對象(參數(shù))代碼示例,舉接收List<String>、List<User>、List<Map<String,Object>>、User[]、User(bean里面包含List)幾種較為復(fù)雜的集合參數(shù),具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Springcloud實現(xiàn)服務(wù)多版本控制的示例代碼

    Springcloud實現(xiàn)服務(wù)多版本控制的示例代碼

    這篇文章主要介紹了Springcloud實現(xiàn)服務(wù)多版本控制的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05

最新評論