新增会话定时清理

This commit is contained in:
RuoYi 2018-02-25 23:42:32 +08:00
parent 623c70d6fc
commit bfaf973e54
21 changed files with 565 additions and 39 deletions

View File

@ -268,8 +268,8 @@ create table sys_user_online (
primary key (sessionId)
) engine=innodb default charset=utf8;
insert into sys_user_online(sessionId, login_name, dept_name, login_name, ipaddr, browser, os, status)
values('c3b252c3-2229-4be4-a5f7-7aba4b0c314c', 'admin', '开发部', '管理员', '127.0.0.1', 'Chrome 45', 'Windows 7');
insert into sys_user_online(sessionId, login_name, dept_name, role_name, ipaddr, browser, os, status)
values('c3b252c3-2229-4be4-a5f7-7aba4b0c314c', 'admin', '开发部', '管理员', '127.0.0.1', 'Chrome 45', 'Windows 7', 'on_line');
-- 用户部门表
SELECT * FROM sys_dept;

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.tools;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTools
{
public static final String DEFAULT_YYYYMMDD = "yyyyMMddHHmmss";
public static final String DEFAULT_YYYY_MM_DD = "yyyy-MM-dd HH:mm:ss";
public static final String dateTimeStr()
{
return dateTimeNow(DEFAULT_YYYY_MM_DD);
}
public static final String dateTimeNow()
{
return dateTimeNow(DEFAULT_YYYYMMDD);
}
public static final String dateTimeNow(final String format)
{
return dateTime(format, new Date());
}
public static final String dateTime(final Date date)
{
return dateTime(DEFAULT_YYYYMMDD, date);
}
public static final String dateTime(final String format, final Date date)
{
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts)
{
try
{
return new SimpleDateFormat(format).parse(ts);
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
}

View File

@ -23,6 +23,7 @@ import java.sql.SQLException;
public class DruidDBConfig
{
private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);
@Value("${spring.datasource.url}")
private String dbUrl;

View File

@ -4,6 +4,7 @@ import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@ -16,6 +17,7 @@ import org.springframework.web.servlet.i18n.SessionLocaleResolver;
* @author yangzz
*/
@Configuration
@Component
public class I18nConfig extends WebMvcConfigurerAdapter
{

View File

@ -2,29 +2,27 @@ package com.ruoyi.framework.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.shiro.realm.UserRealm;
import com.ruoyi.project.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.shiro.session.OnlineSessionFactory;
import com.ruoyi.project.shiro.web.OnlineSessionFilter;
import com.ruoyi.project.shiro.web.sync.SyncOnlineSessionFilter;
import com.ruoyi.project.shiro.web.filter.online.OnlineSessionFilter;
import com.ruoyi.project.shiro.web.filter.sync.SyncOnlineSessionFilter;
import com.ruoyi.project.shiro.web.session.OnlineWebSessionManager;
import com.ruoyi.project.shiro.web.session.SpringSessionValidationScheduler;
import com.ruoyi.project.system.menu.service.MenuServiceImpl;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@ -39,6 +37,18 @@ public class ShiroConfig
{
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
// Session超时时间单位为毫秒默认30分钟
@Value("${shiro.session.expireTime}")
private String expireTime;
// 同步session到数据库的周期 单位为毫秒默认1分钟
@Value("${shiro.session.dbSyncPeriod}")
private String dbSyncPeriod;
// 相隔多久检查一次session的有效性单位毫秒默认就是30分钟
@Value("${shiro.session.validationInterval}")
private String validationInterval;
/**
* 缓存管理器 使用Ehcache实现
*/
@ -75,24 +85,68 @@ public class ShiroConfig
* 自定义sessionFactory会话
*/
@Bean
SessionFactory sessionFactory()
OnlineSessionFactory sessionFactory()
{
OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
return sessionFactory;
}
/**
* 自定义sessionFactory调度器
*/
@Bean
SpringSessionValidationScheduler sessionValidationScheduler()
{
SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler();
// 相隔多久检查一次session的有效性单位毫秒默认就是60分钟
sessionValidationScheduler.setSessionValidationInterval(60 * 60 * 1000);
// 设置会话验证调度器进行会话验证时的会话管理器
sessionValidationScheduler.setSessionManager(sessionValidationManager());
return sessionValidationScheduler;
}
/**
* 会话管理器
*/
@Bean
public DefaultWebSessionManager configWebSessionManager()
public OnlineWebSessionManager sessionValidationManager()
{
DefaultWebSessionManager manager = new DefaultWebSessionManager();
manager.setCacheManager(getEhCacheManager());// 加入缓存管理器
manager.setSessionDAO(sessionDAO());// 设置SessionDao
manager.setDeleteInvalidSessions(true);// 删除过期的session
manager.setGlobalSessionTimeout(sessionDAO().getExpireTime());// 设置全局session超时时间
manager.setSessionValidationSchedulerEnabled(true);// 是否定时检查session
OnlineWebSessionManager manager = new OnlineWebSessionManager();
// 加入缓存管理器
manager.setCacheManager(getEhCacheManager());
// 删除过期的session
manager.setDeleteInvalidSessions(true);
// 设置全局session超时时间
manager.setGlobalSessionTimeout(sessionDAO().getExpireTime());
// 是否定时检查session
manager.setSessionValidationSchedulerEnabled(true);
// 自定义SessionDao
manager.setSessionDAO(sessionDAO());
// 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
return manager;
}
/**
* 会话管理器
*/
@Bean
public OnlineWebSessionManager sessionManager()
{
OnlineWebSessionManager manager = new OnlineWebSessionManager();
// 加入缓存管理器
manager.setCacheManager(getEhCacheManager());
// 删除过期的session
manager.setDeleteInvalidSessions(true);
// 设置全局session超时时间
manager.setGlobalSessionTimeout(sessionDAO().getExpireTime());
// 定义要使用的无效的Session定时调度器
manager.setSessionValidationScheduler(sessionValidationScheduler());
// 是否定时检查session
manager.setSessionValidationSchedulerEnabled(true);
// 自定义SessionDao
manager.setSessionDAO(sessionDAO());
// 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
return manager;
}
@ -109,7 +163,7 @@ public class ShiroConfig
// 注入缓存管理器;
securityManager.setCacheManager(getEhCacheManager());
// session管理器
securityManager.setSessionManager(configWebSessionManager());
securityManager.setSessionManager(sessionManager());
return securityManager;
}

View File

@ -47,8 +47,4 @@ public interface ShiroConstants
*/
public String ONLINE_SESSION = "online_session";
/**
* 仅清空本地缓存 不情况数据库的
*/
public String ONLY_CLEAR_CACHE = "online_session_only_clear_cache";
}

View File

@ -14,13 +14,15 @@ import com.ruoyi.project.util.HttpContextUtils;
/**
* 针对自定义的ShiroSession的db操作
*
* @author yangzz
*/
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
{
/**
* Session超时时间单位为毫秒默认3分钟
* Session超时时间单位为毫秒默认30分钟
*/
private long expireTime = 3 * 60 * 1000;
private long expireTime = 30 * 60 * 1000;
/**
* 同步session到数据库的周期 单位为毫秒默认1分钟
@ -58,14 +60,7 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
@Override
protected Session doReadSession(Serializable sessionId)
{
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
String uri = request.getServletPath();
// 如果是静态文件则不更新SESSION
if (checkStaticLink(uri))
{
return null;
}
System.out.println("==============doReadSession url=================" + uri);
System.out.println("==============doReadSession url=================");
UserOnline userOnline = onlineService.selectByOnlineId(String.valueOf(sessionId));
if (userOnline == null)
{
@ -156,6 +151,11 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
{
linkFlag = true;
}
// 如果是登录请求则不更新SESSION
if (StringUtils.endsWithAny(uri, new String[] { "/" }))
{
linkFlag = true;
}
// 如果是静态文件则不更新SESSION
if (StringUtils.startsWith(uri, "/css") && StringUtils.endsWith(uri, ".css")
|| StringUtils.startsWith(uri, "/js") && StringUtils.endsWith(uri, ".js")

View File

@ -6,17 +6,29 @@ import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.web.session.mgt.WebSessionContext;
import org.springframework.stereotype.Component;
import com.ruoyi.common.tools.StringTools;
import com.ruoyi.project.shiro.common.utils.IpUtils;
import com.ruoyi.project.system.online.domain.OnlineSession;
import com.ruoyi.project.system.online.domain.UserOnline;
import com.ruoyi.project.util.HttpContextUtils;
import eu.bitwalker.useragentutils.UserAgent;
/**
* 自定义sessionFactory会话
*
* @author yangzz
*/
@Component
public class OnlineSessionFactory implements SessionFactory
{
public Session createSession(UserOnline userOnline)
{
OnlineSession onlineSession = userOnline.getSession();
if (StringTools.isNotNull(onlineSession) && onlineSession.getId() == null)
{
onlineSession.setId(userOnline.getSessionId());
}
return userOnline.getSession();
}
@ -30,7 +42,8 @@ public class OnlineSessionFactory implements SessionFactory
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
if (request != null)
{
UserAgent userAgent = UserAgent.parseUserAgentString(HttpContextUtils.getHttpServletRequest().getHeader("User-Agent"));
UserAgent userAgent = UserAgent
.parseUserAgentString(HttpContextUtils.getHttpServletRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器

View File

@ -1,4 +1,4 @@
package com.ruoyi.project.shiro.web;
package com.ruoyi.project.shiro.web.filter.online;
import java.io.IOException;
import javax.servlet.ServletRequest;
@ -14,6 +14,7 @@ import com.ruoyi.project.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.system.online.domain.OnlineSession;
import com.ruoyi.project.system.user.domain.User;
public class OnlineSessionFilter extends AccessControlFilter
{
@ -86,6 +87,7 @@ public class OnlineSessionFilter extends AccessControlFilter
}
// 跳转到登录页
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
{
String loginUrl = getForceLogoutUrl();

View File

@ -1,4 +1,4 @@
package com.ruoyi.project.shiro.web.sync;
package com.ruoyi.project.shiro.web.filter.sync;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -8,6 +8,11 @@ import com.ruoyi.project.shiro.ShiroConstants;
import com.ruoyi.project.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.system.online.domain.OnlineSession;
/**
* 同步Session数据到Db
*
* @author yangzz
*/
public class SyncOnlineSessionFilter extends PathMatchingFilter
{
@Autowired

View File

@ -0,0 +1,156 @@
package com.ruoyi.project.shiro.web.session;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.shiro.ShiroConstants;
import com.ruoyi.project.system.online.domain.OnlineSession;
import com.ruoyi.project.system.online.domain.UserOnline;
import com.ruoyi.project.system.online.service.UserOnlineServiceImpl;
/**
* 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步
*
* @author yangzz
*/
public class OnlineWebSessionManager extends DefaultWebSessionManager
{
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
@Override
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException
{
super.setAttribute(sessionKey, attributeKey, value);
if (value != null && needMarkAttributeChanged(attributeKey))
{
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
s.markAttributeChanged();
}
}
private boolean needMarkAttributeChanged(Object attributeKey)
{
if (attributeKey == null)
{
return false;
}
String attributeKeyStr = attributeKey.toString();
// 优化 flash属性没必要持久化
if (attributeKeyStr.startsWith("org.springframework"))
{
return false;
}
if (attributeKeyStr.startsWith("javax.servlet"))
{
return false;
}
if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME))
{
return false;
}
return true;
}
@Override
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException
{
Object removed = super.removeAttribute(sessionKey, attributeKey);
if (removed != null)
{
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
s.markAttributeChanged();
}
return removed;
}
/**
* 验证session是否有效 用于删除过期session
*/
@Override
public void validateSessions()
{
if (log.isInfoEnabled())
{
log.info("invalidation sessions...");
}
int invalidCount = 0;
int timeout = (int) this.getGlobalSessionTimeout();
Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout);
UserOnlineServiceImpl userOnlineService = SpringUtils.getBean(UserOnlineServiceImpl.class);
List<UserOnline> userOnlineList = userOnlineService.selectByOnlineExpired(expiredDate);
// 批量过期删除
List<String> needOfflineIdList = new ArrayList<String>();
for (UserOnline userOnline : userOnlineList)
{
try
{
SessionKey key = new DefaultSessionKey(userOnline.getSessionId());
Session session = retrieveSession(key);
if (session != null)
{
throw new InvalidSessionException();
}
}
catch (InvalidSessionException e)
{
if (log.isDebugEnabled())
{
boolean expired = (e instanceof ExpiredSessionException);
String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]"
+ (expired ? " (expired)" : " (stopped)");
log.debug(msg);
}
invalidCount++;
needOfflineIdList.add(userOnline.getSessionId());
}
}
if (needOfflineIdList.size() > 0)
{
try
{
userOnlineService.batchDeleteByOnline(needOfflineIdList);
}
catch (Exception e)
{
log.error("batch delete db session error.", e);
}
}
if (log.isInfoEnabled())
{
String msg = "Finished invalidation session.";
if (invalidCount > 0)
{
msg += " [" + invalidCount + "] sessions were stopped.";
}
else
{
msg += " No sessions were stopped.";
}
log.info(msg);
}
}
@Override
protected Collection<Session> getActiveSessions()
{
throw new UnsupportedOperationException("getActiveSessions method not supported");
}
}

View File

@ -0,0 +1,143 @@
package com.ruoyi.project.shiro.web.session;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 自定义任务调度器完成
*
* @author yangzz
*/
public class SpringSessionValidationScheduler implements SessionValidationScheduler
{
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
/**
* 定时器用于处理超时的挂起请求也用于连接断开时的重连
*/
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private volatile boolean enabled = false;
/**
* The session manager used to validate sessions.
*/
private ValidatingSessionManager sessionManager;
/**
* The session validation interval in milliseconds.
*/
private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
/**
* Default constructor.
*/
public SpringSessionValidationScheduler()
{
}
/**
* Constructor that specifies the session manager that should be used for validating sessions.
*
* @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
*/
public SpringSessionValidationScheduler(ValidatingSessionManager sessionManager)
{
this.sessionManager = sessionManager;
}
public void setSessionManager(ValidatingSessionManager sessionManager)
{
this.sessionManager = sessionManager;
}
@Override
public boolean isEnabled()
{
return this.enabled;
}
/**
* Specifies how frequently (in milliseconds) this Scheduler will call the
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
* ValidatingSessionManager#validateSessions()} method.
*
* <p>
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
*
* @param sessionValidationInterval
*/
public void setSessionValidationInterval(long sessionValidationInterval)
{
this.sessionValidationInterval = sessionValidationInterval;
}
/**
* Starts session validation by creating a spring PeriodicTrigger.
*/
@Override
public void enableSessionValidation()
{
enabled = true;
if (log.isDebugEnabled())
{
log.debug("Scheduling session validation job using Spring Scheduler with "
+ "session validation interval of [" + sessionValidationInterval + "]ms...");
}
try
{
executorService.scheduleAtFixedRate(new Runnable()
{
@Override
public void run()
{
if (enabled)
{
sessionManager.validateSessions();
}
}
}, 1000, sessionValidationInterval, TimeUnit.MILLISECONDS);
this.enabled = true;
if (log.isDebugEnabled())
{
log.debug("Session validation job successfully scheduled with Spring Scheduler.");
}
}
catch (Exception e)
{
if (log.isErrorEnabled())
{
log.error(
"Error starting the Spring Scheduler session validation job. Session validation may not occur.",
e);
}
}
}
@Override
public void disableSessionValidation()
{
if (log.isDebugEnabled())
{
log.debug("Stopping Spring Scheduler session validation job...");
}
this.enabled = false;
}
}

View File

@ -22,6 +22,7 @@ public class LogininforServiceImpl implements ILogininforService
*
* @param logininfor 访问日志对象
*/
@Override
public void insertLogininfor(Logininfor logininfor)
{
logininforDao.insertLogininfor(logininfor);

View File

@ -1,7 +1,6 @@
package com.ruoyi.project.system.online.dao;
import java.util.List;
import com.ruoyi.project.system.online.domain.UserOnline;
public interface IUserOnlineDao
@ -35,4 +34,12 @@ public interface IUserOnlineDao
* @param online 会话信息
*/
public List<UserOnline> selectUserOnlines();
/**
* 查询过期会话集合
*
* @param lastAccessTime 过期时间
*/
public List<UserOnline> selectByOnlineExpired(String lastAccessTime);
}

View File

@ -26,6 +26,7 @@ public class UserOnlineDaoImpl extends DynamicObjectBaseDao implements IUserOnli
* @param sessionId 会话ID
* @return 在线用户信息
*/
@Override
public int deleteByOnlineId(String sessionId)
{
return this.delete("SystemOnlineMapper.deleteByOnlineId", sessionId);
@ -36,6 +37,7 @@ public class UserOnlineDaoImpl extends DynamicObjectBaseDao implements IUserOnli
*
* @param online 会话信息
*/
@Override
public int saveByOnline(UserOnline online)
{
return this.save("SystemOnlineMapper.saveByOnline", online);
@ -46,6 +48,7 @@ public class UserOnlineDaoImpl extends DynamicObjectBaseDao implements IUserOnli
*
* @param online 会话信息
*/
@Override
public List<UserOnline> selectUserOnlines()
{
List<UserOnline> userOnlineList = null;
@ -59,4 +62,24 @@ public class UserOnlineDaoImpl extends DynamicObjectBaseDao implements IUserOnli
}
return userOnlineList;
}
/**
* 查询过期会话集合
*
* @param lastAccessTime 过期时间
*/
@Override
public List<UserOnline> selectByOnlineExpired(String lastAccessTime)
{
List<UserOnline> userOnlineList = null;
try
{
userOnlineList = this.findForList("SystemOnlineMapper.selectByOnlineExpired", lastAccessTime);
}
catch (Exception e)
{
e.printStackTrace();
}
return userOnlineList;
}
}

View File

@ -37,11 +37,13 @@ public class OnlineSession extends SimpleSession
// 属性是否改变 优化session数据同步
private transient boolean attributeChanged = false;
@Override
public String getHost()
{
return host;
}
@Override
public void setHost(String host)
{
this.host = host;

View File

@ -1,5 +1,6 @@
package com.ruoyi.project.system.online.service;
import java.util.Date;
import java.util.List;
import com.ruoyi.project.system.online.domain.UserOnline;
@ -21,6 +22,14 @@ public interface IUserOnlineService
*/
public void deleteByOnlineId(String sessionId);
/**
* 通过会话序号删除信息
*
* @param sessions 会话ID集合
* @return 在线用户信息
*/
public void batchDeleteByOnline(List<String> sessions);
/**
* 保存会话信息
*
@ -41,4 +50,11 @@ public interface IUserOnlineService
* @param sessionId 会话ID
*/
public void forceLogout(String sessionId);
/**
* 查询会话集合
*
* @param online 会话信息
*/
public List<UserOnline> selectByOnlineExpired(Date expiredDate);
}

View File

@ -1,9 +1,13 @@
package com.ruoyi.project.system.online.service;
import java.util.Date;
import java.util.List;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.tools.DateTools;
import com.ruoyi.project.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.system.online.dao.IUserOnlineDao;
import com.ruoyi.project.system.online.domain.UserOnline;
@ -23,6 +27,7 @@ public class UserOnlineServiceImpl implements IUserOnlineService
* @param sessionId 会话ID
* @return 在线用户信息
*/
@Override
public UserOnline selectByOnlineId(String sessionId)
{
return userOnlineDao.selectByOnlineId(sessionId);
@ -34,6 +39,7 @@ public class UserOnlineServiceImpl implements IUserOnlineService
* @param sessionId 会话ID
* @return 在线用户信息
*/
@Override
public void deleteByOnlineId(String sessionId)
{
UserOnline userOnline = selectByOnlineId(sessionId);
@ -43,11 +49,31 @@ public class UserOnlineServiceImpl implements IUserOnlineService
}
}
/**
* 通过会话序号删除信息
*
* @param sessions 会话ID集合
* @return 在线用户信息
*/
@Override
public void batchDeleteByOnline(List<String> sessions)
{
for (String sessionId : sessions)
{
UserOnline userOnline = selectByOnlineId(sessionId);
if (userOnline != null)
{
userOnlineDao.deleteByOnlineId(sessionId);
}
}
}
/**
* 保存会话信息
*
* @param online 会话信息
*/
@Override
public void saveByOnline(UserOnline online)
{
userOnlineDao.saveByOnline(online);
@ -58,6 +84,7 @@ public class UserOnlineServiceImpl implements IUserOnlineService
*
* @param online 会话信息
*/
@Override
public List<UserOnline> selectUserOnlines()
{
return userOnlineDao.selectUserOnlines();
@ -68,6 +95,7 @@ public class UserOnlineServiceImpl implements IUserOnlineService
*
* @param sessionId 会话ID
*/
@Override
public void forceLogout(String sessionId)
{
Session session = onlineSessionDAO.readSession(sessionId);
@ -78,4 +106,16 @@ public class UserOnlineServiceImpl implements IUserOnlineService
session.setTimeout(1000);
userOnlineDao.deleteByOnlineId(sessionId);
}
/**
* 查询会话集合
*
* @param online 会话信息
*/
@Override
public List<UserOnline> selectByOnlineExpired(Date expiredDate)
{
String lastAccessTime = DateTools.dateTime("yyyy-MM-dd HH:mm:ss", expiredDate);
return userOnlineDao.selectByOnlineExpired(lastAccessTime);
}
}

View File

@ -1,8 +1,8 @@
y-admin:
ruoyi:
uploadPath: D:/var/uploaded_files/
logging:
level:
com.bootdo: debug
com.ruoyi: debug
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource

View File

@ -32,4 +32,13 @@ mybatis:
# 配置mapper的扫描找到所有的mapper.xml映射文件
mapperLocations: classpath:mybatis/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
configLocation: classpath:mybatis/mybatis-config.xml
# Shiro
shiro:
session:
# Session超时时间默认30分钟
expireTime: 30
# 同步session到数据库的周期默认1分钟
dbSyncPeriod: 1
# 相隔多久检查一次session的有效性默认就是60分钟
validationInterval: 60

View File

@ -44,5 +44,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectUserOnlines" resultMap="UserOnlineResult">
select * from sys_user_online
</select>
<select id="selectByOnlineExpired" parameterType="String" resultMap="UserOnlineResult">
SELECT * FROM sys_user_online o
WHERE o.last_access_time <![CDATA[ <= ]]> #{lastAccessTime} ORDER BY o.last_access_time ASC
</select>
</mapper>