zoukankan      html  css  js  c++  java
  • 关于同一用户不能同时登录问题的探讨(2/2)

    前言

    这是一些理论的东西,大概包括httpsession监听的执行时机,以及相对应的attribute监听的机制调用,并写一些相应的实现sample.

    正文

    监听器概述:

    1.Listener是Servlet的监听器

    2.可以监听客户端的请求、服务端的操作等。

    3.通过监听器,可以自动激发一些操作,如监听在线用户数量,当增加一个HttpSession时,给在线人数加1。

    4.编写监听器需要实现相应的接口

    5.编写完成后在web.xml文件中配置一下,就可以起作用了

    6.可以在不修改现有系统基础上,增加web应用程序生命周期事件的跟踪

    常用的监听接口:

    1.ServletContextAttributeListener

    监听对ServletContext属性的操作,比如增加/删除/修改;

    2.ServletContextListener

    监听ServletContext,当创建ServletContext时,激发contextInitialized (ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed (ServletContextEvent sce)方法。

    3.HttpSessionListener

    监听HttpSession的操作。当创建一个Session时,激发session Created(SessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法(但是,如果用户关闭浏览器的话,不会马上调用sessionDestroyed方法,只有等到session过期才会调用,默认为30分)。

    4.HttpSessionAttributeListener

    监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded (HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved (HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced (HttpSessionBindingEvent se) 方法。

    实现sample: 

    1. 由Context监听器管理共享数据库连接,生命周期事件的一个实际应用由context监听器管理共享数据库连接。

    在web.xml中如下定义监听器:

    <listener>
    <listener-class>XXX.MyConnectionManager</listener-class>
    </listener>

    创建监听器的实例,接受事件并自动判断实现监听器接口的类型。要记住的是由于监听器是配置在部署描述符web.xml中,所以不需要改变任何代码就可以添加新的监听器

    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    public class MyConnectionManager implements ServletContextListener {
    
        public void contextInitialized(ServletContextEvent e) {
            Connection con = null;// create connection;
            e.getServletContext().setAttribute("con", con);
        }
    
        public void contextDestroyed(ServletContextEvent e) {
            Connection con = (Connection) e.getServletContext().getAttribute("con");
            try {
                con.close();
            } catch (SQLException ignored) {
            } // close connection
    
        }
    }

    监听器保证每新生成一个servlet context都会有一个可用的数据库连接,并且所有的连接对会在context关闭的时候随之关闭。

    2.HttpSessionListener监听

    在web.xml中如下定义监听器:

      <listener>
        <listener-class>org.bromon.test.SessionCount</listener-class>
      </listener>

    代码:

    package org.bromon.test;
    
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class SessionCount implements HttpSessionListener {
        private static int count = 0;
    
        public void sessionCreated(HttpSessionEvent se) {
            count++;
            System.out.println("session创建:" + new java.util.Date());
        }
    
        public void sessionDestroyed(HttpSessionEvent se) {
            count--;
            System.out.println("session销毁:" + new java.util.Date());
        }
    
        public static int getCount() {
            return (count);
        }
    }

    这里需要注意的是:sessionDestroyed是在session超时或调用session.invalidate就会执行,也就是说当浏览器异常关闭时,session不会马上消失的,而是要等过期或者调用了invalidate方法后才会调用sessionDestoryed方法。

    3.HttpSessionAttributeListener监听

    设置web.xml文件:

      <listener>
        <listener-class>com.horizon.test.OnlineList</listener-class>
      </listener>

     代码:

    package com.horizon.test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.http.HttpSessionAttributeListener;
    import javax.servlet.http.HttpSessionBindingEvent;
    
    public class OnlineList implements HttpSessionAttributeListener {
    
        private static Map<String, String> map = new HashMap<String, String>();
    
        public void attributeAdded(HttpSessionBindingEvent se) {
            System.out.println("login");
        }
    
        public void attributeRemoved(HttpSessionBindingEvent se) {
            System.out.println("logout");
        }
    
        public void attributeReplaced(HttpSessionBindingEvent se) {
        }
    
        public static Map<String, String> getMap() {
            return (map);
        }
    }

    4.servlet与ajax:
    jsp片段代码:

    <script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
    <script type="text/javascript">
        $(function() {
            setInterval(sub, 500);
        });
        function sub() {
            $.ajax({
                type : "post",//请求方式
                url : "SysServlet",//发送请求地址
                data : {//发送给数据库的数据
                    method : "out"
                },
                //请求成功后的回调函数有两个参数
                success : function(data, textStatus) {
                    $("#resText").append("<br/>" + data);
                },
                error : function(){
                    $("#resText").append("<br/>" + "服务器已经断开");
                }
            });
        }
    </script>

    servlet代码:

    package com.horizon.action;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import com.horizon.test.OnlineList;
    
    public class SysServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        public SysServlet() {
            super();
        }
    
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            HttpSession session = request.getSession();
            String method = request.getParameter("method");
            if ("login".equals(method)) {
                login(request, response);
            } else if ("logout".equals(method)) {
                System.out.println(session.getAttribute("username"));
                logout(request, response);
            } else {
                System.out.println(session.getAttribute("username"));
                session.setMaxInactiveInterval(1);
    
                System.out.println("start............");
    
                PrintWriter out = response.getWriter();
                out.write(">>>>>>>>>>>");
                out.flush();
                out.close();
            }
        }
    
        protected void login(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            HttpSession session = request.getSession();
            String username = request.getParameter("username");
            session.setAttribute("username", username);
            String uname = OnlineList.getMap().get(username);
            if ("name".equals(uname)) {
                response.sendRedirect("error.jsp");
                return;
            }
            OnlineList.getMap().put(username, "name");
            response.sendRedirect("main.jsp");
            session.setMaxInactiveInterval(1);
        }
    
        protected void logout(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            HttpSession sessions = request.getSession(false);// 防止创建Session
            OnlineList.getMap().remove(sessions.getAttribute("username"));
            sessions.removeAttribute("username");
            response.sendRedirect("index.jsp");
        }
    
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

     写的就这些了,望各位看官,交流意见......其中理论部分有网上查的东西....

  • 相关阅读:
    小程序事件参数传递
    java.lang.ClassNotFoundException: javax.servlet.SessionCookieConfig
    SSM单元测试时出现:Failed to load ApplicationContext的一种可能解决办法
    Cannot resolve classpath entry: /Program Files/IBM/SQLLIB/java/db2java.zip
    python 批量重命名文件
    abp + vue 模板新建页面
    Git 新建版本库命令
    vi/vim 行删除操作
    abp angular 前端权限控制
    杨辉三角-python
  • 原文地址:https://www.cnblogs.com/tv151579/p/3403113.html
Copyright © 2011-2022 走看看