filter&listener

filter&listener

今日内容:
	Filter(过滤器) [今天]
    Listener(监听器)  [明天]   
Web阶段的三大组件:
	Servlet[最最最重要的]
    Filter<偶尔可能用到的>
    Listener(基本很少用到的)    

第1章 过滤器简介

1.1 为什么要使用过滤器
当用户想要访问某些资源时,我们需要他//它满足一定的条件,此时我们就可以给这些资源创建一个过滤器,
满足条件的用户可以访问,反之不能访问
1.2 什么是过滤器
在Java只要实现Filter接口的类,我们就称为过滤器

第2章 过滤器的应用场景

2.1 过滤论坛中用户发表内容中的非法字符
2.2 登录权限检查

第3章 过滤器开发步骤

3.1 Filter的API介绍
a.定义一个实现类,实现Filter接口
b.重写doFilter方法,该方法就表示执行过滤的方法
c.如果请求满足要求,那么放行(访问目标资源)!!  
    如果请求不满足要求,那么拦截	    
3.2 使用步骤
1. 编写一个Servlet,路径为/test,并在web.xml配置或者注解配置
2. 给目标资源添加一个过滤器    
    a.定义一个实现类,实现Filter接口
    b.重写doFilter方法,该方法就表示执行过滤的方法
    c.如果请求满足要求,那么放行(访问目标资源)!!  
        如果请求不满足要求,那么拦截	
3.配置过滤器   
    web.xml配置:
	 	<!--配置Filter-->
        <filter>
            <filter-name>TestFilter</filter-name>
            <filter-class>com.itheima.web.filter.TestFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>TestFilter</filter-name>
            <url-pattern>/test</url-pattern>
        </filter-mapping>	
    注解配置:
		@WebFilter(filterName = "TestFilter",urlPatterns = "/目标资源的路径")
4.过滤器拦截到目标资源之后执行doFilter方法,默认不放行!!
    	如果需要放行,那么调用:
		filterChain.doFilter(servletRequest,servletResponse);
3.3 注意事项
过滤器的doFilter默认拦截(不放行),想要放行,调用filterChain.doFilter(servletRequest,servletResponse)
3.4 XML方式代码演示
<!--配置Servlet-->
   <servlet>
    	<servlet-name>TestServlet</servlet-name>
    	<servlet-class>com.itheima.web.servlet.TestServlet</servlet-class>
   </servlet>
   <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/test</url-pattern>
   </servlet-mapping>
   <!--配置Filter-->
   <filter>
        <filter-name>TestFilter</filter-name>
        <filter-class>com.itheima.web.filter.TestFilter</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>TestFilter</filter-name>
      <url-pattern>/test</url-pattern>
   </filter-mapping>
3.5 注解方式代码演示
/**
 * 目标资源
 */
@WebServlet(name = "MyServlet",urlPatterns = "/my")
public class MyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //1.输出
        System.out.println("目标资源到达了...");
    }
}
/**
 * 目标资源过滤器
 */
@WebFilter(filterName = "MyFilter",urlPatterns = "/my")
public class MyFilter implements Filter {
    //过滤方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器执行了...");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

第4章 过滤器的执行流程

4.1 生活案例类比过滤器流程
比如:坐飞机/火车的安全检查
4.2 图解过滤器的执行流程(图)
注意: 当过滤器放行后,执行目标资源,当前目标资源执行后,
		又会回到过滤器接着执行过滤器的以后的内容,最后才响应给浏览器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vRyClsyy-1591273811676)(img/image-20200210151351829.png)]

第5章 过滤器的生命周期

5.1 init方法
init方法称为初始化方法,当过滤器创建后调用(服务器启动时创建)    
5.2 doFilter方法
doFilter方法称为过滤方法,当访问目标资源时调用(访问一次,调用一次)
5.3 destory方法
destory方法称为销毁方法,当过滤器被销毁时调用(正常关闭服务器或者从服务器中卸载该项目)
5.4 过滤器生命周期总结(了解)
当项目随着服务器启动后,调用过滤器的init
当用户访问的路径是过滤器过滤的路径时,调用过滤器的doFilter
当正常关闭服务器或者从服务器中卸载该项目时,调用过滤器的destory    

第6章 过滤器映射路径

6.1 精确匹配模式
urlPatterns = "/具体的资源路径"
6.2 模糊匹配模式
  • 整个应用的配置(全站过滤)

    urlPatterns = "/*" 无论访问当前项目下何种资源,该过滤器都可以拦截
    
  • 指定目录下的路径配置

    urlPatterns = "/aa/*" 只要访问当前项目下"/aa/"下的任何资源,该过滤器都可以拦截
    
  • 指定后缀名的路径配置

    urlPatterns = "*.jsp"   只要访问当前项目下任何以jsp结尾的资源,该过滤器都可以拦截     
    

第7章 拦截方式

我们可以规定,过滤器拦截目标资源的拦截方式是request或者是forward
7.1 request
拦截方式request,表示直接从浏览器访问的请求(包括重定向),这是默认的拦截方式!!
7.2 forward
拦截方式forward,表示从其他Servlet转发过来的请求
注意:
如果想规定请求的方式是POST还是GET,我们后期可以借助SpringMVC框架来处理
/**
 * 目标资源
 */
@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //1.输出
        System.out.println("目标资源执行了...");
    }
}

//@WebFilter(filterName = "TestFilter",urlPatterns = "/test") 默认拦截类型是request,浏览器直接访问
@WebFilter(filterName = "TestFilter",urlPatterns = "/test",dispatcherTypes = DispatcherType.FORWARD) //拦截类型是forward,浏览器转发访问
public class TestFilter 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("过滤器执行了...");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

/**
 * 转发到test的servlet
 */
@WebServlet(name = "ForwardToTestServlet",urlPatterns = "/to")
public class ForwardToTestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //1.把请求转发到test
        request.getRequestDispatcher("/test").forward(request, response);
    }
}
7.3 两种拦截方式能否共存
可以,在配置或注解时,写上两种拦截方式即可
    XML:
		<filter> 
            <filter-name>MethodFilter</filter-name> 
            <filter-class>com.itheima.myfilter.MethodFilter</filter-class> 
		</filter>
		<filter-mapping> 
            <filter-name>MethodFilter</filter-name> 
            <url-pattern>/index.jsp</url-pattern> 
            <dispatcher>FORWARD</dispatcher> 
            <dispatcher>REQUEST</dispatcher> 
		</filter-mapping>
    注解:
	@WebFilter(dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}) 
总结
1. 能够说出过滤器的作用
    过滤器是对目标资源访问的请求进行拦截的,如何条件放行,返回不放行
    ========================
    a.创建目标资源(servlet,html,jsp,图片,txt)
    b.创建Filter的实现类,重写doFilter方法
    		默认是不放行
    		如果需要放行:调用filterChain的dofilter(request,response)
    c.配置Filter实现类的拦截路径
             xml配置: 
				<filter>
                <filter-mappging>    
             注解配置:   
				@WebFilter(filterName="..",urlPatterns="/拦截资源的路径")
	=========================
2. 能够说出过滤器生命周期相关方法
    	init 服务器启动执行
    	doFilter 每次访问目标资源执行
    	destory 正常关闭服务器或者卸载项目执行
    
3.过滤器的路径匹配写法
    a.精确匹配 /test
    b.目录匹配 /目录名/*
    c.扩展名匹配 *.jsp *.html
    d.全站匹配 /* (Servlet也有缺省匹配,"/")
4.拦截方式
	dispatcherType.request(默认的): 只拦截浏览器直接请求(重定向)
	dispatcherType.forward(可配置): 只拦截其他资源转发过来的请求(请求转发)

第8章 过滤器链

8.1 什么是过滤器链
访问目标资源时,需要经过多个过滤器,只有这些过滤器都放行了,请求才能到达目标资源
    这里的多个过滤器,我们称为过滤器链
比如:	做飞机去北京(身份证,登机牌,体温,体温,到达你北京的"家")     
8.2 过滤器链中多个过滤器的执行顺序
8.3 XML配置代码演示
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">
    <!--Servlet类-->
    <servlet>
        <servlet-name>ObjectServlet</servlet-name>
        <servlet-class>com.itheima.web.servlet.ObjectServlet</servlet-class>
    </servlet>
    <!--Servlet路径-->
    <servlet-mapping>
        <servlet-name>ObjectServlet</servlet-name>
        <url-pattern>/obj</url-pattern>
    </servlet-mapping>

    <!--配置BFilter-->
    <filter>
        <filter-name>BFilter</filter-name>
        <filter-class>com.itheima.web.filter.BFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>BFilter</filter-name>
        <url-pattern>/obj</url-pattern>
    </filter-mapping>

    <!--配置AFilter-->
    <filter>
        <filter-name>AFilter</filter-name>
        <filter-class>com.itheima.web.filter.AFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>AFilter</filter-name>
        <url-pattern>/obj</url-pattern>
    </filter-mapping>
</web-app>

如果是XML配置的过滤器,那么在前的过滤器先执行,在后的过滤器后执行
	只有当前所有的过滤器链都放行的情况下请求才能达到目标资源
	如果有一个过滤器不放行,那么请求到此就结束了
8.4 注解配置代码演示
/**
 * 目标Servlet
 */
@WebServlet(name = "ObjectServlet",urlPatterns = "/obj")
public class ObjectServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //1.输出
        System.out.println("请求达到目标资源...");
    }
}

@WebFilter(filterName = "AFilter",urlPatterns = "/obj")
public class AFilter 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("A过滤器执行了..");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

@WebFilter(filterName = "BFilter",urlPatterns = "/obj")
public class BFilter 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("B过滤器执行了..");
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {

    }
}

如果是注解配置的过滤器,那么过滤器执行的先后顺序和配置的过滤器名有关(ASCII码值小的过滤器先执行..)
	只有当前所有的过滤器链都放行的情况下请求才能达到目标资源
	如果有一个过滤器不放行,那么请求到此就结束了
      
所以在后期开发中,我们建议使用xml配置过滤器,xml便于控制过滤器链的执行顺序!!!    
8.5 过滤器链的执行流程(图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evkj2AVB-1591273811679)(img/image-20200211094653405.png)]

第9章 案例:非法字符

9.1 案例需求
创建一个发表言论的表单页面,点击发表时,通过过滤器检查是否有非法字符串,如果有不让发表,如果没有正常发表言论
9.2 案例分析
我们发表言论之前需要经过一个过滤器
    a.如果有非法词语 那么不放行
    b.如果没有非法词语 那么放行
9.3 实现步骤
a.创建BBS.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head><title>BBS论坛</title></head>
        <body>
            <form method="post" action="${pageContext.request.contextPath}/bbs">
                请发表你的言论:
                <input type="text" name="message">
                <input type="submit" value="提交">
            </form>
        </body>
    </html>
    注意:我们使用${pageContext.request.contextPath},获取项目的根路径 "/项目名" 更加灵活
 b.发表言论Servlet
    /**
     * 发表言论的Servlet
     */
    @WebServlet(name = "BBSServlet",urlPatterns = "/bbs")
    public class BBSServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request,response);
        }

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //0.设置响应体和请求体的编码
            response.setContentType("text/html;charset=UTF-8");
            request.setCharacterEncoding("UTF-8");
            //1.获取请求中发表的言论数据
            String message = request.getParameter("message");
            //2.输出到页面
            response.getWriter().println("您的言论:"+message+",发表成功");
        }
    } 

c.发表言论的非法词语过滤器
/**
 * BBS论坛发表言论的过滤器
 */
@WebFilter(filterName = "BBSFilter",urlPatterns = "/bbs")
public class BBSFilter implements Filter{
    public ArrayList<String> words = new ArrayList<String>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        try {
            //3.读取words.txt中敏感词
            String realPath = filterConfig.getServletContext().getRealPath("/words.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(realPath), "UTF-8"));
            //标准循环
            String line = "";
            while ((line = br.readLine()) != null) {
                words.add(line);
            }
            br.close();
            System.out.println(words);
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //要对用户发表的言论进行过滤
        //0.将父类ServletRequest,ServletResponse转成子类HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        //1.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //2.通过request获取数据
        String message = request.getParameter("message");
        System.out.println(message);
        //4.判断message中是否含有非法言论
        for (String word : words) {
            //判断message中是否含有非法言论
            if (message.contains(word)) {
                //言论不合法
                response.getWriter().println("您的言论不合法!");
                return;
            }
        }
        //5.放行
        filterChain.doFilter(request, response);
    }
}
注意: 我们过滤器每访问一次就会执行一次doFilter方法,所以我们把读取words.txt的代码放到init方法中
    	这样就不会每次都去重写读取,而是在过滤器创建的时候读取一次就够了,提高代码的性能!!

        
9.4 案例加强—使用装饰者模式完成非法字符过滤(了解)
装饰设计模式: 也叫包装设计模式
    可以在不改变原有类的基础上,对类的某个方法进行增加
装饰设计模式一般的步骤:
	a.继承原有类
    b.构造方法时,传入原有类的引用
    c.需要增强的方法我们进行重写,不需要增强的方法不需要重写(使用原来的方法即可)
案例1:
	比如:对BufferedReader进行增强,读取一行时,不仅仅可以读取内容,还要加上行号
	//包装BufferedReader的readline方法,能输出行号
    public class LineNumberBufferedReader extends BufferedReader {
        //子类可以继承父类的方法
        private int num = 1;

        public LineNumberBufferedReader(Reader reader) {
            super(reader);
        }

        //要增强谁,覆盖谁
        public String readLine() throws IOException {
            String data = super.readLine();
            if (data == null) return null;
            return (num++) + ":" + data;
        }

        public static void main(String[] args) {
            //读LineNumberReader源码
            try {
                InputStream in = new FileInputStream("E:\\heima126\\day26_IlleageWords\\web\\words.txt");
                Reader reader = new InputStreamReader(in, "UTF-8");//字符流
                BufferedReader bufferedReader = new BufferedReader(reader);
                //读一行
                LineNumberBufferedReader lineNumberReader = new LineNumberBufferedReader(bufferedReader);
                //带行号
                String data = null;
                while ((data = lineNumberReader.readLine()) != null) {
                    System.out.println(data);
                }
                lineNumberReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }      
        
案例2:对HttpServletRequest的getParameter方法进行增强,通过getParameter获取数据时,如果数据中
    有敏感词,把对应的敏感词变为**//对普通的HttpServletRequest类的装饰类    
public class DirtyWordsHttpServletRequest extends HttpServletRequestWrapper {
    private List<String> dicts;

    public DirtyWordsHttpServletRequest(HttpServletRequest request, List<String> dicts) {
        super(request);
        this.dicts = dicts;
    }
    //重点:重写getParameter方法,获取数据时,如果有敏感词在方法中替换成*号
    public String getParameter(String name) {
        String param = super.getParameter(name);
        if (param == null)
            return null; //有值:替换脏词
        if (dicts != null && dicts.size() > 0) {
            for (String word : dicts) {
                if (param.contains(word)) {
                    StringBuffer sb = new StringBuffer();//StringBuilder
                    for (int i = 0; i < word.length(); i++) {
                        //word有几个字符,就搞几个*
                        sb.append("*");
                    }
                    param = param.replace(word, sb.toString());
                }
            }
        }
        //最后返回的内容,所有的敏感词都已经替换成*号了
        return param;
    }
}	

/**
 * BBS论坛发表言论的过滤器
 */
@WebFilter(filterName = "BBSFilter",urlPatterns = "/bbs")
public class BBSFilter implements Filter{
    public ArrayList<String> words = new ArrayList<String>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        try {
            //3.读取words.txt中敏感词
            String realPath = filterConfig.getServletContext().getRealPath("/words.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(realPath), "UTF-8"));
            //标准循环
            String line = "";
            while ((line = br.readLine()) != null) {
                words.add(line);
            }
            br.close();
            System.out.println(words);
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //要对用户发表的言论进行过滤
        //0.将父类ServletRequest,ServletResponse转成子类HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        //1.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //2.通过request获取数据
        String message = request.getParameter("message");
        System.out.println(message);
        //4.由于我们已经对HttpServletRequest进行了增强
        DirtyWordsHttpServletRequest newRequest = new DirtyWordsHttpServletRequest(request,words);
        //5.放行,使用newRequest代替原来的request,那么目标资源拿到的就是newRequest
        filterChain.doFilter(newRequest, response);
    }

    @Override
    public void destroy() {

    }
}

/**
 * 发表言论的Servlet
 */
@WebServlet(name = "BBSServlet",urlPatterns = "/bbs")
public class BBSServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置响应体和请求体的编码
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        //1.获取请求中发表的言论数据
        String message = request.getParameter("message");
        //2.输出到页面
        response.getWriter().println("您的言论:"+message+",发表成功");
    }
}

第10章 综合案例:解决全站乱码

10.1 案例需求
使用一个全站过滤器,统一处理请求体和响应体中的中文乱码
    以后我们写的所有Servlet都不需要关系中文乱码了!!!
10.2 实现步骤
a.创建一个过滤器
b.配置过滤器的拦截路径("/*")
c.在过滤器的doFilter方法中,处理请求体和响应体的乱码!
d.放行到目标资源    
10.3 代码实现
/**
 * 全站中文乱码的过滤器
 */
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    //过滤的方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //1.将servletRequest和servletResponse转回HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //要求请求体和响应体的中文乱码进行处理
        //a.响应体我们所有都需要处理中文乱码
        response.setContentType("text/html;charset=UTF-8");
        //b.如果是post请求,设置请求体的中文乱码
        if (request.getMethod().equalsIgnoreCase("POST")) {
            request.setCharacterEncoding("UTF-8");
        }
        //放行
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}
注意: 该乱码过滤器,我们可以保存下来,以后直接拿过来使用,但是我们建议改成web.xml配置
    	并且把该过滤器配置到所有过滤器的前面,保证先执行该过滤器,解决中文乱码!!!

第11章 监听器入门(了解)

11.1 什么是监听器
在Java中监听器主要监听某些事件
    a.各种域对象的创建和销毁事件(ServletContext,HttpSession,HttpServletRequest)
    b.各种域对象的属性增加和减少事件(ServletContext,HttpSession,HttpServletRequest)    
11.2 监听器的使用场景
a.获取项目启动之后的初始化信息(Spring框架会使用)
b.统计在线人数(监听HttpSession对象的创建和销毁)    
11.3 开发一个监听器(以ServletContextListenner为例)
  • API介绍

    ServletContextListenner是一个接口,其中有两个方法
        	void contextDestroyed(ServletContextEvent sce); 监听ServletContext销毁事件
        	void contextInitialized(ServletContextEvent sce); 监听ServletContext创建事件
    
  • 使用步骤

    1.创建一个类实现ServletContextListenner接口
    2.实现类重写接口中两个方法contextDestroyed和contextInitialized
        /**
         * ServletContext的监听器
         */
        public class MyServletContextListener implements ServletContextListener{
    
            @Override
            public void contextInitialized(ServletContextEvent servletContextEvent) {
                System.out.println("ServletContext创建了");
            }
    
            @Override
            public void contextDestroyed(ServletContextEvent servletContextEvent) {
                System.out.println("ServletContext销毁了");
            }
        }
    
    3.使用web.xml配置 或者 注解配置    
    
  • XML方式演示

    <!--配置监听器-->
    <listener>
        <listener-class>com.itheima.web.listener.MyServletContextListener</listener-class>
    </listener>
    
  • 注解方式演示

    /**
     * ServletContext的监听器
     */
    @WebListener //监听器的注解,只需要一个@WebListener,不需要任何的属性
    public class MyServletContextListener implements ServletContextListener{
    
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext创建了");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext销毁了");
        }
    }
    

    其他域对象也有类似的监听器

    HttpSessionListener 监听Httpsession域的创建于销毁的监听器
    ServletRequestListener 监听ServletRequest域的创建于销毁的监听器    
    
11.4 域对象的生命周期回顾
ServletContext域对象
    创建: 项目启动时创建
    销毁: 项目卸载时或者服务器正常关闭时
HttpSession域对象
    创建: 在本次会话中第一次调用getSession方法时,第一次访问该jsp页面时创建
	销毁: 关闭浏览器默认30分钟后销毁
HttpServletRequest域对象
	创建: 每次请求都会创建
	销毁: 成功响应浏览器了,就销毁
11.5 ServletContextAttributeListener监听器使用
  • ServletContextAttributeListener的作用

    监听ServletContext域对象中属性的变化(新增,删除,修改)
    
  • ServletContextAttributeListener的API

    ServletContextAttributeListener是一个接口,其中有三个方法:
    	void attributeAdded(ServletContextAttributeEvent scab);
    								监听属性添加到servletcontext中 
        void attributeRemoved(ServletContextAttributeEvent scab);
    								监听属性从servletcontext中移除 
        void attributeReplaced(ServletContextAttributeEvent scab);
    								监听属性从 servletcontext中被替换
    
  • ServletContextAttributeListener的使用步骤

    a.创建ServletContextAttributeListener接口的实现类
    b.重写接口中三个监听方法
    c.在web.xml中配置或者注解配置    
    
  • ServletContextAttributeListener的代码实现

    /**
     * ServletContext属性监听器
     */
    public class MyServletContextAttributeListener implements ServletContextAttributeListener {
        @Override
        public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
            String name = servletContextAttributeEvent.getName();
            Object value = servletContextAttributeEvent.getValue();
            System.out.println("向ServletContext域对象中添加数据了..." + name + "..." + value);
        }
    
        @Override
        public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
            String name = servletContextAttributeEvent.getName();
            Object value = servletContextAttributeEvent.getValue();
            System.out.println("从ServletContext域对象中删除数据了..." + name + "..." + value);
        }
    
        @Override
        public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
            String name = servletContextAttributeEvent.getName();
            Object value = servletContextAttributeEvent.getValue();
            System.out.println("对ServletContext域对象中数据进行修改了..." + name + "..." + value);
        }
    }
    配置:
    <listener>
    	<listener-class>
            com.itheima.web.listener.MyServletContextAttributeListener
        </listener-class>
    </listener>	
    
  • 其他监听器有兴趣可以自行研究

    HttpSessionAttributeListener 监听HttpSession中属性的增删改事件
    ServletRequestAttributeListener 监听Request中属性的增删改事件    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值