过滤器和监听器

本文深入探讨Java Web中的过滤器与监听器概念,包括Filter的作用与编写方法,FilterChain的工作流程,以及多种过滤场景如权限控制、字符编码处理和页面静态化。同时,文章还介绍了监听器的基本原理及其在不同域对象生命周期与属性变更中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

过滤器Filter

1.作用

​ 它会在一组资源(jsp、servlet、css、html)的前面执行,作用域是一组资源。它可以让请求的到目标资源,也可以不让请求达到!(拦截请求的能力) Filter是单例的

2.编写过滤器

2.1步骤

AServlet.java

1588824612828.

AFilter.java

import javax.servlet.*;
public class AFilter implements Filter{
    //这三个方法也是Filter的生命周期
    //服务器启动后创建Filter,创建Filter之后马上执行,用来做初始化
    public void init(FilterConfig filterConfig)throws ServletException{
        System.out.println("过滤器出生了")}
    //每次过滤时都会执行 
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
        System.out.println("拦截器")** chain.doFilter(request,response);//放行
           **System.out.println("返回这个方法")}
    //销毁之前执行,在服务器关闭之前销毁,用来做非内存资源进行释放
    public void destory(){
        System.out.println("过滤器要死了")}
}

web.xml

<filter>
    <filter-name>AFilter</filter-name>
    <filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AFilter</filter-name>
    <url-pattern>/*</url-pattern>    //确定过滤的范围
</filter-mapping>

第一次执行的结果:
1588824509392

拦截你(分析:没有打印出AServlet…,被拦截了)

二次执行的结果:

拦截你

拦截你

加上**后的语句后会方行,执行结果:

拦截你

AServlet…

返回这个方法

2.2FilterConfig

  • ServletContext getServletContext(): 获取Servlet的方法
  • String getFilterName() :获取Filter的配置名称;与元素对应
  • String getInitParameter(String name):获取Filter的初始化配置,与元素对应
  • Enumeration getInitParameterName():获取所有初始化参数的名称

1588825363119

1588837301377
1588837334064

2.3FilterChain

1588837455586

2.4多个过滤器的执行顺序

AServlet.java

import java.io.IOException;
public class AServlet extends HttpServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response)
               throws ServletException,IOException{
       System.out.println("AServlet...");        
    }
}

AFilter.java

import javax.servlet.*;
public class AFilter implements Filter{
    //这三个方法也是Filter的生命周期
    //服务器启动后创建Filter,创建Filter之后马上执行,用来做初始化
    public void init(FilterConfig filterConfig)throws ServletException{
        
    }
    //每次过滤时都会执行 
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
        System.out.println("AFilter#satar")** chain.doFilter(request,response);//放行
           **System.out.println("AFilter#end")}
    //销毁之前执行,在服务器关闭之前销毁,用来做非内存资源进行释放
    public void destory(){
       
    }
}

BFilter.java

import javax.servlet.*;
public class AFilter implements Filter{
    //这三个方法也是Filter的生命周期
    //服务器启动后创建Filter,创建Filter之后马上执行,用来做初始化
    public void init(FilterConfig filterConfig)throws ServletException{
    
    }
    //每次过滤时都会执行 
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
        System.out.println("BFilter#satrt");
           ** chain.doFilter(request,response);//放行
           **System.out.println("BFilter#end");
    }
    //销毁之前执行,在服务器关闭之前销毁,用来做非内存资源进行释放
    public void destory(){
       
    }
}

web.xml

<filter>
    <filter-name>AFilter</filter-name>
    <filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AFilter</filter-name>
    <url-pattern>/*</url-pattern>    //确定过滤的范围
</filter-mapping>
<filter>
    <filter-name>BFilter</filter-name>
    <filter-class>cn.itcast.web.filter.BFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>BFilter</filter-name>
    <url-pattern>/AServlet</url-pattern>    //确定过滤的范围
</filter-mapping>

访问index.jsp(执行AFilter)

执行结果:

AFilter#start

我是index.jsp

AFilter#end

访问AServlet

执行结果:

AFilter#start //放行了

BFilter#start //方行了

AServlet

BFilter#end

AFilter#end


说明了
1588838305348

2.5四种拦截方式

1.拦截直接请求REQUEST

2.拦截转发FORWARD

3.拦截包含INCLUDE

4.拦截错误ERROR


配置方式:在中进行配置

web.xml

<filter>
    <filter-name>AFilter</filter-name>
    <filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AFilter</filter-name>
    <url-pattern>/*</url-pattern>    //确定过滤的范围为所有,拦截的是请求
</filter-mapping>
<filter>
    <filter-name>BFilter</filter-name>
    <filter-class>cn.itcast.web.filter.BFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>BFilter</filter-name>
    <url-pattern>/AServlet</url-pattern>    //确定过滤的范围
 //   <dispatcher>REQUEST</dispatcher>      //如果什么都没写拦截的是request
    <dispatcher>FORWARD</dispatcher>      //如果只写了forward就只拦截转发
   // <dispatcher>INCLUDE</dispatcher>
   // <dispatcher>ERROR</dispatcher>
</filter-mapping>

AServlet.java

import java.io.IOException;
public class AServlet extends HttpServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response)
               throws ServletException,IOException{
       System.out.println("AServlet...");        
    }
}

BServlet.java //转发

import java.io.IOException;
public class BServlet extends HttpServlet{
    public void doGet(HttpServletRequest,HttpServletResponse response)
               throws ServletException,IOException{
        request.getRequestDispatcher("/AServlet").forward(request,response);
    }
}

执行结果:
1588926142319

请求BServlet时会执行AFilter,然后转发时执行BFilter

改动:

1588926252300

此时不会执行AFilter,因为他只执行请求不处理转发


拦截错误:

1588926460710

2.6控制多个过滤器的执行顺序

在中配置的顺序决定过滤器对的顺序

AFilter

public class AFilter implements Filter{
    public void init(FilterConfig filterConfig)throws ServletException{
        
    }
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
        System.out.println("AFilter...");
    
    }
    public void destory(){
       
    }
}

BFilter

import javax.servlet.*;
public class AFilter implements Filter{
   
    public void init(FilterConfig filterConfig)throws ServletException{
        
    }
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
        System.out.println("BFilter...");
 
    }
    public void destory(){
       
    }
}

web.xml 先AFilter后BFilter这取决于mapping中的Filter的顺序

<filter>
    <filter-name>AFilter</filter-name>
    <filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AFilter</filter-name>
    <url-pattern>/*</url-pattern>    //确定过滤的范围为所有,拦截的是请求
</filter-mapping>
<filter>
    <filter-name>BFilter</filter-name>
    <filter-class>cn.itcast.web.filter.BFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>BFilter</filter-name>
    <url-pattern>/AServlet</url-pattern>    //确定过滤的范围
</filter-mapping>

2.7过滤器的应用场景

1588927024751

作用:1.几乎所有的Servlet中都要写request.setCharacterEncoding(),可以把他放到一个Filter中,这种过滤器没有拦截的功能。称为预处理工作。

2.8设置目标资源

1588927418922

1588927445690

3.案例

3.1分ip统计网站访问次数

3.1.1

统计工作需要在所有资源之前执行,那么就可以方法哦Filter中 了

我们这个过滤器不打算做拦截操作,因为我们只是用来做统计

用什么东西来装载统计的数据 1个Map<String,Integer>

Map需要在Filter中用来保存数据

Map需要在页面使用,打印Map中的数据

Map保存在ServletContext中

使用ServletContextListener ,Map在服务器开启的时候完成创建。

3.1.2分析

​ 因为一个网站可能有多个页面,无论哪个页面被访问

3.1.3代码

day/WebRoot/a.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>去</h1>
    </body>
</html>

day/WebRoot/b.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>吧</h1>
    </body>
</html>

1589286769464

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
从applicat中获取Map
    从request中得到当前客户端的IP
    进行统计工作,结果保存到Map中
public class AFilter implements Filter{
    private FilterConfig config;
    //在服务器启动时就会执行本方法,只执行一次
    public void init(FilterConfig filterConfig)throws ServletException{
        this.config=fconfig
    }
    @Overrride
    public void doFilter(ServletRequest request,ServletResponse response,
                         FilterChain chain)throws IOException,ServletException{
       //1.得到application中的map
        //2.从request中获取当前客户端的ip地址
        //3.查看map中是否存在这个ip对应访问次数,如果存在,则加1
        //4.如果不存在这个ip,那么说明是第一次访问本站,设置访问次数为1
        ServletContext app=config.getServletContext(); 
        Map<String,Integer>map=app.getAttribute("map");
        //获取客户端的ip地址
        String ip=request.getRemoteAddr();
        //判断
        if(map.containsKey(ip)){
            int cnt=map.get(ip);
            map.put(ip,cnt+1);
        }else{
            map.put(ip,1);
        }
        app.setAttribute("map",map);//把map放回到app中
        chain.doFilter(request,response);// 肯定放行
    
    }
    public void destory(){
       
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传1589329134072

import java.util.Map;
public class Alisterner implements ServletContextListerner{
    //在服务器启动时创建Map,保存到ServletContext
    public void contextInitialized(ServletContextEvent sce){
        //创建Map
        Map<String,Integer>map=new LinkedHashMap<String,Integer>();
        //得到ServletContext
        ServletContext application=sce.getServletContext();
        //把map保存到application中
        application.setAttribute("map",map);
    }
    public void contextDestoryed(ServletContextEvent sce){
        
    }
}

show.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1 aligin="center">显示结果</h1>
        <table align="center" width="60%" border="1">
            <tr>
                <th>IP</th>
                <th>次数</th>
            </tr>
        <c:foreach items="${applicationScope.map}" var="entry">
            <tr>
                <td>${entery.key}</td>
                <td>${entery.value}</td>
            </tr>
        </c:foreach>
        </table>
    </body>
</html>

3.2粗粒度权限控制

1588927297697

index.jsp谁都可以访问

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <h1>欢迎欢迎,游客先生</h1>  
      <a href="c:url value='/index.jsp'/">游客入口</a><br/>
      <a href="c:url value='/users/u.jsp'/">会员入口</a><br/>
      <a href="c:url value='/damin/a.jsp'/">管理员入口</a><br/>
    </body>
</html>

day/users/u.jsp用户访问

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <h1>欢迎欢迎,管理员先生</h1> 
      <a href="c:url value='/index.jsp'/">游客入口</a><br/>
      <a href="c:url value='/users/u.jsp'/">会员入口</a><br/>
      <a href="c:url value='/damin/a.jsp'/">管理员入口</a><br/>
    </body>
</html>

day/admin/a.jsp管理员访问

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <h1>会员先生,早上好</h1> 
      <a href="c:url value='/index.jsp'/">游客入口</a><br/>
      <a href="c:url value='/users/u.jsp'/">会员入口</a><br/>
      <a href="c:url value='/damin/a.jsp'/">管理员入口</a><br/>
    </body>
</html>

day/WebRoot/login.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <h1>登录</h1> 
      ${msg}
      <form action="<c:uel value='LoginServlet.java'/>" method="post">
          用户名:<input type="text" name="username"/>
          <input type="submit" value="登录"/>
        </form>
    </body>
</html>

day/src/LoginServlet.java

package cn.itcast.web.servlet;
import java.io.IOException;
public calss LoginServlet extends HttpServlet{
    public void doPost(HttpServletRequest request,HttpServletResponse response)
              throws ServletException,IOException{
        //1.获取用户名
        //2.判断用户名中是否包含itcast
        //3.包含是管理员,不包含是普通会员
        //4.要把登录的用户名保存到session中
        //5.转发到index.jsp
        String username=request.getParameter("username");
        if(username.contains("itcast")){
            request.getSession().setAttribute("admin",username);
        }else{
            request.getSession().setAtribute("username",username);
        }
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }
}    

day/src/UserFilter

过滤:/users/*

package cn.itcast.web.filter
import java.io.IOException
public class UserFilter implements Filter{
    public void destory(){
        
    }
    public void doFilter(ServletRequest request,ServletResponse response,
              FiterChain chain) throws IOException,ServletException{
        //1.得到session
        //2.判断session域中是否存在admin,如果存在,放行
        //3.判断session域中是否存在usernam,如果存在,方行,否则打会login.jsp
        HttpServletRequest req=(HttpServletRequest) request;
        String name=(String)req.getSession().getAttribute("admin");
        if(name!=null){
            chain.doFilter(request,response);
            return;
        }
        name=(String)req.getSession().getAttribute("username");
        if(name!=null){
            chain.doFilter(request,response);
        }else{
            req.setAttribute("msg","既不是管理员,也不是会员");
            req.getRequestDispatcher("/login.jsp").forward(request,response);    
        }
        
    }
    public void init(FilterConfig fConfig)throws ServletException{
        
    }
}    

day/src/AdminFilter

过滤:/admin/*

package cn.itcast.web.filter;
import java.io.IOException;
public class AdminFilter implements Filter{
    public void destory(){
        
    }
    public void doFilter(ServletRequest request,ServletResponse response,
              FiterChain chain) throws IOException,ServletException{
        //1.得到session
        //2.判断session域中是否存在admin,如果存在,放行
        //3.判断session域中是否存在usernam,如果存在,方行,否则打会login.jsp
        HttpServletRequest req=(HttpServletRequest) request;
        String name=(String)req.getSession().getAttribute("admin");
        if(name!=null){
            chain.doFilter(request,response);
        }else{
            req.setAttribute("msg","不是管理员");
            req.getRequestDispatcher("/login.jsp").forward(request,response);    
        }
        
    }
    public void init(FilterConfig fConfig)throws ServletException{
        
    }
}

1589758866692

3.3解决全站字符乱码问题

1589785690581

day/src/AServlet

package cn.itcast.web.servlet;
import java.io.IOException;
public class AServlet exteends HttpServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response)
             throws ServletException,IOException{
        response.setContentType("text/html;charset=utf-8");
        String username=request.getParameter("username");
        response.getWriter().println(username);
    }
    public void doPost(HttpServletRequest request,HttpServletResponse response)
            throws ServletException,IOException{
        response.setContentType("text/html;charset=utf-8");
        String username=request.getParameter("username");
        response.getWriter().println(username);
    }
}

day/index.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <a href="<c:url value='/AServlet?username=张三'/>">点击这里</a><br/>
      <form action="<c:uel value='/AServlet'/>" method="post">
          用户名:<input type="text" name="username" value="李四"/>
          <input type="submit" value="登录"/>
        </form>
    </body>
</html>

day/src/EncodingFilter

过滤范围:/*

package cn.itcast.web.filter;
import java.io.IOException;
public class EncodingFilter implements Filter{
    public void destory(){
        
    }
    public void doFilter(ServletRequest request,ServletResponse response,
                FilterChain chain)throws IOException,ServletException{
        //处理post请求编码问题
        request.setCharacterEncoding("utf-8");
        HttpServletRequest req=(HttpServletRequest) request;
        //处理get请求的编码问题
        //调包request
        //1.写一个request的装饰类
        //2.在放行时,使用我们自己的request
        if(req.getMethod().equals("GET")){
        EncodingRequest er=new EncodingRequest(req);
        chain.doFilter(er,response);  //er是调包后的request
        }else if(req.getMethod().equals("POST")){
            chain.doFilter(request,response);
        }
    }
    public void init(FilterConfig fConfig)throws ServletException{
        
    }
}

day/src/EncondingRequest

package cn.itcast.web.filter;
import java.io.*;
import java.util.*;
import java.security.Principal;
import javax.servlet.*;
public class EncodingRequest extends HttpServletRequestWrapper{
    private HttpServletRequest req;
    public EncodingRequest(HttpServletRequest request){
        super(request);   //完成一切拜托你
        this.req=request;
    }
    //以下是主要方法
    public String getParameter(String name){
        String value=request.getParameter(name);
        //处理编码问题
        try{
        value=new String(value.getBytes("iso-8859"),"utf-8");
        }catch(UnsupportedEncodingException e){
            throw new RuntimeException(e);
        }
            return value;
    }
}

3.4页面静态化

1.第一步:写一个小项目,图书管理

1.1页面:

*jsp:link.jsp

链接页面,四个超链接

|-查询所有

|-查看SE分类

|-查看EE分类

|-查看框架分类

*show.jsp

|-显示查询结果

1.2servlet:

BookServlet

*findAll()–>查看所有图书

*findByCategory–>按分类查询

1.3BookService:略

1.4BookDao:

*List findAll()

*List findByCateGory(int category)

1.5domain:

Book类

2.第二步:什么是页面静态化

首次访问去数据库获取数据,然后把数据保存到一个html页面中

二次访问就不去数据库获取,而是直接显示html

监听器Listener

介绍

在JavaWeb被监听的事件源为:三大域对象

六大监听器

1.ServletContext

1.1*生命周期监听:ServletContextListerner,它有两个方法,一个在出生时调用,一个在死亡时调用

​ |- void contextInitialized(ServletContextEvent sre):创建ServletContext时

​ |- void contextDestroyed(ServletContextEvent sre):销毁ServletContext时

1.2*属性监听:ServletContextAttributeListerner,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用。

​ |-void attributeAdded(ServletContextAttributeEvent event):添加属性时;

​ |-void attributeReplaced(ServletContextAttributeEvent event):替换属性时;

​ |-void attributeRemoved(ServletContextAttributeEvent event):移除属性时;

2HttpSession

2.1*生命周期监听:HttpSessionListerner,它有两个方法,一个在出生时调用,一个在死亡时调用

​ |- void sessionCreated(HttpSessionEvent sre):创建session时

​ |- void sessionCreated(HttpSessionEvent sre):销毁session时

2.2*属性监听:HttpSessionAttributeListerner,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用。

​ |-void attributeAdded(HttpSessionBindingEvent event):添加属性时;

​ |-void attributeReplaced(HttpSessionBindingEvent event):替换属性时;

​ |-void attributeRemoved(HttpSessionBindingEvent event):移除属性时;

3.ServletRequest

3.1*生命周期监听:ServletRequestListerner,它有两个方法,一个在出生时调用,一个在死亡时调用

​ |- void requestInitialized(ServletResquestEvent sre):创建request时

​ |- void requestDestroyed(ServletRequestEvent sre):销毁request时

3.2*属性监听:ServletRequestAttributeListerner,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用。

​ |-void attributeAdded(ServletRequestAttributeEvent srae):添加属性时;

​ |-void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时;

​ |-void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时;

监听域对象“创建”与“销毁”的监听器

监听域对象“操作域属性”的监听器

监听HttpSession的监听器

事件对象

ServletContextEvent:ServletContext getServletContext()

HttpSessionEvent:HttpSession getSession()

ServletRequest:

​ ServletContxt getServletContext()

​ ServletRequest getServletRequest()

ServletContextAttributeEvent:

​ ServletContext getServletContext();

​ String getName():获取属性名

​ Object getValue():获取属性值

HttpSessionBindingEvent:略

ServletRequestAttributeEvent:略

编写监听器

1.写一个监听器类,要求必须实现某个监听器接口;

2.注册,是在web.xml中配置来完成注册

day/src/AListener

package cn.itcast.web.listerner;
import javax.servlet.ServletContextEvent;
//可以在这个监听器中存放一些tomcat启动时就要完成的代码
public class Alisterner implements ServletContextListerner{
    @Override
    public void contextInitialized(ServletContextEvent sce){    //生之后调用
        System.out.println("我来了");  //启动服务器时就会有
    }
    @Override
    public void contextDestoryed(ServletContextEvent sce){      //死之前调用
        System.out.println("我要挂了")}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w2.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">
<listerner>
    <listerner-class>cn.itcast.web.listener.AListerner</listerner-class> 
 </listerner>
</web-app>

day/src/BListerner

package cn.itcast.web.listerner;
import javax.servlet.ServletContextAttribuetEvent;
public class Blisterner implements ServletContextAttributeListener{
    public void attributeAddes(ServletContextAttributeEven scab){
        System.out.println("您向application中添加一个名为"+scab.getName()+"值为:"
                          +scab.getValue()+"的属性")}
    public void attributeReplace(ServletContextAttributeEven scab){
       System.out.println(scab.getName()+"="+scab.getValue()+","
                         +scab.getServletContext().getAttribuet(scab.getName()))}
    public void attributeRemoved(ServletContextAttributeEvent scab){
        System.out.println(scab.getName()+"="+scab.getValue())}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w2.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">
<listerner>
    <listerner-class>cn.itcast.web.listener.AListerner</listerner-class> 
 </listerner>
 <listerner>
     <listerner-class>cn.itcast.web.listener.BListerner</listerner-class>
 </listerner>
</web-app>

index.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <%
        application.setAttribute("xxx","XXX");
      %>
    </body>
</html>

1589940475027

replcae.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <%
        application.setAttribute("xxx","YYY");
      %>
    </body>
</html>

1589940934652

remove.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <%
        application.removeAttribute("xxx");
      %>
    </body>
</html>

感知监听

用来添加到JavaBean上,而不是添加到三大域上

这两个监听器都不需要再web.xml中注册

HttpSessionBindListener:添加到JavaBean上,JavaBean就知道自己是否添加到session中

User.Java

public class User implements HtttpSessionBingdingListerner{
    private String username;
    private String password;
    //get set方法
    public User(){
        super();
    }
    public User(String username,String password){
        super();
        this.username=username;
        this.password=password;
    }
    public String toString(){
        return"User[username=]"+username+",password="+password+"]";
    }
    @Override
    public void valueBound(HttpSessionBindingEvent event){
        System.out.println("session添加了我");
    }
    @Override
    public void valueUnbound(HttpSesionBindingEvent event){
        System.out.println("session抛弃了我");
    }
}

add.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <%
        cn.itcast.web.listener.User user=new cn.itcast.web.listerner.User();
        session.setAttribute("user",user);
      %>
    </body>
</html>

[1589942874111

remove.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
      <%
         session.removeAttribute("user");
      %>
    </body>
</html>

1589942900956

session序列化

day/WebRoot/a.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            向session中保存数据
        </h1>
      <%
         session.setAttribute("xxx","我是快乐的小session");
      %>
    </body>
</html>

day/WebRoot/b.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            获取session中的数据
        </h1>
      <%
         out.print(session.getAttribute("xxx"));
      %>
    </body>
</html>

废除序列化

1589961349920

session的钝化和活化

​ HttpSessionActivationListener:Tomcat会在session长时间不被使用时钝化session对象,所谓钝化session,就是把session通过序列化的方式保存到硬盘文件中。当用户再使用session时,Tomcat还会把钝化的对象再活化session,所谓 活化就是把硬盘文件中的session在反序列化回内存。当session被Tomat钝化时,session中存储的对象也被钝化,当session被活化时,也会把session中存储的对象活化。如果某个类实现了HttpSessionActiveationListener接口后,当对象随着session被钝化和 活化时,下面两个方法就会被调用:

public void sessionWillPassivate(HttpSessionEvent se):当对象感知被活化时调用本方法;

public void sessionDidActivare(HttpSessionEvent se):当对象感知被钝化时调用本方法

​ HttpSessionActivationListener监听器与HttpSessionBindingListener监听器相似,都是感知型的监听器,例如让Person类实现了HttpSessionActivateListener监听器接口,并把Person对象添加到了session中后,当Tomcat钝化session时,同时也会钝化session中的Person对象,这时Person对象就会感知到自己被钝化了,其实就是调用Person对象的sessionWillPassivate()方法。当用户再次使用session时,Tomcat会活化session,这时Person会感知到自己被活化,其实就是调用Person对象的sessionDidActivate()方法

*注意:因为钝化和活化session,其实就是使用序列化和反序列化技术把session从内存保存到硬盘,和把session从硬盘加载到内存。这说明如果Person类没有实现Serializable接口,那么当session钝化时就不会钝化Person,而是把Person从session中移除再钝化,这也说明session活化 后,session中就不再有Person对象了

  • 先不管HttpSessionActivationListener监听器接口,先来配置Tomcat钝化session的参数,把下面配置文件方到Tomcat/conf/catalina/localhost目录下,文件名为项目名称
<Context>
    <!--如果session在1分钟内没有使用,那么Tomcat会钝化它-->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
    <!--把session序列化到Tomcat/work/Catalina/listener/mysession目录下-->
        <Store className="org.apache.catalina.session.FileStore" directory="mysession"/>
    </Manager>
</Context>

钝化
1589962638191

User.java

public class User implements HttpSessionActivationListerner,java.io.Serializable{
    @Override
    public void sessionWillPassivate(HttpSessionEvent se){
        System.out.println("我被钝化了");
    }
    @Override
    public void sessionDidActivate(HttpSesionEvent se){
        System.out.println("我活化了");
    }
}

a.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            向session中保存数据
        </h1>
      <%
         session.setAttribute("xxx",new cn.itcast.User());
      %>
    </body>
</html>

b.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            向session中保存数据
        </h1>
      <%
         out.print(session.setAttribute("xxx"));
      %>
    </body>
</html>
```

钝化

User.java

public class User implements HttpSessionActivationListerner,java.io.Serializable{
    @Override
    public void sessionWillPassivate(HttpSessionEvent se){
        System.out.println("我被钝化了");
    }
    @Override
    public void sessionDidActivate(HttpSesionEvent se){
        System.out.println("我活化了");
    }
}

a.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            向session中保存数据
        </h1>
      <%
         session.setAttribute("xxx",new cn.itcast.User());
      %>
    </body>
</html>

b.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//w3c//DTD html 4.01 Transitional//EN">
<html>
    <head>
        
    </head>
    <body>
        <h1>
            向session中保存数据
        </h1>
      <%
         out.print(session.setAttribute("xxx"));
      %>
    </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值