定时器Timer&监听器Listener

来源:互联网 发布:Linux开启lamp端口 编辑:程序博客网 时间:2024/06/06 09:26

利用定时器定时删除服务器端保存的Session

对于一个Web应用,N个用户访问就会产生N个Session,但如果成千上万的用户进行访问,总不能服务器一直保存所有的Session。就想是不是可以通过计算当前系统时间和上一次访问时间进行计算,如果超出一定的时间,那么就删除Session
我们使用监听器Listener监听Session对象和ServletContext对象

package com.itdream.listener;import javax.servlet.ServletContext;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;import java.util.List;/** * 监听HttpSession对象 * Created by Dream on 2017/12/7. */public class MySessionListener implements HttpSessionListener {    @Override    public void sessionCreated(HttpSessionEvent httpSessionEvent) {        //通过事件源对象获得事件源        HttpSession session = httpSessionEvent.getSession();        //通过session对象获取servletContext对象        ServletContext application = session.getServletContext();        List<HttpSession> list = (List<HttpSession>) application.getAttribute("sessions");        list.add(session);    }    @Override    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {    }}
package com.itdream.listener;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.http.HttpSession;import java.util.ArrayList;import java.util.List;import java.util.Timer;import java.util.TimerTask;/** * 监听ServletContext对象 * Created by Dream on 2017/12/7. */public class MyServletContextListener implements ServletContextListener {    @Override    public void contextInitialized(ServletContextEvent servletContextEvent) {        //通过事件源获得事件源对象        ServletContext application = servletContextEvent.getServletContext();        final List<HttpSession> list = new ArrayList<>();        application.setAttribute("sessions",list);        Timer t = new Timer();        //设置定时器任务        t.schedule(new TimerTask() {            //匿名内部类            @Override            public void run() {  //匿名内部类只能访问final类型的变量                for(HttpSession hs : list){                    long l = System.currentTimeMillis() - hs.getLastAccessedTime();                    if(l>5000){                        hs.invalidate(); //使Session无效                        list.remove(hs); //从list中移除session                    }                }            }        },2000,5000);  //延迟2s执行任务,之后每隔5s执行一次    }    @Override    public void contextDestroyed(ServletContextEvent servletContextEvent) {    }}

注意:使用Listener要配置web.xml

    <listener>        <listener-class>com.itdream.listener.MyServletContextListener</listener-class>    </listener>    <listener>        <listener-class>com.itdream.listener.MySessionListener</listener-class>    </listener>

随后我们启动服务器,访问任意页面,会出现如下问题:
这里写图片描述
这是因为在应用中执行定时器任务的时候,访问List出现了线程安全问题解决该问题修改的代码如下:

package com.itdream.listener;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.http.HttpSession;import java.util.*;/** * Created by Dream on 2017/12/7. */public class MyServletContextListener implements ServletContextListener {    @Override    public void contextInitialized(ServletContextEvent servletContextEvent) {        //通过事件源获得事件源对象        ServletContext application = servletContextEvent.getServletContext();        final List<HttpSession> list = Collections.synchronizedList(new ArrayList<>());        application.setAttribute("sessions",list);        Timer t = new Timer();        //设置定时器任务        t.schedule(new TimerTask() {            //匿名内部类            @Override            public void run() {  //匿名内部类只能访问final类型的变量                for(Iterator<HttpSession> it=list.listIterator();it.hasNext();){                    HttpSession hs = it.next();                    long l = System.currentTimeMillis() - hs.getLastAccessedTime();                    if(l>5000){                        hs.invalidate(); //使Session无效                        it.remove(); //从list中移除session                    }                }                /*for(HttpSession hs : list){                    long l = System.currentTimeMillis() - hs.getLastAccessedTime();                    if(l>5000){                        hs.invalidate(); //使Session无效                        list.remove(hs); //从list中移除session                    }                }*/            }        },2000,5000);  //延迟2s执行任务,之后每隔5s执行一次    }    @Override    public void contextDestroyed(ServletContextEvent servletContextEvent) {    }}
原创粉丝点击