本文主要介紹了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。這是我感覺不清楚的地方,功夫沒到家。
具體實現:
監聽器代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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中獲得監聽器返回值并處理的代碼
1
2
3
4
5
6
7
8
9
10
|
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" ; } |
頁面捕獲提示信息代碼
1
2
|
<% @taglib prefix= "s" uri= "/struts-tags" %> <s:property value= "#attr.timeoutMSG" /> |
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!