
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
昆明IT培训的小编这一期给大家讲自定义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中