• 自定义session扫描器


    为何要自定义session扫描器

    由于服务器来管理session的销毁不怎么靠谱,因此很多网站都会自己定义一个session扫描器来管理session的创建和销毁。

    实现思路

    首先,创建一个session扫描器类SessionScanner,然后继承HttpSessionListener,在sessionCreated方法中,获取session,这个时候我们需要创建一个容器,用来存放session,然后继承ServletContextListener,在contextInitialized方法(在web应用启动时执行此方法)中定义一个定时器,将一段时间内没有用到的session销毁。

    代码实现如下:

     1 package com.ccfdod.web.listener;
     2 
     3 import java.util.Collections;
     4 import java.util.Iterator;
     5 import java.util.LinkedList;
     6 import java.util.List;
     7 import java.util.ListIterator;
     8 import java.util.Timer;
     9 import java.util.TimerTask;
    10 
    11 import javax.servlet.ServletContextEvent;
    12 import javax.servlet.ServletContextListener;
    13 import javax.servlet.http.HttpSession;
    14 import javax.servlet.http.HttpSessionEvent;
    15 import javax.servlet.http.HttpSessionListener;
    16 
    17 public class SessionScanner implements HttpSessionListener,ServletContextListener {
    18 
    19     //这里使用Collections.synchronizedList(List<T> list)是考虑到线程并发问题,因此将容器设置为线程安全的
    20     //Collections为集合的帮助类,如发现具体的集合类不能提供某些功能,可查看该帮助类的方法,看是否存在该功能
    21     //另外使用LinkedList而不使用ArrayList的原因是ArrayList底层为数据,用来做增删改查不适合,效率较低
    22     private List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>());
    23 
    24     //定义一个锁对象,用于解决线程并发时,session的添加和除去若同时进行,会引起定时器中对list的session操作时,产生迭代器并发修改异常
    25     private Object lock = new Object();
    26     public void contextInitialized(ServletContextEvent sce) {
    27         //这里使用Timer作为定时器,当然也可以使用其他的
    28         Timer timer = new Timer();
    29         timer.schedule(new MyTask(list,lock), 0, 30*1000);
    30     }
    31     
    32     public void sessionCreated(HttpSessionEvent se) {
    33         //第一次调用getSession时,服务器创建一个session
    34         //但在jsp中,默认调用request.getSession()方法,创建一个session
    35         //但可以在jsp文件的第一行,添加session="false",这样在访问jsp页面时,就不会创建session了
    36         HttpSession session = se.getSession();
    37         System.out.println(session + "被创建了!!");
    38         synchronized (lock) {  //锁旗标
    39             list.add(session);
    40         }
    41     }
    42     public void sessionDestroyed(HttpSessionEvent se) {
    43         System.out.println(se.getSession() + "被销毁了");
    44     }
    45 
    46     public void contextDestroyed(ServletContextEvent sce) {
    47         
    48     }
    49 }
    50 
    51 class MyTask extends TimerTask{
    52     private List list;
    53     private Object lock;
    54     public MyTask(List list,Object lock){
    55         this.list = list;
    56         this.lock = lock;
    57     }
    58     @Override
    59     public void run() {
    60         System.out.println("定时器执行!!");
    61         synchronized (this.lock) {
    62             //ListIterator为Iterator的子类,提供了对crud操作
    63             ListIterator it = list.listIterator();
    64             while(it.hasNext()){
    65                 HttpSession session = (HttpSession) it.next();
    66                 if((System.currentTimeMillis()-session.getLastAccessedTime())>30*1000){
    67                     session.invalidate();
    68                     //list.remove(session);  //迭代器并发修改异常
    69                     //若对集合迭代,需要对集合进行crud操作时,使用迭代器的方法对集合进行crud
    70                     it.remove();
    71                 }
    72             }
    73         }
    74     }
    75 }

    最后

    将SessionScanner添加至web.xml中

  • 相关阅读:
    CUDA教程三、cuda的随机数生成
    python 使用element tree 解析 xml
    [转载] Shell正则表达式大全
    git 更新项目中子模块的版本
    git 切换到本地不存在但远端存在的分支
    vue.js3:在css中使用变量(vue@3.2.6)
    mybatis做update:动态传入要更新的字段名和字段值(mybatis 3.5.7)
    npm全局安装和非全局安装的区别(node v16.13.1 / npm 8.4.1)
    vue.js3:用mitt发送接收事件消息(vue@3.2.6 / mitt@3.0.0)
    vue3: 动态修改favicon(网站的ico 图标)(vue@3.2.26)
  • 原文地址:https://www.cnblogs.com/ccfdod/p/6288328.html
Copyright © 2020-2023  润新知