session的补充和监控

不同的seesion

当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;

当不在同一个窗口中打开相同的浏览器时,发送请求,仍是同一个session;

当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;

当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,是不同的session。
测试


@Controller
@Slf4j
public class TestSeesionContoller {

    @ResponseBody
    @RequestMapping("/login")
    public Object login(HttpServletRequest httpServletRequest){

        HttpSession session=httpServletRequest.getSession();
        //log.info(session.getId());
        System.out.println("seesion"+session.getId());
        session.setAttribute("name","小华");
        System.out.println("cookie"+httpServletRequest.getCookies());
        System.out.println("===");

        return null;

    }

    @RequestMapping("/getSeesion")
    @ResponseBody
    public String getSesion(HttpServletRequest httpServletRequest){
        HttpSession session=httpServletRequest.getSession();
        System.out.println("ssesion"+session.getId());
        System.out.println("name"+session.getAttribute("name"));
        return null;
    }
}

看输出:
用谷歌浏览器请求:
输出:
seesionB0DD5AAF475235C13E0F84E5F8B4B793
cookie[Ljavax.servlet.http.Cookie;@1f236781

接着用ie浏览器请求:
输出:
ssesionD04983707E92123747AFC6EF317EC7C6
namenull;

可以看出不同的session设置属性是不能共享的,每一个session有自己特定的值,还有,每一次发出的请求的cookie(浏览器是有服务器发给浏览器存在浏览器的东西,生命周期和session是完全不一样的) 一种是存在于浏览器的进程中;

   一种是存在于硬盘上。

   而session的Cookie是存在于浏览器的进程中,那么这种Cookie我们称为会话Cookie,当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时服务器从tpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上原先的session等到它的默认时间到之后,便会自动销毁。

session什么时候死?

tomcat服务器的session的生命周期默认是30分钟,springboot可以在yml文件里面设置server.timeout=。。。。单位是秒
session的生命周期什么时候开始计算:
在生成session的时候,会设置一个session过期时间。session的过期时间并不是从生成session对象开始计算,超过过期时间,session就失效了。
而是每当一个浏览器请求,session生存时间就会刷新,最后一次浏览器请求,超过过期时间,没有浏览器请求到达,session就会过期

怎么样子让session死亡??

1.生命期到了自动死亡
2.手动杀死》 调用Session.invalidate()方法,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;比如说退出页面的时候,在关掉页面的时刻发出一个请求,后台执行invalidate()方法清除掉session;js里面有实现关掉页面发请求的函数onbeforeunload方法。

seesion的监控:

步骤:
1.ServletComponentScan注解需要添加到springboot启动类中,否则监听器无法被扫描到而不能执行
2.@WebListenter注解,添加到实现类上,如果没有添加那么将不能使用

3.在conf文件夹下新建一个java类重写两个接口HttpSessionListener, HttpSessionAttributeListener ;可以在每一个方法上写入相应的操作数据库等代码,当session被创建了之后或者销毁,又或者一个seesion的属性被销毁了都会自动触发这个被@WebListener注释了的类的方法(原理是动态代理)


@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
    public static final Logger logger= LoggerFactory.getLogger(SessionListener.class);

    @Override
    public void  attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        logger.info("--attributeAdded--");
        HttpSession session=httpSessionBindingEvent.getSession();
        logger.info("key----:"+httpSessionBindingEvent.getName());
        logger.info("value---:"+httpSessionBindingEvent.getValue());

    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        logger.info("--attributeRemoved--");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        logger.info("--attributeReplaced--");
    }

    @Override
    public void sessionCreated(HttpSessionEvent event) {
        logger.info("---sessionCreated----");
        HttpSession session = event.getSession();
        ServletContext application = session.getServletContext();
        // 在application范围由一个HashSet集保存所有的session
        HashSet sessions = (HashSet) application.getAttribute("sessions");
        if (sessions == null) {
            sessions = new HashSet();
            application.setAttribute("sessions", sessions);
        }
        // 新创建的session均添加到HashSet集中
        sessions.add(session);
        // 可以在别处从application范围中取出sessions集合
        // 然后使用sessions.size()获取当前活动的session数,即为“在线人数”
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) throws ClassCastException {
        logger.info("---sessionDestroyed----");
        HttpSession session = event.getSession();
        logger.info("deletedSessionId: "+session.getId());
        System.out.println(session.getCreationTime());
        System.out.println(session.getLastAccessedTime());
        ServletContext application = session.getServletContext();
        HashSet sessions = (HashSet) application.getAttribute("sessions");
        // 销毁的session均从HashSet集中移除
        sessions.remove(session);
    }

}

这个监控可实现把所有的seesion存储起来,在重写sessionCreated()方法时换了一种办法来写,如下:(发现每一次新建一个session时执行完了这个函数后那个用于存储session的list也就没了,没有保存下来,但是原文的可以,但是又不知道session.getServletContext()是什么意思,这时可以把session存在redis里面,)

System.out.println("全部session");
        List<HttpSession> sessions=new LinkedList<>();
        sessions.add(session);
        for (int i=0;i<sessions.size();i++){
            System.out.println(sessions.get(i)+"##");
        }

看输出:

全部session
org.apache.catalina.session.StandardSessionFacade@6a30d19d##
seesion49ED94F6391F997DEAD3FA6D0FFC8E48
2019-10-11 16:18:13.879  INFO 15052 --- [nio-8085-exec-1] c.lqh.suanfa_study.conf.SessionListener  : --attributeAdded--
2019-10-11 16:18:13.879  INFO 15052 --- [nio-8085-exec-1] c.lqh.suanfa_study.conf.SessionListener  : key----:name
2019-10-11 16:18:13.879  INFO 15052 --- [nio-8085-exec-1] c.lqh.suanfa_study.conf.SessionListener  : value---:小华
cookie[Ljavax.servlet.http.Cookie;@500ca0c9
===
seesion49ED94F6391F997DEAD3FA6D0FFC8E48
2019-10-11 16:18:24.212  INFO 15052 --- [nio-8085-exec-4] c.lqh.suanfa_study.conf.SessionListener  : --attributeReplaced--
cookie[Ljavax.servlet.http.Cookie;@74312fe5
===
2019-10-11 16:18:35.027  INFO 15052 --- [nio-8085-exec-6] c.lqh.suanfa_study.conf.SessionListener  : ---sessionCreated----
全部session
org.apache.catalina.session.StandardSessionFacade@4f8274fe##
seesion2A8EC9AFA0B175F05D0BACBC2171C402
2019-10-11 16:18:35.028  INFO 15052 --- [nio-8085-exec-6] c.lqh.suanfa_study.conf.SessionListener  : --attributeAdded--
2019-10-11 16:18:35.028  INFO 15052 --- [nio-8085-exec-6] c.lqh.suanfa_study.conf.SessionListener  : key----:name
2019-10-11 16:18:35.028  INFO 15052 --- [nio-8085-exec-6] c.lqh.suanfa_study.conf.SessionListener  : value---:小华
cookie[Ljavax.servlet.http.Cookie;@4145937e
===
seesion2A8EC9AFA0B175F05D0BACBC2171C402
2019-10-11 16:18:41.464  INFO 15052 --- [nio-8085-exec-7] c.lqh.suanfa_study.conf.SessionListener  : --attributeReplaced--
cookie[Ljavax.servlet.http.Cookie;@20c46efb
===

request session servletContext的区别联系(解析上面代码中为什么session.getServletContext()为什么可以保存所有的session)

就servlet规范本身,servlet可以再三个不同的作用域存储数据,分别是:

Request对象、Session对象和getServletContext()方法返回的servletContext对象中保存

1 首先从作用范围来说

Request       保存的键值仅在下一个request对象中可以得到。
Session        它是一个会话范围,相当于一个局部变量,从Session第一次创建知道关闭,数据都一直 保存,每一个客户都有一个Session,所以它可以被客户一直访问,只要Session没有关闭和超时即浏览器关闭。
servletContext    它代表了servlet环境的上下文,相当于一个全局变量,即只要某个web应用在启动中,这个对象就一直都有效的存在,所以它的范围是最大的,存储的数据可以被所有用户使用,只要服务器不关闭,数据就会一直都存在。

2 它们的优缺点:

request:

好处:用完就仍,不会导致资源占用的无限增长。
弊处:数据只能被下一个对象获取,所以在写程序时会因为无法共享数据导致每次要用都从数据库中取,多做操作,自然会对性能有一些影响。

session:

好处:是一个局部变量,可以保存用户的信息并直接取出,不用每次都去数据库抓,少做操作,极大的方便了程序的编写。
弊处:每个客户都有一个session,只能自己使用,不同session可能保存大量重复数据; 可能耗费大量服务器内存; 另外session构建在cookie和url重写的基础上,所以用session实现会话跟踪,会用掉一点点服务器带宽和客户端保持联络, 当然session越多,耗费的带宽越多,理论上也会对性能造成影响。 集群的session同步会是个问题。

servletContext:

好处:不用每次都去数据库抓,少做操作。 存储的数据所有客户都可以用。 可减少重复在内存中存储数据造成的开销。

看完了之后:总结一下:三者都有setAttribute和getAttribute(),两个函数,也就是说我们可以向三者存入我们的数据,但是存在request没什么用的,如httpServletRequest.getAttribute(“name”);;因为他是用完就扔的,session是一个局部变量,只针对一个session,servletContext可以用,全局变量,例如上述代码:

 HttpSession session = event.getSession();
        ServletContext application = session.getServletContext();
        System.out.println("全局变量servletContext:"+application);
        // 在application范围由一个HashSet集保存所有的session
        HashSet sessions = (HashSet) application.getAttribute("sessions");
        if (sessions == null) {
            sessions = new HashSet();
            application.setAttribute("sessions", sessions);
        }
        // 新创建的session均添加到HashSet集中
        sessions.add(session);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值