第6章 filter(4課時(shí))過(guò)濾器和監(jiān)聽(tīng)器

課程目標(biāo)

掌握過(guò)濾器概念及兩種編寫(xiě)方法

過(guò)濾器Filter

過(guò)濾器也叫攔截器,在一個(gè)層面上解決問(wèn)題骡送。
應(yīng)用:用來(lái)做統(tǒng)一編碼解碼、用來(lái)做權(quán)限驗(yàn)證、做網(wǎng)站計(jì)數(shù)等等
特殊說(shuō)明:過(guò)濾器可以是一個(gè)鏈搀绣。也就是說(shuō)可以配置多個(gè)過(guò)濾器,我們也可以通過(guò)配置來(lái)控制順序

怎么建filter

servlet3.0以后滤蝠⊥阆ǎ可以用向?qū)Ы?br> 例如:我建一個(gè)統(tǒng)一做編碼處理的

我們之前在每個(gè)servlet里要寫(xiě)

request.setChararcterEncoding("utf-8");
response.setChararcterEncoding("utf-8");

file-new -Filter-按向?qū)б徊讲脚渲谩?br> step1 為filter起個(gè)文件名CharacterFilter
step2 設(shè)置初始化參數(shù) encoding:UTF-8
step3 mapping 配置過(guò)濾對(duì)象(1--可以對(duì)指定的servlet進(jìn)行過(guò)濾 2--可以配置過(guò)濾規(guī)則)

配置完成后生成如下代碼:

package com.neuedu.utils;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;


@WebFilter(
        urlPatterns = { "/*" }, 
        initParams = { 
                @WebInitParam(name = "encoding", value = "UTF-8")
        })
public class CharacterFilter implements Filter {


public CharacterFilter() {
// TODO Auto-generated constructor stub
}

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here

        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

我們看到有三個(gè)主要方法

init() 初始化方法:做準(zhǔn)備工作

doFilter() 業(yè)務(wù)方法
需要注意的是:j里面有一個(gè)
chain.doFilter(request, response);這句話的意思是執(zhí)行完該過(guò)濾器后去執(zhí)行下一個(gè)過(guò)濾器
用@WebFilter方式配置的過(guò)濾器執(zhí)行順序是按filterName首字母的先后順序執(zhí)行。

destroy() 銷(xiāo)毀方法:做清理工作

完整代碼如下:

package com.neuedu.utils;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * Servlet Filter implementation class CharacterFilter
 */
@WebFilter(
        filterName="MyFilter",
        urlPatterns = { "/*" }, 
        initParams = { 
                @WebInitParam(name = "encoding", value = "UTF-8")
        })
public class CharacterFilter implements Filter {
    String encode="";
     /**
 * Default constructor. 
 */
public CharacterFilter() {
// TODO Auto-generated constructor stub
}
    
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        //在初始化時(shí)準(zhǔn)備好編碼方式
        encode=fConfig.getInitParameter("encoding");
    }
   
/**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encode);
        response.setCharacterEncoding(encode);
        //執(zhí)行下一個(gè)過(guò)濾器
        chain.doFilter(request, response);
    }
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        encode="";
    }
}

filter另外一種創(chuàng)建方式

servlet3.0之前

簡(jiǎn)化版

java類

public class TestFilter implements Filter {
    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig fconfig) throws ServletException {
    }

}

配置:

<filter>
        <filter-name>TestFilter</filter-name>
        <filter-class>com.neuedu.utils.TestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

分兩步
step1 寫(xiě)一個(gè)類實(shí)現(xiàn)filter接口

package com.neuedu.utils;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyFilter implements Filter {
    FilterConfig fconfig=null;
    @Override
    public void destroy() {
        fconfig=null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String encode=fconfig.getInitParameter("encode");
        request.setCharacterEncoding(encode);
        response.setCharacterEncoding(encode);
        //執(zhí)行下一個(gè)過(guò)濾器
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        fconfig=config;
    }

}

step2 在WEB-INF\web.xml里配置
配置分兩步
第一步filter 第二步配置filter-mapping

 <filter>
  <filter-name>MyFilter</filter-name>
  <filter-class>com.neuedu.utils.MyFilter</filter-class>
  <init-param>
  <param-name>encode</param-name>
  <param-value>utf-8</param-value>
  </init-param>
  </filter>
  
  <filter-mapping>
   <filter-name>MyFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>

過(guò)濾器使用

日志記錄
登錄驗(yàn)證
編碼處理

后臺(tái)登錄攔截

可以定個(gè)規(guī)則物咳,比如所有需要登錄才能訪問(wèn)的jsp和servlet都加上/admin前綴

    @WebFilter("/admin/*")
    public class LoginFilter implements Filter {
    
        /**
         * Default constructor. 
         */
        public LoginFilter() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see Filter#destroy()
         */
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        /**
         * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
         */
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            // place your code here
            System.out.println("進(jìn)入攔截器");
            //在此處做用戶是否登錄的驗(yàn)證
            //判斷session里是否存在loginUser
            HttpServletRequest httprequest=(HttpServletRequest)request;
            HttpSession session=httprequest.getSession();
            Object obj=session.getAttribute("loginUser");
            if(obj!=null){
                //如果有就放行
                chain.doFilter(request, response);
                return ;
            }else{
                //如果沒(méi)有锣险,就回登錄頁(yè)
                HttpServletResponse httpresponse=(HttpServletResponse)response;
                httpresponse.sendRedirect(httprequest.getContextPath()+"/login.jsp");
            }
        }
    
        /**
         * @see Filter#init(FilterConfig)
         */
        public void init(FilterConfig fConfig) throws ServletException {
            // TODO Auto-generated method stub
        }
    
    }

監(jiān)聽(tīng)器

監(jiān)聽(tīng)事件蹄皱,比如session建立,系統(tǒng)啟動(dòng)芯肤,請(qǐng)求到達(dá)
本質(zhì)也是java類巷折。
建立方式
file-new listener-輸入名稱-選擇監(jiān)聽(tīng)器種類

比如我選擇了以下三個(gè) ServletContextListener, HttpSessionListener, ServletRequestListener
系統(tǒng)會(huì)自動(dòng)生成如下類

package com.neuedu.utils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Application Lifecycle Listener implementation class TestLisenter
 *
 */
@WebListener
public class TestLisenter implements ServletContextListener, HttpSessionListener, ServletRequestListener {

/**
 * Default constructor. 
 */
public TestLisenter() {
// TODO Auto-generated constructor stub
}

    /**
 * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
 */
public void sessionCreated(HttpSessionEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletRequestListener#requestDestroyed(ServletRequestEvent)
 */
public void requestDestroyed(ServletRequestEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletRequestListener#requestInitialized(ServletRequestEvent)
 */
public void requestInitialized(ServletRequestEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
 */
public void sessionDestroyed(HttpSessionEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletContextListener#contextDestroyed(ServletContextEvent)
 */
public void contextDestroyed(ServletContextEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletContextListener#contextInitialized(ServletContextEvent)
 */
public void contextInitialized(ServletContextEvent arg0)  { 
 // TODO Auto-generated method stub
}

}

仿照下面程序做一個(gè)在線人數(shù)統(tǒng)計(jì)計(jì)數(shù)器

https://blog.csdn.net/troubleshooter/article/details/78416857

注意:
1、application 的類型為ServletContext
2崖咨、可使用哪些方法取得Web容器環(huán)境ServletContext對(duì)象?
request.getServletContext 锻拘、 sessoin.getServletContext 、 servletConfig.getServletContext
在編寫(xiě)Servlet時(shí)击蹲,需要繼承HttpServlet類署拟,在Servlet中聲明doGet()和doPost()需要HttpServletRequest和HttpServletResponse類型的兩個(gè)參數(shù)。
ServletContextListener:服務(wù)啟動(dòng)和停止時(shí)觸發(fā)期初始化和銷(xiāo)毀(生命周期最長(zhǎng))
HttpSessionListener:session的建立和銷(xiāo)毀(session超時(shí)或調(diào)用invalidate()方法)時(shí)觸發(fā)期初始化和銷(xiāo)毀(其次)
ServletRequestListener:一次請(qǐng)求和響應(yīng)有效(最短)

如果同時(shí)存在監(jiān)聽(tīng)器和過(guò)濾器歌豺,先走監(jiān)聽(tīng)器再走過(guò)濾器.

在線人數(shù)統(tǒng)計(jì)

    package com.neuedu.utils;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    /**
     * Application Lifecycle Listener implementation class MyFilter
     *
     */
    @WebListener
    public class MyListener implements ServletContextListener {
    
        /**
         * Default constructor. 
         */
        public MyListener() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see ServletContextListener#contextDestroyed(ServletContextEvent)
         */
        public void contextDestroyed(ServletContextEvent arg0)  { 
            System.out.println("上下文銷(xiāo)毀");
        }
    
        /**
         * @see ServletContextListener#contextInitialized(ServletContextEvent)
         * ServletContext---application
         */
        public void contextInitialized(ServletContextEvent applicationEvent)  { 
            ServletContext application=applicationEvent.getServletContext();
            //在線人數(shù)推穷,初始化為0
            application.setAttribute("onlinenumber", 0);
             System.out.println("上下文創(chuàng)建");
        }
        
    }


    package com.neuedu.utils;
    
    import javax.servlet.ServletContext;
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     * Application Lifecycle Listener implementation class MySessionListenter
     *
     */
    @WebListener
    public class MySessionListenter implements HttpSessionListener {
    
        /**
         * Default constructor. 
         */
        public MySessionListenter() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
         */
        public void sessionCreated(HttpSessionEvent sessionEvent)  { 
             System.out.println("sessionCreated建立");
             //從session/request里都可以得到ServletContext--->sessionEvent.getSession可以獲取
             HttpSession session=sessionEvent.getSession();
             ServletContext application= session.getServletContext();
             int old_online=(Integer)application.getAttribute("onlinenumber");
             //如果有用戶訪問(wèn),我們就把計(jì)數(shù)器加1
             int new_online=old_online+1;
             application.setAttribute("onlinenumber", new_online);
             System.out.println("新的在線人數(shù)"+new_online);
        }
    
        /**
         * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
         */
        public void sessionDestroyed(HttpSessionEvent sessionEvent)  { 
             System.out.println("sessionDestroyed");
             //從session/request里都可以得到ServletContext--->sessionEvent.getSession可以獲取
             HttpSession session=sessionEvent.getSession();
             ServletContext application= session.getServletContext();
             int old_online=(Integer)application.getAttribute("onlinenumber");
             //如果有用戶訪問(wèn)类咧,我們就把計(jì)數(shù)器加1
             int new_online=old_online-1;
             application.setAttribute("onlinenumber", new_online);
             System.out.println("新的在線人數(shù)"+new_online);
            //如果有用戶退出或超時(shí)馒铃,我們就把計(jì)數(shù)器-1
        }
        
    }

前臺(tái)頁(yè)面

    在線人數(shù):${onlinenumber}

如果登錄成功才認(rèn)為是在線

@Override
public void attributeAdded(HttpSessionBindingEvent sessionEvent) {
    // TODO Auto-generated method stub
    User user=(User)sessionEvent.getSession().getAttribute("loginUser");
    HttpSession session=sessionEvent.getSession();
    ServletContext application= session.getServletContext();
    int old_online=(Integer)application.getAttribute("onlinenumber");
    //如果有用戶訪問(wèn),我們就把計(jì)數(shù)器加1
    if(user!=null){
    int new_online=old_online+1;
    application.setAttribute("onlinenumber", new_online);
    System.out.println("新的在線人數(shù)"+new_online);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痕惋,一起剝皮案震驚了整個(gè)濱河市区宇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌值戳,老刑警劉巖议谷,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異述寡,居然都是意外死亡柿隙,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)鲫凶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)禀崖,“玉大人,你說(shuō)我怎么就攤上這事螟炫〔ǜ剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵昼钻,是天一觀的道長(zhǎng)掸屡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)然评,這世上最難降的妖魔是什么仅财? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮碗淌,結(jié)果婚禮上盏求,老公的妹妹穿的比我還像新娘抖锥。我一直安慰自己,他們只是感情好碎罚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布磅废。 她就那樣靜靜地躺著,像睡著了一般荆烈。 火紅的嫁衣襯著肌膚如雪拯勉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天憔购,我揣著相機(jī)與錄音宫峦,去河邊找鬼。 笑死倦始,一個(gè)胖子當(dāng)著我的面吹牛斗遏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鞋邑,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼账蓉!你這毒婦竟也來(lái)了枚碗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铸本,失蹤者是張志新(化名)和其女友劉穎肮雨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體箱玷,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怨规,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锡足。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片波丰。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舶得,靈堂內(nèi)的尸體忽然破棺而出掰烟,到底是詐尸還是另有隱情,我是刑警寧澤沐批,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布纫骑,位于F島的核電站,受9級(jí)特大地震影響九孩,放射性物質(zhì)發(fā)生泄漏先馆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一躺彬、第九天 我趴在偏房一處隱蔽的房頂上張望煤墙。 院中可真熱鬧缤底,春花似錦、人聲如沸番捂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)设预。三九已至徙歼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鳖枕,已是汗流浹背魄梯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宾符,地道東北人酿秸。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像魏烫,于是被迫代替她去往敵國(guó)和親辣苏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容