一.HttpSessionListener的作用

1.1 常用方法

这个接口也只包含两个方法,分别对应于Session的创建和失效:

1.public void sessionCreated(HttpSessionEvent se);
2.public void sessionDestroyed(HttpSessionEvent se);
 sessionHandler中 调用sessionDestroyed方法,虽然此时 httpSessionEvent.getSession().getAttribute("name");                                                  
能够获取信息,但是执行完此方法后,其他地方通过session.getAttribute("name"),获取为null
session的默认超时时间为:1800s  为30分钟

1.2 参考其他常用过滤器

拦截器参考文章:CSDN

过滤器: springboot的filter 过滤器的使用_健康平安的活着的专栏-CSDN博客

监听器: springboot之HttpSessionListener的用法创建,销毁_健康平安的活着的专栏-CSDN博客_httpsessionlistener

拦截器:  CSDN

二.HttpSessionListener的触发机制

2.1 创建与销毁的情况

当一个浏览器第一次访问网站的时候,J2EE应用服务器会新建一个HttpSession对象 ,并触发 HttpSession创建事件 ,如果注册了HttpSessionListener事件监听器,则会调用HttpSessionListener事件监听器的 sessionCreated方法。

相反,当这个浏览器访问结束超时的时候,J2EE应用服务器会销毁相应的HttpSession对象,触发 HttpSession销毁事件,同时调用所注册HttpSessionListener事件监听器的sessionDestroyed方法。

以下两种情况下就会发生sessionDestoryed(会话销毁)事件

1.执行session.invalidate()方法时   会调用sessionListener的sessionDestroyed方法

2.如果用户长时间没有访问服务器,超过了会话最大超时时间 ,服务器就会自动销毁超时的session。会调用sessionListener的sessionDestroyed方法。流程如下图所示:

会话超时时间可以在web.xml中进行设置,为了容易看到超时效果,我们将超时时间设置为最小值

<session-config>
 <session-timeout>1</session-timeout>

</session-config>

时间单位是一分钟,并且只能是整数,如果是零或负数,那么会话就永远不会超时。

参考来源:HttpSessionListener的用法 - 吴小雨 - 博客园 

三.setMaxInactiveInterval与setTimeout的区别

3.1 相同与区别

1.setMaxInactiveInterval设置的是当前会话的失效时间,不是整个web的时间,单位为以秒计算。
 如果设置的值为零或负数,则表示会话将永远不会超时。常用于设置当前会话时间。

2.session-timeout元素(WEB.XML文件中的元素)用来指定默认的会话超时时间间隔, 以分钟为单位。该元素值必须为整数。如果session-timeout元素的值为零或负数,则表示会话将永远不会超时。

session的默认超时时间为:1800s  为30分钟

可以理解为两种实现方式,一种通过java代码进行设置,且按秒作为计算单位,一种通过web.xml配置文件进行配置,单位为分钟。

四.项目演示

4.1.创建项目:spt-listener-demo

4.2.pom文件:

  <!--spring boot的启动类 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

4.3.编写controller:

package com.ljf.spring.boot.demo.spt.listener.controller;

import com.ljf.spring.boot.demo.spt.listener.utils.DateUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @ClassName: LoginController
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2020/08/19 18:54:35
 * @Version: V1.0
 **/
@Controller
public class LoginController {

    /**
    * @author liujianfu
     * 创建用户
    * @param [request]
    * @return void
    */
    @RequestMapping("/login")
    @ResponseBody
    public String createUser(HttpServletRequest request){
        System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"controller层创建用户:");
        request.getSession().setAttribute("name","zwq");
         return "ok";
    }
    @RequestMapping("/query")
    @ResponseBody
    public String queryUser(HttpServletRequest request){
        System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"controller层查询用户:");
       String name=(String) request.getSession().getAttribute("name");
       System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"当前在线用户:"+name);
        return "ok";
    }
    @RequestMapping("/logout")
    @ResponseBody
    public String cancelUser(HttpServletRequest request){
        System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"controller层销毁用户:");
        //销毁session
        request.getSession().invalidate();
        return "ok";
    }
}

4.4.编写session监听器

package com.ljf.spring.boot.demo.spt.listener.listener;

import com.ljf.spring.boot.demo.spt.listener.utils.DateUtil;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Date;

/**
 * @ClassName: MySessionListener
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2020/08/19 18:47:34
 * @Version: V1.0
 **/
@WebListener
public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        //设置session持续时间,单位为秒
        /*1.setMaxInactiveInterval设置的是当前会话的失效时间,不是整个web的时间,单位为以秒计算。
        * 如果设置的值为零或负数,则表示会话将永远不会超时。常用于设置当前会话时间。
        * 2.session-timeout元素(WEB.XML文件中的元素)用来指定默认的会话超时时间间隔,
        * 以分钟为单位。该元素值必须为整数。如果session-timeout元素的值为零或负数,
        * 则表示会话将永远不会超时
        */
        httpSessionEvent.getSession().setMaxInactiveInterval(60);
        System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"-----------session监听器中Session已创建------------------");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        String name = (String)httpSessionEvent.getSession().getAttribute("name");
        System.out.println(DateUtil.dateToStrLong(new Date(),"yyyy-MM-dd HH:mm:ss")+"-----------session监听器中Session已销毁------------------"+"name= "+ name);
    }
}

4.5.DateUtil工具类:

package com.ljf.spring.boot.demo.spt.listener.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: DateUtil
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2020/08/19 20:56:49
 * @Version: V1.0
 **/
public class DateUtil {
    /**
     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
     *
     * @param dateDate
     * @return
     */
    public static String dateToStrLong(Date dateDate,String pattern) {
        SimpleDateFormat formatter = new SimpleDateFormat (pattern);
        String dateString = formatter.format (dateDate);
        return dateString;

    }
}

4.6.启动类:

package com.ljf.spring.boot.demo.spt.listener;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;

import java.util.concurrent.TimeUnit;

/**
 * Hello world!
 *
 */
@SpringBootApplication
@ServletComponentScan
public class App 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class, args);
        System.out.println( "listener qidong ....." );
    }

}

五.测试演示

5.1 通过主动销毁session

5.1.1 登录访问创建session

1.通过访问登录接口,登录成功,调用session,存储用户信息,则触发session的创建方法,在sessionlistener调用create方法。

2.查看后端日志

5.1.2  访问查询session信息

1.访问query方法:

因为前面执行login方法访问,sessionlistener监听到了session的创建,执行了sessioncreate方法,本次执行query方法,不再执行sessionlistener中的sessionCreate方法。而是直接访问controller中query方法,进行信息输出。

1.访问查询

2.后端日志

 5.1.3  退出,销毁用户的session信息

最后访问logout请求,里面调用invlidate()方法,触发了listener的destrory()方法,session进行失效。会调用sessionListener中的sessionDestroyed()方法

1.页面访问: 主动销毁session:http://localhost:8091/logout

2.查看后台:

 5.1.4  退出后,再次查询用户的session信息

1.页面

2.后端日志 

5.2 sessiontimeout超时自动注销session

5.2.1 登录访问创建session

1.页面访问

2.配置文件设置600s

5.2.2 不作任何操作,让session过期

等待10分钟后: 查看后端日志:配置文件设置为秒为单位:这里设置10分钟,600s

调用:sessionHandler中 调用sessionDestroyed方法,虽然此时: 

         httpSessionEvent.getSession().getAttribute("name");                                                  
能够获取信息,但是执行完此方法后,其他地方通过session.getAttribute("name"),获取为null

 ###4.按每分钟设置

1.在application配置 文件配置session timeout的超时时间:server.servlet.session.timeout = PT1M

参考地址:SpringBoot session超时的问题 - ergexy - 博客园 

2.按照配置文件配置的1分钟后查看后端文件:

5.2.3 进行查询query访问

进行query查询,看看session中的用户的信息,可以看到用户的session信息已经为null

1.页面访问 

2.控制台: 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐