亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaWeb實(shí)現(xiàn)同一帳號(hào)同一時(shí)間只能一個(gè)地點(diǎn)登陸(類似QQ登錄的功能)

 更新時(shí)間:2016年11月07日 10:54:53   作者:l284849736  
最近做了企業(yè)項(xiàng)目,其中有這樣的需求要求同一帳號(hào)同一時(shí)間只能一個(gè)地點(diǎn)登陸類似QQ登錄的功能。下面小編通過本文給大家分享實(shí)現(xiàn)思路,感興趣的朋友參考下吧

JavaWeb實(shí)現(xiàn)同一帳號(hào)同一時(shí)間只能一個(gè)地點(diǎn)登陸(類似QQ登錄的功能)的實(shí)現(xiàn)思路如下所示:

一、該功能有什么作用

大家想想吧。反正總會(huì)有這樣的需求的。這年頭什么需求不會(huì)有。。呵呵。有時(shí)候也不一定是需求,很有可能為了安全也會(huì)這么做。例如考試系統(tǒng),在線聊天系統(tǒng),很有必要做成這樣的吧。

二、實(shí)現(xiàn)過程

a.問題分析

    在系統(tǒng)中,我們一般都是把登錄信息綁定到session中,看來從這入手是可能找到解決辦法。說白了,也就是當(dāng)用戶登錄時(shí),判斷一下這個(gè)用戶有沒有登錄,如果登錄了,就把以前的那個(gè)session清除掉就OK了。??此坪芎?jiǎn)單是不?其實(shí)你細(xì)想你會(huì)發(fā)現(xiàn)有以下問題:如何得到之前這個(gè)用戶有沒有登錄過,也就是如何訪問到所有登錄的session信息呢?

b.具體實(shí)現(xiàn)

   大家知道,在j2ee api好像是沒有具體的方法直接得到所有session信息的。但是我們可以通過配制監(jiān)聽器,監(jiān)控所有的session創(chuàng)建和消毀過程,以及可以監(jiān)控session中的屬性的創(chuàng)建,刪除和替換過程。

其實(shí)我們只要做以下處理即可:

在保存用戶登錄信息到session時(shí),對(duì)應(yīng)的也就是session一個(gè)屬性的創(chuàng)建過程(attributeAdded),可以把當(dāng)前這個(gè)session記錄到一個(gè)ArrayList中。

其實(shí)在保存到list中時(shí)你要首先遍歷一下這個(gè)list中有沒有已經(jīng)存在該用戶的登錄信息。如果存在就消毀掉這個(gè)list中存在的session信息,并且從list中移除,不存在就把該session信息放到list中。

在session的登錄信息消毀時(shí),直接把該sesseion從list中移除掉。

還有就是當(dāng)用戶登錄后沒有退出直接登錄這個(gè)時(shí)候是一個(gè)session屬性的替換過程。也要做處理判斷新的用戶是否已經(jīng)在除了當(dāng)前session的其它session中是否存在。存在則刪除。

具體代碼如下:

package com.weirhp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class RecordSessionListener implements HttpSessionAttributeListener,
HttpSessionListener {
private static List<SessionAndUser> sessions;
public static String loginFlag = "loginUser";
static {
if (sessions == null) {
sessions = Collections.synchronizedList(new ArrayList<SessionAndUser>());
}
}
public void attributeAdded(HttpSessionBindingEvent e) {
HttpSession session = e.getSession();
System.out.println("-------------*start added*-----------------------");
String attrName = e.getName();
// 登錄
if (attrName.equals(loginFlag)) {
User nowUser = (User) e.getValue();
User sUser = (User)session.getAttribute(loginFlag);
// 遍歷所有session
for (int i = sessions.size()-1; i >= 0; i--) {
SessionAndUser tem = sessions.get(i);
if (tem.getUserID().equals(nowUser.getName())) {
tem.getSession().invalidate();//自動(dòng)調(diào)用remove
break;
}
}
SessionAndUser sau = new SessionAndUser();
sau.setUserID(nowUser.getName());
sau.setSession(session);
sau.setSid(session.getId());
sessions.add(sau);
}
}
public void attributeRemoved(HttpSessionBindingEvent e) {
HttpSession session = e.getSession();
System.out.println("-------------*start Removed*-----------------------");
String attrName = e.getName();
// 登錄
if (attrName.equals(loginFlag)) {
User nowUser = (User) e.getValue();
// 遍歷所有session
for (int i = sessions.size()-1; i >= 0; i--) {
SessionAndUser tem = sessions.get(i);
if (tem.getUserID().equals(nowUser.getName())) {
sessions.remove(i);
break;
}
}
}
}
public void attributeReplaced(HttpSessionBindingEvent e) {
HttpSession session = e.getSession();
System.out.println("-------------*start replace*-----------------------");
String attrName = e.getName();
int delS=-1;
// 登錄
if (attrName.equals(loginFlag)) {
// User nowUser = (User) e.getValue();//old value
User nowUser = (User)session.getAttribute(loginFlag);//當(dāng)前session中的user
// 遍歷所有session
for (int i = sessions.size()-1; i >= 0; i--) {
SessionAndUser tem = sessions.get(i);
if (tem.getUserID().equals(nowUser.getName())&&!tem.getSid().equals(session.getId())) {
System.out.println("Remove:invalidate 1!");
delS=i;
}else if(tem.getSid().equals(session.getId())){
tem.setUserID(nowUser.getName());
}
}
if (delS!=-1) {
sessions.get(delS).getSession().invalidate();//失效時(shí)自動(dòng)調(diào)用了remove方法。也就會(huì)把它從sessions中移除了
}
}
}
public void sessionCreated(HttpSessionEvent e) {
}
public void sessionDestroyed(HttpSessionEvent e) {
}
}

在web.xml中的配制

<listener>
<display-name>recordSession</display-name>
<listener-class>com.weirhp.RecordSessionListener</listener-class>
</listener>

三、可能存在的問題

整個(gè)個(gè)程序可能有的點(diǎn)沒有想到。可能存在一些bug,用于具體項(xiàng)目需謹(jǐn)慎,歡迎大家拍磚,也希望給點(diǎn)建議。我再改進(jìn)。

四、后來的一些思考

  如果兩臺(tái)機(jī)器使用同一帳號(hào)在同一時(shí)刻登錄系統(tǒng),是不是兩個(gè)帳號(hào)都可以登錄成功呢。。(還有就是這個(gè)session List很大時(shí),在遍歷的時(shí)間段中兩臺(tái)機(jī)器使用同一帳號(hào)在同一時(shí)刻登錄系統(tǒng)也可能會(huì)成功登錄的)。很是糾結(jié)。。應(yīng)該怎么控制呢?

(解決辦法:經(jīng)測(cè)試Listener在系統(tǒng)中是一個(gè)單例,在它的方法上加上synchronize關(guān)鍵字就可以保證list的線程安全了。)

以上所述是小編給大家介紹的JavaWeb實(shí)現(xiàn)同一帳號(hào)同一時(shí)間只能一個(gè)地點(diǎn)登陸(類似QQ登錄的功能),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • java IO實(shí)現(xiàn)電腦搜索、刪除功能的實(shí)例

    java IO實(shí)現(xiàn)電腦搜索、刪除功能的實(shí)例

    下面小編就為大家?guī)硪黄猨ava IO實(shí)現(xiàn)電腦搜索、刪除功能的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    這篇文章主要介紹了Java中easypoi導(dǎo)入excel文件列名相同的處理方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Spring整合Dubbo框架過程及原理解析

    Spring整合Dubbo框架過程及原理解析

    這篇文章主要介紹了Spring整合Dubbo框架過程及原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java經(jīng)典設(shè)計(jì)模式之模板方法模式定義與用法示例

    Java經(jīng)典設(shè)計(jì)模式之模板方法模式定義與用法示例

    這篇文章主要介紹了Java經(jīng)典設(shè)計(jì)模式之模板方法模式,簡(jiǎn)單說明了模板方法模式的原理、定義,并結(jié)合實(shí)例形式分析了java模板方法模式的具體使用方法,需要的朋友可以參考下
    2017-08-08
  • 攔截Druid數(shù)據(jù)源自動(dòng)注入帳密解密實(shí)現(xiàn)詳解

    攔截Druid數(shù)據(jù)源自動(dòng)注入帳密解密實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了攔截Druid數(shù)據(jù)源自動(dòng)注入帳密解密實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 一文帶你搞懂什么是BIO

    一文帶你搞懂什么是BIO

    BIO英文全名是 blocking IO,也叫做 阻塞IO,是最容易理解、最容易實(shí)現(xiàn)的IO工作方式,本文就來通過一些簡(jiǎn)單的示例為大家講講什么是BIO吧
    2023-06-06
  • java開發(fā)RocketMQ生產(chǎn)者高可用示例詳解

    java開發(fā)RocketMQ生產(chǎn)者高可用示例詳解

    這篇文章主要為大家介紹了java開發(fā)RocketMQ生產(chǎn)者高可用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Spring?Data?JPA框架的核心概念與Repository接口詳解

    Spring?Data?JPA框架的核心概念與Repository接口詳解

    Spring?Data?JPA是Spring基于JPA規(guī)范的基礎(chǔ)上封裝的?套?JPA?應(yīng)?框架,可使開發(fā)者?極簡(jiǎn)的代碼即可實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的訪問和操作,本篇我們來了解Spring?Data?JPA框架的核心概念與Repository接口
    2022-04-04
  • 一文搞懂Spring中的注解與反射

    一文搞懂Spring中的注解與反射

    這篇文章主要為大家介紹了Spring中的注解與反射的原理與實(shí)現(xiàn),文中的示例代碼講解詳細(xì),對(duì)我們了解Spring有一定的幫助,需要的可以參考一下
    2022-06-06
  • Java基于二維數(shù)組實(shí)現(xiàn)的數(shù)獨(dú)問題示例

    Java基于二維數(shù)組實(shí)現(xiàn)的數(shù)獨(dú)問題示例

    這篇文章主要介紹了Java基于二維數(shù)組實(shí)現(xiàn)的數(shù)獨(dú)問題,涉及java針對(duì)數(shù)組的遍歷、計(jì)算、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01

最新評(píng)論