SessionScaner:Session定时扫描器

            这个博客主要是用来介绍对Session定时扫描的一个作用,也就是session定时扫描器,该扫描器涉及到了线程并发、线程安全、迭代器选择和定时器等知识。扫描器的具体操作步骤如下:

1.创建一个监听器SessionScaner实现HttpSession、SerevletContext接口。

2.在创建session方法中监听session的创建,然后将创建的session保存到自己创建的容器中。

3.当web应用启动的时候,创建一个定时器,为定时器设置一个schedul()方法,用来设置定时任务和定时时间。

4.编写定时任务类实现TimerTask接口,覆盖其run()方法,在run()方法中使用迭代器来迭代容器中的session链接,考虑到

线程安全和线程并发的问题,我在这里使用共享锁解决还问题和使用ListItrator 迭代器取代Itrator迭代器,解决线程并发访问出现的异常。


代码如下:

1.SessionScaner.java

package com.nyist.cn.Example;

import java.util.List;
import java.util.ListIterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Collections;
import java.util.LinkedList;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

//session扫描器
public class SessionScaner implements HttpSessionListener,ServletContextListener{

//在有Session创建的时候,将session创建的链接放在一个集合中去
//Collections  是集合的一个辅助工具类,之所以使用你Collections.synchronizedList()方法是因为该方法
//可以实现线程安全  避免线程并发访问
private List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>());
private Object lock = new Object();
@Override
public void sessionCreated(HttpSessionEvent se) {
//拿到Session链接
HttpSession session = se.getSession();
System.out.println(session+" 被创建了!");
synchronized(this.lock){
list.add(session);
}
}

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

@Override
public void contextDestroyed(ServletContextEvent sce) {
}

@Override
public void contextInitialized(ServletContextEvent sce) {
//Web应用启动的时候,定义一个定时器
Timer time = new Timer();
time.schedule(new MyTesk(list,lock),0,10*1000);
}
}

//定义一个任务  座位参数传递给定时器让其每隔多长时间进行调度
class MyTesk extends TimerTask{

private List list;
private Object lock;
public MyTesk(List list,Object lock){
this.list = list;
this.lock = lock;
}

//有线程并发访问异常 ,需要使用synchronized 放到同步代码块中,但是需要同步的代码位置不在一块的时候
//这时候就需要使用 共享同一把锁了
@Override
public void run() {
System.out.println("定时器执行");
//这里使用共享锁  是因为防止线程并发执行 list.add()和以下run()方法
synchronized (this.lock) {
//这里之所以  使用listIterator()获得ListItrator迭代器,是因为如果使用Itrator这种迭代器
//当我们在 对迭代器进行添加add()、删除remove()的时候,迭代器并不知道,所以会可能发生线程并发异常
//使用ListItrator()这种迭代器 可以避免这种异常
ListIterator it = list.listIterator();
while(it.hasNext()){
HttpSession session = (HttpSession)it.next();
if(System.currentTimeMillis() - session.getLastAccessedTime() > 10*1000){
session.invalidate(); //销毁session链接
it.remove();
}
}
}
}

   <listener>

}

2.在web.xml中注册该监听器

<listener-class>com.nyist.cn.Example.SessionScaner</listener-class>

</listener>

3.我们访问工程下的index.jsp页面,观察控制台信息输出

4.运行结果


猜你喜欢

转载自blog.csdn.net/lvhaoguang0/article/details/81065846
今日推荐