这一块叫做简易的Session管理,因为集成原因被推到后期,方案就白做了,就来发挥点光和热给我可怜的博客添点料吧。
其实之前主要想用想用HttpSessionBindingListener,后来发现它必须添加进Session中才能起作用,所以就放弃了,具体可以参考这篇http://www.cnblogs.com/shencheng/archive/2011/01/07/1930227.html
官方手册https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSession.html
现在有这样一个需求:
1. Admin可以改任意用户的密码。
2. 被更改的用户需要重新登录。
那么使用监听器来监听所有的session无疑是最容易想到的方案之一。因而选用了无敌的HttpSessionListener,可以在session被创建和销毁的时候获取值,从而方便我们操作。
Step 1: Web.xml
这里是配置监听的实现类。
<listener>
<listener-class>*.SessionManagement</listener-class>
</listener>
Step 2: SessionMangement.java
这里我就破坏了设计模式,其实用Interface来继承HttpSessionListener也是可以的
比如:
public interface SessionManagementInterface extends HttpSessionListener
当然也可以在实现类中实现:
public class SessionManagement implements HttpSessionListener
那么实现思路是怎样?做个List来记录创建和销毁的session,而在session需要改变的地方去更新记录了的session状态。
@Override public void sessionCreated (HttpSessionEvent event){ HttpSession session = event.getSession(); addLoginSessions(session); } @Override public void sessionDestroyed(HttpSessionEvent event){ HttpSession session = event.getSession(); removeLoginSessions(session); }
这样子我们就记录了Session的改变,并且做了对应的操作。
而在实际案例中,这样远远不够,因为客户端会产生大量无效的session和与我们相悖的session。那么如何甄别有效的session就是addLoginSessions需要考虑的问题。
在本案例中,session被先创建,而后登陆信息被记录在attribute中,按照上面的方法,其实我们会错过正确的session。该怎么办?
还好,HttpSessionAttributeListener为Attribute的改变提供了解决方案。
同时监听器,实现方法与HttpSessionListener类似,我们需要重写三个方法:
@Override public void attributeAdded(HttpSessionBindingEvent event){ } @Override public void attributeRemoved(HttpSessionBindingEvent event){ } @Override public void attributeReplaced(HttpSessionBindingEvent event) { }
在这三个对应的需要的方法里,实现我们的操作就可以了。
是不是很简单,其实就是两步:配置对应的web.xml和实现对应的接口即可。
下面就是我实现的一个方案,当然略去了很多细节,给大家做个参考吧。
好了上代码。
public class SessionManagementImpl implements SessionManagement , HttpSessionAttributeListener{
private static final Map<String, Map<String, HttpSession>> loginSessions = new HashMap<String, Map<String, HttpSession>>();
private static final Map<String, String> reverseKeyLoginSessions = new HashMap<String, String>();
@Override
public void attributeAdded(HttpSessionBindingEvent event){
HttpSession httpSession = event.getSession();
Object attr = httpSession.getAttribute("UserInfo");
if (attr != null && (attr instanceof Info)) {
Info Info = (Info) attr;
if (Info.getUser() != null) {
updatedLoginSessions(Info, httpSession);
}
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event){
HttpSession httpSession = event.getSession();
if (reverseKeyLoginSessions.containsKey(httpSession.getId())) {
Object attr = httpSession.getAttribute("UserInfo");
if (attr != null && (attr instanceof Info)) {
Info Info = (Info) attr;
if (Info.getUser() != null) {
updatedLoginSessions(Info, httpSession);
}else {
removeLoginSessions(httpSession);
}
}
else {
removeLoginSessions(httpSession);
}
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) { }
@Override
public boolean isLoginSessionIdExist(String currentKey, HttpSession httpSession){
if (loginSessions.containsKey(currentKey)){
if (loginSessions.get(currentKey).containsKey(httpSession.getId())){
return true;
}else {
return false;
}
}
else{
return false;
}
}
@Override
public void addLoginSessions(final HttpSession session){
Object attr = session.getAttribute("UserInfo");
if (attr != null && (attr instanceof Info)) {
Info Info = (Info) attr;
if (Info.getUser() != null) {
if (isLoginSessionIdExist(Info.getSessionId(), session)) {
updatedLoginSessions(Info, session);
} else {
if (loginSessions.containsKey(Info.getSessionId())) {
loginSessions.get(Info.getSessionId()).put(session.getId(), session);
reverseKeyLoginSessions.put(session.getId(), Info.getSessionId());
} else {
loginSessions.put(Info.getSessionId(), new HashMap<String, HttpSession>() {{
put(session.getId(), session);
}});
reverseKeyLoginSessions.put(session.getId(), Info.getSessionId());
}
}
}
}
}
@Override
public void updatedLoginSessions(Info Info, HttpSession session){
if (isLoginSessionIdExist(Info.getSessionId(), session)){
loginSessions.get(Info.getSessionId()).remove(session.getId());
loginSessions.get(Info.getSessionId()).put(session.getId(),session);
reverseKeyLoginSessions.remove(session.getId());
reverseKeyLoginSessions.put(session.getId(), Info.getSessionId());
}
else {
addLoginSessions(session);
}
}
@Override
public void invalidLoginSessions(User User){
if (User != null) {
if (loginSessions.containsKey(User.getName())) {
for (HttpSession httpSession : loginSessions.get(User.getName()).values()){
httpSession.invalidate();
}
}
}
}
@Override
public void removeLoginSessions(HttpSession session){
if (reverseKeyLoginSessions.containsKey(session.getId())){
loginSessions.get(reverseKeyLoginSessions.get(session.getId()).toString()).remove(session.getId());
if (loginSessions.get(reverseKeyLoginSessions.get(session.getId()).toString()).isEmpty()){
loginSessions.remove(reverseKeyLoginSessions.get(session.getId()));
}
reverseKeyLoginSessions.remove(session.getId());
}
}
@Override
public void sessionCreated(HttpSessionEvent event){
HttpSession session = event.getSession();
addLoginSessions(session);
}
@Override
public void sessionDestroyed(HttpSessionEvent event){
HttpSession session = event.getSession();
removeLoginSessions(session);
}
}