View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2013-9-22 下午05:14:19
4    */
5   package gboat2.base.plugin.servlet.listener;
6   
7   import gboat2.base.bridge.model.UserSession;
8   
9   import java.util.Map;
10  import java.util.concurrent.ConcurrentHashMap;
11  
12  import javax.servlet.http.HttpSession;
13  import javax.servlet.http.HttpSessionAttributeListener;
14  import javax.servlet.http.HttpSessionBindingEvent;
15  import javax.servlet.http.HttpSessionEvent;
16  import javax.servlet.http.HttpSessionListener;
17  
18  import org.apache.commons.lang3.StringUtils;
19  
20  /**
21   * 监听session,限制一个用户在某个时刻只能在一个客户端登陆。<br>
22   * 如果同时有多个客户端登陆,其他除了最后一次登陆的所有登陆客户端会自动退出。
23   * <pre><code>
24   * 在 web.xml 中配置该监听器:
25   *    &lt;listener&gt;
26   *        &lt;listener-class&gt;gboat2.base.plugin.servlet.listener.SessionListener&lt;/listener-class&gt;
27   *    &lt;/listener&gt;
28   * </code></pre>
29   * @date 2013-9-22
30   * @author <a href="mailto:[email protected]">何明旺</a>
31   * @since 1.0
32   */
33  public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
34  
35  	/** 保存已登录的用户信息的 Map,key 为登录名, value 为其对应的 session 对象 */
36  	private Map<String, HttpSession> loginedUsers = new ConcurrentHashMap<String, HttpSession>();
37  
38  	@Override
39  	public void sessionCreated(HttpSessionEvent se) {
40  		//System.out.println(se);
41  	}
42  
43  	@Override
44  	public void sessionDestroyed(HttpSessionEvent se) {
45  		Object userSession = se.getSession().getAttribute(UserSession.USER_SESSION_KEY);
46  		if(userSession instanceof UserSession) {
47  		    loginedUsers.remove(((UserSession)userSession).getLoginId());
48  		}
49  	}
50  
51  	@Override
52  	public void attributeAdded(HttpSessionBindingEvent se) {
53  		if (UserSession.USER_SESSION_KEY.equals(se.getName())) {
54  			userLoginIdBinding2HttpSession(se.getSession(), (UserSession) se.getValue());
55  		}
56  	}
57  
58  	@Override
59  	public void attributeRemoved(HttpSessionBindingEvent se) {
60  		//注销有两种方式,一种是:request.getSession().removeAttribute(UserSession.USER_SESSION_KEY);
61  		//一种是request.getSession().invalidate();
62  		if (UserSession.USER_SESSION_KEY.equals(se.getName())) {
63  			sessionDestroyed(se);
64  		}
65  	}
66  
67  	@Override
68  	public void attributeReplaced(HttpSessionBindingEvent se) {
69  		attributeAdded(se);
70  	}
71  
72  	/**
73  	 * 检查是否为例外账号
74  	 * @param userSession
75  	 * @return
76  	 */
77  	private boolean excludeUser(UserSession userSession) {
78  		if ("super".equals(userSession.getLoginId())) {
79  			return true;
80  		}
81  
82  		// 测试账号,不对客户端进行限制
83  		if (null != userSession.getUserNameEn() && userSession.getUserNameEn().endsWith("@glodon")) {
84  			return true;
85  		}
86  
87  		return false;
88  	}
89  
90  	private void userLoginIdBinding2HttpSession(HttpSession session, UserSession userSession) {
91  		if (null == userSession || StringUtils.isEmpty(userSession.getLoginId())) {
92  			return;
93  		}
94  
95  		//测试账号,不对客户端进行限制
96  		if (excludeUser(userSession)) {
97  			return;
98  		}
99  
100         synchronized (loginedUsers) {
101             if (loginedUsers.containsKey(userSession.getLoginId())) {
102                 HttpSession oldSession = loginedUsers.remove(userSession.getLoginId());
103                 if (null != oldSession && oldSession != session) {
104                     oldSession.invalidate(); // 注销掉以前的session
105                 }
106             }
107             loginedUsers.put(userSession.getLoginId(), session); // 绑定新的session
108         }
109 	}
110 }