JavaWeb- Filter 和 Listener


Filter和Listener


1. Filter

  1. 概念:Filter(過濾器),當(dāng)訪問服務(wù)器資源時(shí),過濾器可以將請(qǐng)求攔截下來完成一系列特殊的功能。
  2. 作用:Filter一般用于完成通用的操作,如:登錄驗(yàn)證,統(tǒng)一編碼處理,敏感字符的過濾。
  3. 使用步驟:
    1. 定義一個(gè)類并實(shí)現(xiàn)接口Filter
    2. 復(fù)寫Filter接口中的方法
    3. 配置攔截路徑:
      • web.xml配置攔截路徑
        <!-- 在web.xml中 -->
        <!-- 過濾器配置 -->
        <filter>
            <!-- 配置過濾器的名稱 -->
            <filter-name>demo</filter-name>
            <!-- 配置過濾器的全類名 -->
            <filter-class>com.hsh.study.web.filter.FilterDemo</filter-class>
        </filter>
        <!-- 配置過濾器映射 -->
        <filter-mapping>
            <!-- 對(duì)應(yīng)過濾器的名稱 -->
            <filter-name>demo</filter-name>
            <!-- 配置攔截路徑 -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
      • 通過注解的方式配置攔截路徑
        // 訪問所有資源之前,都會(huì)執(zhí)行該過濾器
        @WebFilter("/*")
        // 定義的類實(shí)現(xiàn)Filter
        public class FilterDemo1 implements Filter {
            // 過濾器初始化方法
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {
            }
            // 主要方法
            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                // 訪問資源文件之前會(huì)先執(zhí)行此重寫方法,只有資源放行后才能訪問
                System.out.println("filterDemo1被執(zhí)行了....");
                // 放行
                filterChain.doFilter(servletRequest,servletResponse);
            }
            // 過濾器銷毀方法
            @Override
            public void destroy() {
            }
        }
        
  4. 過濾器的執(zhí)行執(zhí)行過程:
    1. 執(zhí)行過濾器
    2. 執(zhí)行放行后的資源
    3. 回來執(zhí)行過濾器放行代碼后的代碼
  5. 過濾器的生命周期:
    1. init:在服務(wù)器啟動(dòng)后,創(chuàng)建Filter對(duì)象然后調(diào)用init方法。只執(zhí)行一次,通常用于加載資源。
    2. doFilter:在每一次請(qǐng)求被攔截資源時(shí)執(zhí)行,執(zhí)行多次。
    3. destory:在服務(wù)器關(guān)閉后,F(xiàn)ilter對(duì)象被銷毀。如果服務(wù)器時(shí)正常關(guān)閉,則執(zhí)行destory方法。只執(zhí)行一次,通常用于釋放資源
  6. 過濾器的配置:
    • 攔截路徑配置
      1. 具體的資源路徑: /index.jsp 只有訪問index.jsp時(shí),過濾器才會(huì)被執(zhí)行。
      2. 攔截目錄: /user/* 訪問/user下的資源時(shí),過濾器都會(huì)被執(zhí)行。
      3. 后綴名攔截: *.jsp 訪問所有后綴名為.jsp的文件時(shí),過濾器都會(huì)被執(zhí)行。
      4. 攔截所有資源: /* 訪問所有資源時(shí),過濾器都會(huì)被執(zhí)行。
    • 攔截方式配置:資源被訪問的方式
      1. 注解配置
        • 設(shè)置dispatcherTypes屬性:
          1. REQUEST:默認(rèn)值,瀏覽器直接請(qǐng)求資源
          2. FORWARD:轉(zhuǎn)發(fā)訪問資源
          3. INCLUDE:包含訪問資源
          4. ERROR:錯(cuò)誤跳轉(zhuǎn)資源
          5. ASYNC:異步訪問資源
      2. web.xml配置
        • 設(shè)置<dispatcher></dispatcher>標(biāo)簽即可
  7. 過濾器鏈(配置多個(gè)過濾器時(shí))
    • 執(zhí)行順序:假設(shè)有兩個(gè)過濾器<過濾器1,過濾器2>
      graph LR
      A[過濾器1]-->B[過濾器2]
      B[過濾器2]-->C[放行后資源執(zhí)行]
      C[放行后資源執(zhí)行]-->D[過濾器2]
      D[過濾器2]-->E[過濾器1]
      
    • 過濾器執(zhí)行順序:
      1. 注解配置
        • 按照類名的字符串比較規(guī)則比較,值小的先執(zhí)行。如 AFilter和BFilter,先執(zhí)行AFilter
      2. web.xml配置
        • 誰的<filter-mapping></filter-mapping>定義在上邊,誰先執(zhí)行。

代理模式

  • 概念:
    1. 真實(shí)對(duì)象:被代理的對(duì)象
    2. 代理對(duì)象:代理真實(shí)的對(duì)象
    3. 代理模式:代理對(duì)象代理真實(shí)對(duì)象,達(dá)到增強(qiáng)真實(shí)對(duì)象功能的目的
  • 實(shí)現(xiàn)方法:
    1. 靜態(tài)代理:有一個(gè)類文件描述代理模式
    2. 動(dòng)態(tài)代理:在內(nèi)存中形成代理類
      • 實(shí)現(xiàn)步驟:
        1. 代理對(duì)象和真實(shí)對(duì)象實(shí)現(xiàn)相同的接口
        2. 代理對(duì)象 = Proxy.newProxyInstance();
        3. 使用代理對(duì)象調(diào)用方法
        4. 增強(qiáng)原有對(duì)象的方法
      • 增強(qiáng)方式:
        1. 增強(qiáng)參數(shù)列表
        2. 增強(qiáng)返回值類型
        3. 增強(qiáng)方法體執(zhí)行邏輯
  • 具體的實(shí)現(xiàn)
    // 接口類
    public interface SaleComputer {
        public String sale(double money);
        public void show();
    }
    // 實(shí)現(xiàn)接口的實(shí)體類
    public class Lenovo implements SaleComputer {
        @Override
        public String sale(double money) {
            System.out.println("花了"+money+"元買了一臺(tái)聯(lián)想電腦...");
            return "聯(lián)想電腦";
        }
        @Override
        public void show() {
            System.out.println("展示電腦....");
        }
    }

    //動(dòng)態(tài)代理實(shí)現(xiàn)類
    public class ProxyTest {
        public static void main(String[] args) {
            //1.創(chuàng)建真實(shí)對(duì)象
            Lenovo lenovo = new Lenovo();
            //2.動(dòng)態(tài)代理增強(qiáng)lenovo對(duì)象
            /*
                三個(gè)參數(shù):
                    1. 類加載器:真實(shí)對(duì)象.getClass().getClassLoader()
                    2. 接口數(shù)組:真實(shí)對(duì)象.getClass().getInterfaces()
                    3. 處理器:new InvocationHandler()
            */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
           /*
               代理邏輯編寫的方法:代理對(duì)象調(diào)用的所有方法都會(huì)觸發(fā)該方法執(zhí)行
                   參數(shù):
                       1. proxy:代理對(duì)象
                       2. method:代理對(duì)象調(diào)用的方法,被封裝為的對(duì)象
                       3. args:代理對(duì)象調(diào)用的方法時(shí),傳遞的實(shí)際參數(shù)
            */
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               /*System.out.println("該方法執(zhí)行了....");
               System.out.println(method.getName());
               System.out.println(args[0]);
               */
               //判斷是否是sale方法
               if(method.getName().equals("sale")){
                   //1.增強(qiáng)參數(shù)
                   double money = (double) args[0];
                   money = money * 0.85;
                   System.out.println("專車接你....");
                   //使用真實(shí)對(duì)象調(diào)用該方法
                   String obj = (String) method.invoke(lenovo, money);
                   System.out.println("免費(fèi)送貨...");
                   //2.增強(qiáng)返回值
                   return obj+"_鼠標(biāo)墊";
               }else{
                   Object obj = method.invoke(lenovo, args);
                   return obj;
               }
             }
         });
         //3.調(diào)用方法
         String computer = proxy_lenovo.sale(8000);
         System.out.println(computer);
         proxy_lenovo.show();
        }
    }

2. Listener

  1. 概念:
    • 事件監(jiān)聽機(jī)制:
      1. 事件:一件事情
      2. 事件源:事件發(fā)生的地方
      3. 監(jiān)聽器:一個(gè)對(duì)象
      4. 注冊(cè)監(jiān)聽:將事件、事件源、監(jiān)聽器綁定在一起。當(dāng)事件源上發(fā)生指定事件時(shí),執(zhí)行監(jiān)聽器處理事件。
  2. 按監(jiān)聽的對(duì)象Servlet監(jiān)聽器可以分為如下幾類:
    1. 監(jiān)聽?wèi)?yīng)用程序環(huán)境(ServletContext)
    2. 監(jiān)聽繪畫對(duì)象(HttpSession)
    3. 監(jiān)聽請(qǐng)求消息對(duì)象(ServletRequest)
  3. 監(jiān)聽器常用接口
    1. ServletContextListener接口
      • 用于監(jiān)聽代表Web應(yīng)用程序的ServletContext對(duì)象創(chuàng)建和銷毀的事件
    2. HttpSessionListener接口
      • 用于監(jiān)聽Web應(yīng)用程序中的用戶會(huì)話HttpSession對(duì)象的創(chuàng)建和銷毀的事件
      • HttpSessionListener接口可以在session創(chuàng)建后或session無效前得到通知,接口中的方法為:
        1. sessionCreated():session創(chuàng)建時(shí)調(diào)用此方法
        2. sessionDestoryed():session銷毀前調(diào)用該方法
    3. ServletRequestListener接口
      • 用于監(jiān)聽Web應(yīng)用程序中的ServletRequest對(duì)象的創(chuàng)建和銷毀的事件
  4. ServletContextListener:監(jiān)聽ServletContext對(duì)象的創(chuàng)建和銷毀
    • 方法:
      • void contextDestoryed(ServletContextEvent sce) : ServletContext對(duì)象被銷毀之前會(huì)調(diào)用該方法
      • void contextInitialized(ServletContextEvent sce) : ServletContext對(duì)象創(chuàng)建后會(huì)調(diào)用該方法
    • 步驟:
      1. 定義一個(gè)類,實(shí)現(xiàn)ServletContextListener接口
      2. 復(fù)寫方法
      3. 配置
        • web.xml的配置
              <listener>
              <!-- 監(jiān)聽器所在的全類名 -->
              <listener-class>com.hsh.study.ContextLoaderListener</listener-class>
              </listener>
          
        • 注解配置: @WebListener
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容