目录
2.4 EnterpriseCacheSessionDAO 类
3.1 SessionValidationScheduler接口
3.2 ExecutorServiceSessionValidationScheduler 类
1. 会话
当用户访问我们的应用时,为了方便,将用户的信息(不止是用户信息)保存起来,下次用户访问的时候,应用就能识别出用户。shiro也提供了会话机制,可以代替Web的会话机制,Session接口是会话的核心。
1.1 Session 接口、SimpleSession类
public interface Session {
Serializable getId();
Date getStartTimestamp();
Date getLastAccessTime();
long getTimeout() throws InvalidSessionException;
void setTimeout(long var1) throws InvalidSessionException;
String getHost();
void touch() throws InvalidSessionException;
void stop() throws InvalidSessionException;
Collection<Object> getAttributeKeys() throws InvalidSessionException;
Object getAttribute(Object var1) throws InvalidSessionException;
void setAttribute(Object var1, Object var2) throws InvalidSessionException;
Object removeAttribute(Object var1) throws InvalidSessionException;
}
可以看出会话可以保存的信息有:会话id,会话创建时间,最近一次访问会话的时间,会话超时时间,用户主机,键值对(用来存储一些额外自定义的数据的)。
Session接口的实现类有多个:SimpleSession(简单地实现了Session接口)
SimpleSession 简单的会话实现类,我们一般都用这个,当然还有其他的会话类。
public class SimpleSession implements ValidatingSession, Serializable {
protected static final long MILLIS_PER_SECOND = 1000L; //这是一秒的常量
protected static final long MILLIS_PER_MINUTE = 60000L; //一分钟的常量
protected static final long MILLIS_PER_HOUR = 3600000L; //一小时的常量
static int bitIndexCounter = 0;
private static final int ID_BIT_MASK;
private static final int START_TIMESTAMP_BIT_MASK;
private static final int STOP_TIMESTAMP_BIT_MASK;
private static final int LAST_ACCESS_TIME_BIT_MASK;
private static final int TIMEOUT_BIT_MASK;
private static final int EXPIRED_BIT_MASK;
private static final int HOST_BIT_MASK;
private static final int ATTRIBUTES_BIT_MASK;
private transient Serializable id; //会话ID,就是Sessionid
private transient Date startTimestamp; //会话开始时间
private transient Date stopTimestamp; //会话结束时间
private transient Date lastAccessTime; //上一次会话访问的时间
private transient long timeout; //会话过期时间
private transient boolean expired; //会话是否过期了
private transient String host; //用户主机
private transient Map<Object, Object> attributes; //会话的存储空间,可将用户的重要信息存进会话的attributes里面
public SimpleSession() {
this.timeout = 1800000L;//默认会话过期时间为30分钟
this.startTimestamp = new Date(); //会话开始时间就是创建会话的这一刻
this.lastAccessTime = this.startTimestamp;//初始化时,上一次会话访问时间是创建时间
}
public SimpleSession(String host) { //可以设置用户主机的构造方法
this();
this.host = host;
}
//省略了get、set方法
public void touch() { //访问了一次会话,更新“上一次访问时间”
this.lastAccessTime = new Date();
}
public void stop() { //停止会话,设置结束时间
if (this.stopTimestamp == null) {
this.stopTimestamp = new Date();
}
}
protected boolean isStopped() { //判断会话是否结束
return this.getStopTimestamp() != null;
}
protected void expire() { //让会话过期
this.stop();
this.expired = true;
}
public boolean isValid() { //判断会话是否有效,即判断是否过期或者结束
return !this.isStopped() && !this.isExpired();
}
protected boolean isTimedOut() { //判断会话是否超时
if (this.isExpired()) {
return true;
} else {
long timeout = this.getTimeout();
if (timeout >= 0L) {
Date lastAccessTime = this.getLastAccessTime();
if (lastAccessTime == null) {
String msg = "session.lastAccessTime for session with id [" + this.getId() + "] is null. This value must be set at least once, preferably at least upon instantiation. Please check the " + this.getClass().getName() + " implementation and ensure this value will be set (perhaps in the constructor?)";
throw new IllegalStateException(msg);
} else {
long expireTimeMillis = System.currentTimeMillis() - timeout;
Date expireTime = new Date(expireTimeMillis);
return lastAccessTime.before(expireTime);
}
} else {
if (log.isTraceEnabled()) {
log.trace("No timeout for session with id [" + this.getId() + "]. Session is not considered expired.");
}
return false;
}
}
}
public void validate() throws InvalidSessionException {//验证会话是否有效,无效则抛出异常
if (this.isStopped()) {
String msg = "Session with id [" + this.getId() + "] has been explicitly stopped. No further interaction under this session is allowed.";
throw new StoppedSessionException(msg);
} else if (this.isTimedOut()) {
this.expire();
Date lastAccessTime = this.getLastAccessTime();
long timeout = this.getTimeout();
Serializable sessionId = this.getId();
DateFormat df = DateFormat.getInstance();
String msg = "Session with id [" + sessionId + "] has expired. Last access time: " + df.format(lastAccessTime) + ". Current time: " + df.format(new Date()) + ". Session timeout is set to " + timeout / 1000L + " seconds (" + timeout / 60000L + " minutes)";
if (log.isTraceEnabled()) {
log.trace(msg);
}
throw new ExpiredSessionException(msg);
}
}
private Map<Object, Object> getAttributesLazy() {//获取Attributes
Map<Object, Object> attributes = this.getAttributes();
if (attributes == null) {
attributes = new HashMap();
this.setAttributes((Map)attributes);
}
return (Map)attributes;
}
//获取Attributes的key集合
public Collection<Object> getAttributeKeys() throws InvalidSessionException {
Map<Object, Object> attributes = this.getAttributes();
return attributes == null ? Collections.emptySet() : attributes.keySet();
}
public Object getAttribute(Object key) {//根据key找value
Map<Object, Object> attributes = this.getAttributes();
return attributes == null ? null : attributes.get(key);
}
public void setAttribute(Object key, Object value) { //添加A