mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-09-23 12:33:48 +08:00
issue #69 添加Session的支持
This commit is contained in:
@@ -39,11 +39,9 @@ public interface InternalSession {
|
||||
void access();
|
||||
|
||||
/**
|
||||
* Set the <code>isNew</code> flag for this session.
|
||||
*
|
||||
* @param isNew The new value for the <code>isNew</code> flag
|
||||
* End the access.
|
||||
*/
|
||||
void setNew(boolean isNew);
|
||||
void endAccess();
|
||||
|
||||
/**
|
||||
* Set the creation time for this session. This method is called by the
|
||||
|
@@ -4,6 +4,7 @@ import me.chanjar.weixin.common.util.res.StringManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SessionImpl implements WxSession, InternalSession {
|
||||
|
||||
@@ -90,11 +91,6 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
*/
|
||||
protected volatile boolean isValid = false;
|
||||
|
||||
/**
|
||||
* Flag indicating whether this session is new or not.
|
||||
*/
|
||||
protected boolean isNew = false;
|
||||
|
||||
/**
|
||||
* We are currently processing a session expiration, so bypass
|
||||
* certain IllegalStateException tests. NOTE: This value is not
|
||||
@@ -123,11 +119,6 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
*/
|
||||
protected volatile long thisAccessedTime = creationTime;
|
||||
|
||||
/**
|
||||
* The last accessed time for this Session.
|
||||
*/
|
||||
protected volatile long lastAccessedTime = creationTime;
|
||||
|
||||
/**
|
||||
* The default maximum inactive interval for Sessions created by
|
||||
* this Manager.
|
||||
@@ -140,9 +131,15 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
*/
|
||||
protected transient InternalSessionFacade facade = null;
|
||||
|
||||
/**
|
||||
* The access count for this session.
|
||||
*/
|
||||
protected transient AtomicInteger accessCount = null;
|
||||
|
||||
|
||||
public SessionImpl(InternalSessionManager manager) {
|
||||
this.manager = manager;
|
||||
this.accessCount = new AtomicInteger();
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +173,28 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return isValid;
|
||||
if (!this.isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.expiring) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (accessCount.get() > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (maxInactiveInterval > 0) {
|
||||
long timeNow = System.currentTimeMillis();
|
||||
int timeIdle;
|
||||
timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
|
||||
if (timeIdle >= maxInactiveInterval) {
|
||||
expire();
|
||||
}
|
||||
}
|
||||
|
||||
return this.isValid;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,6 +233,8 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
// Mark this session as "being expired"
|
||||
expiring = true;
|
||||
|
||||
accessCount.set(0);
|
||||
|
||||
// Remove this session from our manager's active sessions
|
||||
manager.remove(this, true);
|
||||
|
||||
@@ -238,23 +258,23 @@ public class SessionImpl implements WxSession, InternalSession {
|
||||
public void access() {
|
||||
|
||||
this.thisAccessedTime = System.currentTimeMillis();
|
||||
accessCount.incrementAndGet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setNew(boolean isNew) {
|
||||
public void endAccess() {
|
||||
|
||||
this.isNew = isNew;
|
||||
this.thisAccessedTime = System.currentTimeMillis();
|
||||
accessCount.decrementAndGet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setCreationTime(long time) {
|
||||
|
||||
this.creationTime = time;
|
||||
this.lastAccessedTime = time;
|
||||
this.thisAccessedTime = time;
|
||||
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class SessionManagerImpl implements WxSessionManager, InternalSessionManager {
|
||||
|
||||
@@ -104,6 +105,11 @@ public class SessionManagerImpl implements WxSessionManager, InternalSessionMana
|
||||
*/
|
||||
protected int processExpiresFrequency = 6;
|
||||
|
||||
/**
|
||||
* 后台清理线程是否已经开启
|
||||
*/
|
||||
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public void remove(InternalSession session) {
|
||||
remove(session, false);
|
||||
@@ -155,7 +161,6 @@ public class SessionManagerImpl implements WxSessionManager, InternalSessionMana
|
||||
InternalSession session = createEmptySession();
|
||||
|
||||
// Initialize the properties of the new session and return it
|
||||
session.setNew(true);
|
||||
session.setValid(true);
|
||||
session.setCreationTime(System.currentTimeMillis());
|
||||
session.setMaxInactiveInterval(this.maxInactiveInterval);
|
||||
@@ -191,6 +196,26 @@ public class SessionManagerImpl implements WxSessionManager, InternalSessionMana
|
||||
@Override
|
||||
public void add(InternalSession session) {
|
||||
|
||||
// 当第一次有session创建的时候,开启session清理线程
|
||||
if (!backgroundProcessStarted.getAndSet(true)) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
// 每秒清理一次
|
||||
Thread.sleep(1000l);
|
||||
backgroundProcess();
|
||||
} catch (InterruptedException e) {
|
||||
log.error("SessionManagerImpl.backgroundProcess error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
|
||||
sessions.put(session.getIdInternal(), session);
|
||||
int size = getActiveSessions();
|
||||
if( size > maxActive ) {
|
||||
|
@@ -2,9 +2,19 @@ package me.chanjar.weixin.common.session;
|
||||
|
||||
public interface WxSessionManager {
|
||||
|
||||
|
||||
/**
|
||||
* 获取某个sessionId对应的session,如果sessionId没有对应的session,则新建一个并返回。
|
||||
* @param sessionId
|
||||
* @return
|
||||
*/
|
||||
public WxSession getSession(String sessionId);
|
||||
|
||||
/**
|
||||
* 获取某个sessionId对应的session,如果sessionId没有对应的session,若create为true则新建一个,否则返回null。
|
||||
* @param sessionId
|
||||
* @param create
|
||||
* @return
|
||||
*/
|
||||
public WxSession getSession(String sessionId, boolean create);
|
||||
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package me.chanjar.weixin.common.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -21,8 +22,16 @@ public class WxMsgIdMemoryDuplicateChecker implements WxMsgIdDuplicateChecker {
|
||||
*/
|
||||
private final Long clearPeriod;
|
||||
|
||||
/**
|
||||
* 消息id->消息时间戳的map
|
||||
*/
|
||||
private final ConcurrentHashMap<Long, Long> msgId2Timestamp = new ConcurrentHashMap<Long, Long>();
|
||||
|
||||
/**
|
||||
* 后台清理线程是否已经开启
|
||||
*/
|
||||
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* WxMsgIdInMemoryDuplicateChecker构造函数
|
||||
* <pre>
|
||||
@@ -33,7 +42,6 @@ public class WxMsgIdMemoryDuplicateChecker implements WxMsgIdDuplicateChecker {
|
||||
public WxMsgIdMemoryDuplicateChecker() {
|
||||
this.timeToLive = 15 * 1000l;
|
||||
this.clearPeriod = 5 * 1000l;
|
||||
this.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,10 +52,12 @@ public class WxMsgIdMemoryDuplicateChecker implements WxMsgIdDuplicateChecker {
|
||||
public WxMsgIdMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
|
||||
this.timeToLive = timeToLive;
|
||||
this.clearPeriod = clearPeriod;
|
||||
this.start();
|
||||
}
|
||||
|
||||
private void start() {
|
||||
protected void checkBackgroundProcessStarted() {
|
||||
if (backgroundProcessStarted.getAndSet(true)) {
|
||||
return;
|
||||
}
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -72,6 +82,7 @@ public class WxMsgIdMemoryDuplicateChecker implements WxMsgIdDuplicateChecker {
|
||||
|
||||
@Override
|
||||
public boolean isDuplicate(Long wxMsgId) {
|
||||
checkBackgroundProcessStarted();
|
||||
Long timestamp = msgId2Timestamp.putIfAbsent(wxMsgId, System.currentTimeMillis());
|
||||
if (timestamp == null) {
|
||||
// 第一次接收到这个消息
|
||||
|
Reference in New Issue
Block a user