java中使用session监听实现同帐号登录限制、登录人数限制

所属分类: 软件编程 / java 阅读数: 46
收藏 0 赞 0 分享

本文主要介绍了java中使用session监听实现同帐号登录限制、登录人数限制,具体代码如下:

问题域:

1、同帐号登录:若此帐号已登录,不可再次登录(与QQ模式相反)。

2、登录人数限制,超过、已达人数限制则提示:系统繁忙,稍后再试。

解决思路:使用HttpSessionAttributeListener监听器(虽然我同时使用了HttpSessionListener不过感觉不好操作)

知识储备:HttpSessionAttributeListener中有attributeAdd、attributeRemove、attributeReplace3个方法。

对session的setAttribute、removeAttribute将触发attributeAdd、attributeRemove方法,对同一个session的同一个attribute进行重复设置将触发attributeReplace方法。

HttpSessionListener不好操作的原因:只要访问jsp页面便会创建session(访问html并不会创建session,在server端,如servlet中调用HttpServletRequest.getSession(true)才会创建),jsp是动态页,本质就是个servlet。我的login.jsp显然是个jsp,当我在监听器中invalidate一个session,返回登录页,马上就又创建了一个session。这是我感觉不清楚的地方,功夫没到家。

具体实现:

监听器代码

public class OnlineListener implements HttpSessionListener,
    HttpSessionAttributeListener {
  private static List<SessionAndUser> sessions;
  static int delS = -1;
  static boolean flag = false;
  static {
    if (sessions == null) {
      sessions = Collections
          .synchronizedList(new ArrayList<SessionAndUser>());
    }
  }
  public void sessionCreated(HttpSessionEvent hse) {
    System.out.println(hse.getSession() + "-" + new Date());
    System.out.println(hse.getSession() + "-" + new Date());
  }
  public void sessionDestroyed(HttpSessionEvent hse) {
    System.out.println("-------------sessionDestroyed()-----------");
    System.out.println(hse.getSession() + " "
        + new Date(hse.getSession().getLastAccessedTime()));
    System.out.println(hse.getSession() + " " + new Date());
  }
  public void attributeAdded(HttpSessionBindingEvent e) {
    System.out.println("-------------*start added*-----------------------"
        + sessions.size());
    HttpSession session = e.getSession();
    ActionContext ctx = ActionContext.getContext();
    boolean newOne = true;
    String attrName = e.getName();
    // 登录
    if (attrName.equals(Constant.USER_NAME)) {
      // 检查登录人数
      if (sessions.size() >= Constant.USER_LIMIT) {
        newOne = false;
        ctx.put("timeoutMSG", "serverBusy");
      }
      String nowUser = (String) e.getValue();
      // 遍历所有session,检查是否已经登录,若是则提示已经登录
      for (int i = sessions.size() - 1; i >= 0; i--) {
        SessionAndUser tem = sessions.get(i);
        if (tem.getUserName().equals(nowUser)) {
          newOne = false;
          ctx.put("timeoutMSG", "beenLoged");// tem.getSession().invalidate();//
                            // 同账号顶替登录,自动调用remove
          break;
        }
      }
      // 新登录帐号添加进账户维护列表
      if (newOne) {
        SessionAndUser sau = new SessionAndUser();
        sau.setUserName(nowUser);
        sau.setSession(session);
        sau.setSid(session.getId());
        sessions.add(sau);
      }
    }
  }
  public void attributeRemoved(HttpSessionBindingEvent e)
      throws IllegalStateException {
    HttpSession session = e.getSession();
    System.out
        .println("-------------*start Removed*-----------------------"
            + sessions.size());
    if (delS > -1) {
      if (flag) {
        sessions.remove(delS);
        flag = false;
      }
    } else {
      // 登录
      String attrName = e.getName();
      if (attrName.equals(Constant.USER_NAME)) {
        String nowUser = (String) e.getValue();
        // 遍历所有session
        for (int i = sessions.size() - 1; i >= 0; i--) {
          SessionAndUser tem = sessions.get(i);
          if (tem.getUserName().equals(nowUser)) {
            sessions.remove(i);
            break;
          }
        }
      }
    }
  }
  public void attributeReplaced(HttpSessionBindingEvent e) {
    HttpSession session = e.getSession();
    System.out
        .println("-------------*start replace*-----------------------"
            + sessions.size());
    String attrName = e.getName();
    delS = -1;
    // 登录
    if (attrName.equals(Constant.USER_NAME)) {
      // User nowUser = (User) e.getValue();//old value
      String nowUser = (String) session.getAttribute(Constant.USER_NAME);// 当前session中的user
      // 遍历所有session
      for (int i = sessions.size() - 1; i >= 0; i--) {
        SessionAndUser tem = sessions.get(i);
        if (tem.getUserName().equals(nowUser)
            && !tem.getSid().equals(session.getId())) {
          System.out.println("Remove:invalidate 1!");
          delS = i;
          flag = true;
        } else if (tem.getSid().equals(session.getId())) {
          tem.setUserName(nowUser);
        }
      }
      if (delS != -1) {
        sessions.get(delS).getSession().invalidate();// 失效时自动调用了remove方法。也就会把它从sessions中移除了
      }
    }
  }
}

代码主要思路是定义一个静态List<SessionAndUser>存放session和帐号名称。

登录的Action中获得监听器返回值并处理的代码

session.setAttribute(Constant.USER_NAME, operator.getUsername());
    ActionContext ctx = ActionContext.getContext();
    if("serverBusy".equals(ctx.get("timeoutMSG"))){
      ctx.put("timeoutMSG", "服务器繁忙,请稍后再试");
      return "jump";
    }
    if("beenLoged".equals(ctx.get("timeoutMSG"))){
      ctx.put("timeoutMSG", "此账户在别处登录");
      return "jump";
    }

页面捕获提示信息代码

<%@taglib prefix="s" uri="/struts-tags"%>
<s:property value="#attr.timeoutMSG" />

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多精彩内容其他人还在看

JavaWeb项目部署到服务器详细步骤详解

这篇文章主要介绍了JavaWeb项目如何部署到服务器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

IDEA基于支付宝小程序搭建springboot项目的详细步骤

这篇文章主要介绍了IDEA基于支付宝小程序搭建springboot项目的详细步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解SpringBoot应用服务启动与安全终止

这篇文章主要介绍了SpringBoot应用服务启动与安全终止,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Boot启动及退出加载项的方法

这篇文章主要介绍了Spring Boot启动及退出加载项的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Data Jpa 自动生成表结构的方法示例

这篇文章主要介绍了Spring Data Jpa 自动生成表结构的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

IDEA中osgi的开发应用指南详解

这篇文章主要介绍了IDEA中osgi的开发应用指南详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解用maven将dubbo工程打成jar包运行

这篇文章主要介绍了详解用maven将dubbo工程打成jar包运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解Java合并数组的两种实现方式

这篇文章主要介绍了Java合并数组的两种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

使用Jenkins Pipeline自动化构建发布Java项目的方法

这篇文章主要介绍了使用Jenkins Pipeline自动化构建发布Java项目的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

使用Maven配置Spring的方法步骤

这篇文章主要介绍了使用Maven配置Spring的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多