15-web之过滤器和监听器

本文详细介绍了Servlet技术中的Filter和Listener两大组件。Filter用于对Web服务器管理的所有资源进行拦截,实现如URL级别的权限访问控制等功能。Listener则用于监听web应用中某些对象的状态变化,如用户的会话状态等。

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

Filter

        Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

        Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。


Filter介绍

  • 入门案例:
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")//过滤所有,包括jsp
public class MyFilter implements Filter {         //过滤器优先级与类名有关,按字符串顺序
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器1...init...执行了");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse 
            servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器1...doFilter...放行前");
        //放行(执行目标资源)
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("过滤器1...doFilter...放行后");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器1...destroy...执行了");
    }
}

         运行结果:

                

        可以看到过滤器随着服务器的开启初始化,且不能像servlet一样设置初始化时间(开启时还是第一次访问时);随着服务器的关闭销毁

  • 配置:
注解式配置:
在自定义的Filter类上使用注解@WebFilter(“/*”)   (上述案例即使用此配置方式)

xml配置:
在web.xml中进行过滤器的配置
<!-- web.xml配置方式:-->
    <!--过滤器优先级与配置顺序有关-->    
    <filter>
        <filter-name>myfilter2</filter-name>
        <filter-class>MyFilter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>myfilter1</filter-name>
        <filter-class>MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 过滤器链及优先级问题:
每个过滤器实现某个特定的功能,一个过滤器检测多个Servlet。(匹配几个,检测几个)。
通常客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),
那么这组过滤器就称为一条过滤器链。

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。
在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,
则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

如果为注解的话,是按照类名的字符串顺序进行起作用的
如果web.xml,执行顺序与<filter-mapping>的配置顺序有关,从上往下
web.xml配置高于注解方式(两者共存互不干扰时)

        注:同一个过滤器不要同时使用 web.xml 和 注解配置,会使服务器重复加载该过滤器:

                

  • 过滤器的初始化参数:
//基于注解的:
@WebFilter(value="/*",initParams= {@WebInitParam(name = "version", value = "1.0")})
    
//基于xml配置:
    <filter>
        <filter-name>myfilter</filter-name>
        <filter-class>MyFilter</filter-class>
        <!--过滤器的初始化参数  -->
        <init-param>
            <param-name>version</param-name>
            <param-value>1.0</param-value>
        </init-param>
    </filter>

        使用示例:

    @Override    
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器1...init...执行了");
        System.out.println("初始化参数:版本号:"+filterConfig.getInitParameter("version"));
    }

        运行结果:


Filter的典型应用

        可以实现 Web 应用程序中的预处理和后期处理逻辑 。

  • 过滤器控制浏览器缓存:
对于目前现在的浏览器,get请求动态资源缓存问题已经解决。

对于静态资源部分浏览器(IE,FixFox)使用Cache-Control头和Expires头设置缓存时间。chrome浏览器设置不设置都无效而是每次都请求服务器。

对于静态资源服务器会采用304状态码控制是否再次发送数据,从而节省带宽;可以通过Cache-Control=no-store控制304无效。
  • 禁止浏览器缓存动态页面:
@WebFilter(filterName = "NoCacheFilter",urlPatterns = "*.jsp")//jsp页面不要缓存好,静态页面要缓存好
public class NoCacheFilter implements Filter {
    public void destroy() {}
    public void doFilter(ServletRequest req, ServletResponse 
                    resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        response.setHeader("pragma", "no-cache");
        response.setHeader("expires", "0");
        chain.doFilter(req, resp);
    }
    public void init(FilterConfig config) throws ServletException {}
}

  • 使浏览器缓存静态资源:

@WebFilter(filterName = "CacheFilter",urlPatterns = {"*.html","*.css","*.jpg"})
public class CacheFilter implements Filter {     //静态页面要缓存
    public void destroy() {}
    public void doFilter(ServletRequest req, ServletResponse
                    resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //这两个属性对chrome无效
        response.setDateHeader("expires", System.currentTimeMillis() + 600000);
                                                                       //毫秒-10分钟
        response.setHeader("cache-control", "max-age=600");//秒-10分钟

        chain.doFilter(req, resp);
    }
    public void init(FilterConfig config) throws ServletException {}
}

        响应报文头:

ETag:令牌

        设置后用 chrome 第二次请求静态资源:

        设置后用 ie 第二次请求静态资源:

  • 自动登录:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
        <h2>用户登录</h2>
        <form action="${pageContext.request.contextPath}/login" method="post">
            <input type="text" name="username" placeholder="请输入用户名"><br/>
            <input type="password" name="password" placeholder="请输入密码"><br/>
            <input type="submit" value="登录">
            ${msg}
        </form>
</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>网站首页</title>
  </head>
  <body>
    <h2>欢迎访问我的网站</h2>
    当前用户:${empty username?"<a href='login.jsp'>请登录</a>":username}
  </body>
</html>
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //接受数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //判断
        if(username.equals("admin")&&password.equals("123456")){
            //正确
            //放入session
            request.getSession().setAttribute("username", username);
            //创建cookie
            String cookievalue=username+"#"+password;

            //BASE64Encoder base64Encoder=new BASE64Encoder();
            //String encode=base64Encoder.encode(cookievalue.getBytes("utf-8"));
            String encode = Base64.getEncoder().encodeToString(cookievalue.getBytes("utf-8"));
            Cookie cookie=new Cookie("userinfo", encode);
            //1有效期
            cookie.setMaxAge(60*60*24*7);
            //2有效路径
            cookie.setPath("/");
            //3设置httponly
            cookie.setHttpOnly(true);
            response.addCookie(cookie);
            response.sendRedirect(request.getContextPath()+"/index.jsp");
        }else{
           request.setAttribute("msg", "用户名或密码错误");
           request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
@WebFilter(filterName = "AutoLoginFilter", urlPatterns = "/index.jsp")
public class AutoLoginFilter implements Filter {
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //处理
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //1先查看session有没有数据
        String username = (String) request.getSession().getAttribute("username");
        System.out.println("-------------" + username);
        if (username == null) {
            //2再查看cookie
            Cookie[] cookies = request.getCookies();
            if (cookies != null && cookies.length > 0) {
                for (Cookie cookie : cookies) {
                    String name = cookie.getName();
                    if (name.equals("userinfo")) {
                        String value = cookie.getValue();
                        BASE64Decoder decoder = new BASE64Decoder();
                        byte[] bs = decoder.decodeBuffer(value);
                        String userinfo = new String(bs, "utf-8");
                        String[] userinfos = userinfo.split("#");
                        if (userinfos[0].equals("admin") && userinfos[1].equals("123456")) {
                            //自动登录
                            request.getSession().setAttribute("username", userinfos[0]);
                        } else {
                            //删除
                            Cookie cookie1 = new Cookie("userinfo", "username");
                            cookie1.setMaxAge(0);
                            cookie1.setPath("/");
                            cookie1.setHttpOnly(true);
                            response.addCookie(cookie1);
                        }
                    }
                }
            }
        }
        //放行
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {}
}
  • 过滤器解决编码:
public class CharacterEncodingFilter implements Filter {
    private String defaultCharset = "utf-8";
    private FilterConfig config;
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //获取配置中的编码
        String charset = config.getInitParameter("charset");
        if (charset == null) {
            charset = defaultCharset;
        }
        System.out.println(charset);
        req.setCharacterEncoding(charset);
        resp.setContentType("text/html;charset=" + charset);

        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }
}
  • 过滤器解决脏词:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@WebFilter(filterName = "DirtyFilter", urlPatterns = "/comment")
public class DirtyFilter implements Filter {
    @Override
    public void init(FilterConfig config) throws ServletException {}
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //放行(执行目标资源)
        HttpServletRequest request = (HttpServletRequest) req;
        DirtyHttpServletRequest drequest = new DirtyHttpServletRequest(request);
        chain.doFilter(drequest, resp);
    }

    /*
    增强方法的功能:
    1 继承重写
    2 装饰者模式
    3 动态代理
     */
    //此处使用"2 装饰者模式",HttpServletRequestWrapper为抽象类,DirtyHttpServletRequest为装饰者实现
    static class DirtyHttpServletRequest extends HttpServletRequestWrapper {
        private static List<String> dirtyWords = null;
        static {
            dirtyWords = Arrays.asList("狗蛋", "扯淡", "sb");
        }
        public DirtyHttpServletRequest(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(String name) {
            String paraValue = super.getParameter(name);
            //过滤
            for (String dirtyWord : dirtyWords) {
                paraValue = paraValue.replaceAll(dirtyWord, "***");
            }
            System.out.println("过滤完成.......");
            return paraValue;
        }
    }

}
  • 响应内容压缩:
@WebFilter(filterName = "GzipFilter", urlPatterns = "*.jsp")
public class GzipFilter implements Filter {
    @Override
    public void init(FilterConfig config) throws ServletException {}
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletResponse response = (HttpServletResponse) resp;
        GzipHttpServletResponse gresponse = new GzipHttpServletResponse(response);
        response.setContentType("text/html;charset=utf-8");
        //放行(执行目标资源)
        chain.doFilter(req, gresponse);
        //把内容压缩后再给浏览器
        ByteArrayOutputStream baos = gresponse.getBaos();
        System.out.println("压缩之前:" + baos.size());
        //新的内存流
        ByteArrayOutputStream newbaos = new ByteArrayOutputStream();
        //压缩
        GZIPOutputStream gzip = new GZIPOutputStream(newbaos);
        gzip.write(baos.toByteArray());
        gzip.flush();
        gzip.close();
        System.out.println("压缩之后:" + newbaos.size());

        //添加响应头,告诉浏览器内容是压缩的
        response.setHeader("Content-Encoding", "gzip");

        //把压缩的内容给浏览器
        response.getOutputStream().write(newbaos.toByteArray());
    }

    //装饰者模式
    static class GzipHttpServletResponse extends HttpServletResponseWrapper {
        private ByteArrayOutputStream baos;
        private PrintWriter pw;
        public GzipHttpServletResponse(HttpServletResponse response) {
            super(response);
            //初始化pw
            baos = new ByteArrayOutputStream();
        }

        public ByteArrayOutputStream getBaos() {
            if (pw != null) {
                pw.flush();//把内容刷新到底层流
            }
            return baos;
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            if (pw == null) {
                pw = new PrintWriter(new OutputStreamWriter(baos, "utf-8"));
            }
            return pw;
        }
    }

}
  • 实现图片防盗链:

        http 协议中,如果从一个网页跳到另一个网页,http 头字段里面会带个 Referer。图片服务器通过检测 Referer 是否来自规定域名,来进行防盗链(防止其它网站盗用图片,浪费流量)

@WebFilter(filterName = "StealFilter",urlPatterns ={"*.jpg","*.png","*.bmp"})
public class StealFilter implements Filter {
    @Override
    public void init(FilterConfig config) throws ServletException {}
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request= (HttpServletRequest) req;
        HttpServletResponse response= (HttpServletResponse) resp;
        String referer = request.getHeader("referer");
        System.out.println(referer+"---------------");
        if(referer!=null&&referer.startsWith("http://localhost:8080"+request.getContextPath())){
            //正常访问
            chain.doFilter(req, resp);
        }else{
            request.getRequestDispatcher("/img/steal.jpg").forward(request, response);
        }
    }
}

Listener

        监听器用于监听web应用中某些对象(request,session,application)、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计访问人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

实现原理:

观察者模式&事件监听_头秃人强的博客-CSDN博客


 Listener介绍

  • 生命周期监听器:
ServletContext上下文监听器:
    ServletContextListener接口
		内部方法:
		初始化:contextInitialized
		销毁:contextDestroyed

Session监听器:
    HttpSessionListener
		内部方法:
		sessionCreated:监听Session对象的创建
		sessionDestroyed:监听Session对象的销毁

request监听器:
    ServletRequestListener
		监听request对象的初始化和销毁
		内部方法:
			1、requestInitialized:监听request对象的初始化
			2、requestDestroyed:监听request对象的销毁
  • 属性变化监听器:
ServletContext属性变化监听器:
    ServletContextAttributeListener接口        
 		内部的方法:        
 		attributeAdded:监听属性的添加        
 		attributeRemoved:监听属性的移除        
 		attributeReplaced:监听属性的修改

session属性变化监听器:
    HttpSessionAttributeListener
		监听HttpSession的内容的变化
		内部的方法:
		attributeAdded:监听属性的添加
		attributeRemoved:监听属性的移除
		attributeReplaced:监听属性的修改

request属性变化监听器:
    ServletRequestAttributeListener
		监听属性内容变化
		内部方法:
		attributeAdded:监听属性的添加
		attributeRemoved:监听属性的移除
		attributeReplaced:监听属性的修改
  • 感知型监听器: 
对象从session添加或移除:
    HttpSessionBindingListener
		监听对象的添加和移除
		内部方法:
		valueBound:监听对象的绑定
		valueUnbound:监听对象的解除绑定

对象钝化和活化:
    HttpSessionActivationListener
		监听session的钝化和活化
		内部方法:
		sessionWillPassivate:监听Session内部存储对象的钝化-写入
		sessionDidActivate:监听Session内部存储对象的活化-读取
		对应类需要实现序列化接口Serializable
		
在 web目录下创建META-INF文件夹,在META-INF文件夹中创建context.xml文件		
<?xml version='1.0' encoding='utf-8'?>
<Context>
	<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
	<Store className="org.apache.catalina.session.FileStore" directory="qf">  
	</Store>
</Manager>
</Context>
<!-- maxIdleSwap: session中的对象多长时间不使用就被钝化 (分钟单位) -->
<!-- directory: 钝化后的对象的文件写到磁盘的哪个目录下 -->
<!-- 配置钝化的对象文件在${TOMCAT_HOME}/work/Catalina/localhost/YOUR_PROJECT/qf -->
  • 监听器的两种配置:
在web.xml中进行配置:
<listener>
<!--直接写出自定义的监听器的类名即可-->
    <listener-class>com.qf.web.listener.RequestLeftListener</listener-class>
</listener>

Servlet3.0之后新增的,使用注解@WebListener进行监听器的注册

Listener应用

  • 生命周期监听器:
/**
 * ServletContext监听器作用:1启动应用程序时提前加载类,做一些初始化工作 2关闭应用程序时,释放资源。关闭连接池
 */
//@WebListener
public class ApplicationListener implements ServletContextListener {
    //上下文初始化
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext applcation = sce.getServletContext();
        System.out.println("servletcontext创建了..."+applcation.toString());
    }
    //上下文销毁
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext applcation = sce.getServletContext();
        System.out.println("servletcontext销毁了..."+applcation.toString());
    }
}

/**
 * sesssionListener: 1 初始化与用户相关的数据  (权限信息) 2 释放与用户有关的信息
 *  (1)统计当前访问用户
 */
public class SessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("session创建了session:"+session.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("session销毁了session:"+session.getId());
    }
}

/**
 * RequestListener:统计应用程序一天请求次数。
 */
//@WebListener
public class RequestListener  implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        ServletRequest request = sre.getServletRequest();
        System.out.println("请求对象销毁了..."+request.toString());

    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        ServletRequest request = sre.getServletRequest();
        System.out.println("请求对象创建了..."+request.toString());
    }
}
  • 属性变化监听器:
//@WebListener
public class AttributeListener implements ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener {
    //application属性变化
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        System.out.println("向application中添加:" + name + ":" + value);
    }
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        System.out.println("向application中移除:" + name + ":" + value);
    }
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        System.out.println("向application中替换:" + name + ":" + value);
    }

    //session属性变化
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        String name = se.getName();
        Object value = se.getValue();
        System.out.println("向session中添加:" + name + ":" + value);
    }
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        String name = se.getName();
        Object value = se.getValue();
        System.out.println("向session中移除:" + name + ":" + value);
    }
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        String name = se.getName();
        Object value = se.getValue();
        System.out.println("向session中替换:" + name + ":" + value);
    }

    //request属性变化
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("向request中添加:" + name + ":" + value);
    }
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("向request中移除:" + name + ":" + value);
    }
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("向request中替换:" + name + ":" + value);
    }
}
  • 实现访问人数统计: 
//@WebListener
public class VisitCountListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext application = se.getSession().getServletContext();
        Integer count = (Integer) application.getAttribute("count");
        if (count == null) {
            application.setAttribute("count", 1);
        } else {
            count++;
            application.setAttribute("count", count);
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext application = se.getSession().getServletContext();
        Integer count = (Integer) application.getAttribute("count");
        if (count > 0) {
            count--;
            application.setAttribute("count", count);
        }
    }
}
  • 自定义Session管理器:
session会话的默认有效时间为30分钟,需要使用开发人员自己管理session的有效期,不需要系统管理。
​	功能1:把所有的session放入集合中。
​	功能2:遍历集合中每个session, 判断session有多长时间没有被访问了,如果超过1分钟,置session为失效
//@WebListener
public class SessionManagerListener implements HttpSessionListener, ServletContextListener {
    private Timer timer;
    private static List<HttpSession> sessions;
    static {
        sessions = Collections.synchronizedList(new LinkedList<>());
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("定时器启动了....");
        //初始化timer
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                synchronized (sessions) {
                    Iterator<HttpSession> it = sessions.iterator();
                    while (it.hasNext()) {
                        //判断是否超过1沒有访问
                        HttpSession session = it.next();
                        long d = System.currentTimeMillis() - session.getLastAccessedTime();
                        if (d > 60000) {
                            System.out.println("session失效了:" + session.getId());
                            session.invalidate();
                            it.remove();
                        }
                    }
                }
            }
        }, 0, 1000);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        timer.cancel();
        System.out.println("定时器关闭了....");
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("添加了一个session");
        sessions.add(se.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }
}
  • 感知型监听器:
public class User implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {
    private String userid;
    private String username;
    private String password;

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("绑定session:" + this.userid + "..." + this.username);
        //获取application
        ServletContext application = event.getSession().getServletContext();
        Integer logincount = (Integer) application.getAttribute("logincount");
        if (logincount == null) {
            logincount = 1;
        } else {
            logincount++;
        }
        application.setAttribute("logincount", logincount);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("解除绑定session:" + this.userid + "..." + this.username);
        ServletContext application = event.getSession().getServletContext();
        Integer logincount = (Integer) application.getAttribute("logincount");
        if (logincount > 0) {
            logincount--;
        }
        application.setAttribute("logincount", logincount);
    }

    //钝化(序列化)
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("sessionid:" + session.getId() + "对象钝化了...." + this.toString());
    }

    //活化(反序列)
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("sessionid:" + session.getId() + "对象活化了...." + this.toString());
    }
}
<?xml version='1.0' encoding='utf-8'?>
<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="qq">
        </Store>
    </Manager>
</Context>
        <!-- maxIdleSwap: session中的对象多长时间不使用就被钝化 (分钟单位) -->
        <!-- directory: 钝化后的对象的文件写到磁盘的哪个目录下 -->
        <!-- 配置钝化的对象文件在${TOMCAT_HOME}/work/Catalina/localhost/YOUR_PROJECT/qq -->

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值