From 623c70d6fca298984ba0aa78d225ac0a3fb5d050 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Sun, 25 Feb 2018 17:47:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BC=9A=E8=AF=9D=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E8=BF=87=E6=BB=A4=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ll_20180224.sql => new_intall_20180225.sql | 20 +- .../ruoyi/framework/config/ShiroConfig.java | 36 +++ .../shiro/session/OnlineSessionDAO.java | 37 +-- .../shiro/web/OnlineSessionFilter.java | 95 ++++++++ .../web/sync/SyncOnlineSessionFilter.java | 35 +++ .../controller/UserOnlineController.java | 46 +++- .../system/online/domain/OnlineSession.java | 224 +++++------------- .../system/online/domain/UserOnline.java | 94 +++++--- .../online/service/UserOnlineServiceImpl.java | 2 +- .../user/controller/IndexController.java | 2 +- .../mybatis/system/SystemOnlineMapper.xml | 13 +- .../static/js/appjs/sys/online/online.js | 44 ++-- src/main/resources/templates/include.html | 38 +++ src/main/resources/templates/index.html | 4 +- src/main/resources/templates/main.html | 8 +- 15 files changed, 424 insertions(+), 274 deletions(-) rename new_intall_20180224.sql => new_intall_20180225.sql (92%) create mode 100644 src/main/java/com/ruoyi/project/shiro/web/OnlineSessionFilter.java create mode 100644 src/main/java/com/ruoyi/project/shiro/web/sync/SyncOnlineSessionFilter.java create mode 100644 src/main/resources/templates/include.html diff --git a/new_intall_20180224.sql b/new_intall_20180225.sql similarity index 92% rename from new_intall_20180224.sql rename to new_intall_20180225.sql index 3f33fdaea..ab66a02fe 100644 --- a/new_intall_20180224.sql +++ b/new_intall_20180225.sql @@ -110,10 +110,10 @@ insert into sys_menu values('4', '角色管理', '1', '2', '/system/role/roleLis insert into sys_menu values('5', '菜单管理', '1', '3', '/system/menu/menuList', 'C', '0', 'system:menu:list', '#', '2018-01-01', '', 'system', '菜单管理菜单'); insert into sys_menu values('6', '操作日志', '1', '4', '/system/operlog/operlogList', 'C', '0', 'system:operlog:list', '#', '2018-01-01', '', 'system', '操作日志菜单'); insert into sys_menu values('7', '登录日志', '1', '5', '/system/userlog/userlogList', 'C', '0', 'system:userlog:list', '#', '2018-01-01', '', 'system', '登录日志菜单'); -insert into sys_menu values('8', '在线用户', '2', '1', '/monitor/userOnline', 'C', '0', 'monitor:userOnline', '#', '2018-01-01', '', 'system', '在线用户菜单'); +insert into sys_menu values('8', '在线用户', '2', '1', '/monitor/online', 'C', '0', 'monitor:online', '#', '2018-01-01', '', 'system', '在线用户菜单'); insert into sys_menu values('9', '数据监控', '2', '2', '/monitor/druid/index.html', 'C', '0', 'monitor:druid:list', '#', '2018-01-01', '', 'system', '数据监控菜单'); --- 三级用户按钮 -insert into sys_menu values('10', '用户新增', '3', '1', '/system/user/add', 'F', '0', 'sys:user:add', '#', '2018-01-01', '', 'system', '用户管理新增按钮'); +insert into sys_menu values('10', '用户新增', '3', '1', '/system/user/add', 'F', '0', 'sys:user:add', '#', '2018-01-01', '', 'system', '用户管理新增按钮'); insert into sys_menu values('11', '用户修改', '3', '2', '/system/user/update', 'F', '0', 'sys:user:update', '#', '2018-01-01', '', 'system', '用户管理修改按钮'); insert into sys_menu values('12', '用户删除', '3', '3', '/system/user/delete', 'F', '0', 'sys:user:delete', '#', '2018-01-01', '', 'system', '用户管理删除按钮'); insert into sys_menu values('13', '用户查询', '3', '4', '/system/user/select', 'F', '0', 'sys:user:select', '#', '2018-01-01', '', 'system', '用户管理查询按钮'); @@ -254,22 +254,22 @@ insert into sys_logininfor values(1, 'admin', 0 , '127.0.0.1', 'Chrome 45', 'Win -- ---------------------------- drop table if exists sys_user_online; create table sys_user_online ( - sessionId varchar(100) default '' comment '用户会话id', - user_id int(11) default 0 comment '用户ID', - login_name varchar(50) default '' comment '登录名', + sessionId varchar(50) default '' comment '用户会话id', + login_name varchar(50) default '' comment '登录名称', + dept_name varchar(50) default '' comment '部门名称', + role_name varchar(50) default '' comment '角色名称', ipaddr varchar(50) default '' comment '登录IP地址', browser varchar(50) default '' comment '浏览器类型', os varchar(50) default '' comment '操作系统', - status varchar(10) default '' comment '在线状态', + status varchar(10) default '' comment '在线状态on_line在线off_line离线', start_timestsamp timestamp default current_timestamp comment 'session创建时间', last_access_time timestamp default current_timestamp comment 'session最后访问时间', - timeout int(5) default 0 comment '超时时间', - onlineSession varchar(50) default '' comment '备份的当前用户会话', + expireTime int(5) default 0 comment '超时时间,单位为分钟', primary key (sessionId) ) engine=innodb default charset=utf8; -insert into sys_user_online(sessionId, user_id, login_name, ipaddr, browser, os, status) -values('c3b252c3-2229-4be4-a5f7-7aba4b0c314c', 1, 'admin', '127.0.0.1', 'Chrome 45', 'Windows 7', 'on_line'); +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'); -- 用户部门表 SELECT * FROM sys_dept; diff --git a/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/src/main/java/com/ruoyi/framework/config/ShiroConfig.java index f8c942b8a..4e8e0e5e3 100644 --- a/src/main/java/com/ruoyi/framework/config/ShiroConfig.java +++ b/src/main/java/com/ruoyi/framework/config/ShiroConfig.java @@ -1,6 +1,9 @@ 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; @@ -20,6 +23,8 @@ 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.system.menu.service.MenuServiceImpl; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; @@ -140,12 +145,43 @@ public class ShiroConfig // 系统权限列表 MenuServiceImpl menuService = SpringUtils.getBean(MenuServiceImpl.class); filterChainDefinitionMap.putAll(menuService.selectPermsAll()); + + Map filters = new LinkedHashMap<>(); + filters.put("onlineSession", onlineSessionFilter()); + filters.put("syncOnlineSession", syncOnlineSessionFilter()); + shiroFilterFactoryBean.setFilters(filters); + // 所有请求需要认证 filterChainDefinitionMap.put("/**", "authc"); + // 系统请求记录当前会话 + filterChainDefinitionMap.put("/system/**", "onlineSession,syncOnlineSession"); + filterChainDefinitionMap.put("/monitor/**", "onlineSession,syncOnlineSession"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; } + /** + * 自定义在线用户处理过滤器 + */ + @Bean + OnlineSessionFilter onlineSessionFilter() + { + OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter(); + onlineSessionFilter.setLoginUrl("/login"); + return onlineSessionFilter; + } + + /** + * 自定义在线用户同步过滤器 + */ + @Bean + SyncOnlineSessionFilter syncOnlineSessionFilter() + { + SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter(); + return syncOnlineSessionFilter; + } + /** * 保证实现了Shiro内部lifecycle函数的bean执行 */ diff --git a/src/main/java/com/ruoyi/project/shiro/session/OnlineSessionDAO.java b/src/main/java/com/ruoyi/project/shiro/session/OnlineSessionDAO.java index dae162451..6c99c5879 100644 --- a/src/main/java/com/ruoyi/project/shiro/session/OnlineSessionDAO.java +++ b/src/main/java/com/ruoyi/project/shiro/session/OnlineSessionDAO.java @@ -77,35 +77,22 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO /** * 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用 */ - @Override - protected void doUpdate(Session session) + public void syncToDb(OnlineSession onlineSession) { HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); String uri = request.getServletPath(); - // 如果是静态文件,则不更新SESSION - if (checkStaticLink(uri)) - { - return; - } - System.out.println("==============update url=================" + uri); - if (session == null) - { - return; - } - - OnlineSession onlineSession = (OnlineSession) session; - - Date lastSyncTimestamp = (Date) session.getAttribute(LAST_SYNC_DB_TIMESTAMP); + System.out.println("===============update================" + uri); + Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP); if (lastSyncTimestamp != null) { boolean needSync = true; - long deltaTime = session.getLastAccessTime().getTime() - lastSyncTimestamp.getTime(); + long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime(); if (deltaTime < dbSyncPeriod) { // 时间差不足 无需同步 needSync = false; } - boolean isGuest = session.getId() == null; + boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L; // 如果不是游客 且session 数据变更了 同步 if (isGuest == false && onlineSession.isAttributeChanged()) @@ -118,8 +105,7 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO return; } } - session.setAttribute(LAST_SYNC_DB_TIMESTAMP, session.getLastAccessTime()); - // session.setTimeout(expireTime); + onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime()); // 更新完后 重置标识 if (onlineSession.isAttributeChanged()) { @@ -134,14 +120,16 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO @Override protected void doDelete(Session session) { - System.out.println("===============delete================"); + HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); + String uri = request.getServletPath(); + System.out.println("===============delete================" + uri); OnlineSession onlineSession = (OnlineSession) session; if (null == onlineSession) { return; } - String sessionId = String.valueOf(onlineSession.getId()); - onlineService.deleteByOnlineId(sessionId); + onlineSession.setStatus(OnlineSession.OnlineStatus.off_line); + onlineService.deleteByOnlineId(String.valueOf(onlineSession.getId())); } public long getExpireTime() @@ -163,7 +151,8 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO { boolean linkFlag = false; // 如果是登录请求,则不更新SESSION - if (StringUtils.endsWithAny(uri, new String[] { "/login", "/logout", "/index", "/", "/favicon.ico" })) + if (StringUtils.startsWithAny(uri, + new String[] { "/monitor/online/forceLogout", "/login", "/logout", "/index", "/favicon.ico" })) { linkFlag = true; } diff --git a/src/main/java/com/ruoyi/project/shiro/web/OnlineSessionFilter.java b/src/main/java/com/ruoyi/project/shiro/web/OnlineSessionFilter.java new file mode 100644 index 000000000..b02ad2f68 --- /dev/null +++ b/src/main/java/com/ruoyi/project/shiro/web/OnlineSessionFilter.java @@ -0,0 +1,95 @@ +package com.ruoyi.project.shiro.web; + +import java.io.IOException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.AccessControlFilter; +import org.apache.shiro.web.util.WebUtils; +import org.springframework.beans.factory.annotation.Autowired; +import com.ruoyi.common.utils.security.ShiroUtils; +import com.ruoyi.project.shiro.ShiroConstants; +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 +{ + + /** + * 强制退出后重定向的地址 + */ + private String forceLogoutUrl = "/login"; + + @Autowired + private OnlineSessionDAO onlineSessionDAO; + + public String getForceLogoutUrl() + { + return forceLogoutUrl; + } + + /** + * 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false; + */ + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) + throws Exception + { + Subject subject = getSubject(request, response); + if (subject == null || subject.getSession() == null) + { + return true; + } + Session session = onlineSessionDAO.readSession(subject.getSession().getId()); + if (session != null && session instanceof OnlineSession) + { + OnlineSession onlineSession = (OnlineSession) session; + request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession); + // 把user对象设置进去 + boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L; + if (isGuest == true) + { + User user = ShiroUtils.getUser(); + if (user != null) + { + onlineSession.setUserId(user.getUserId()); + onlineSession.setLoginName(user.getLoginName()); + onlineSession.setDeptName(user.getDept().getDeptName()); + onlineSession.setRoleName(user.getRole().getRoleName()); + onlineSession.markAttributeChanged(); + } + } + + if (onlineSession.getStatus() == OnlineSession.OnlineStatus.off_line) + { + return false; + } + } + return true; + } + + /** + * 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。 + */ + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception + { + Subject subject = getSubject(request, response); + if (subject != null) + { + subject.logout(); + } + saveRequestAndRedirectToLogin(request, response); + return true; + } + + // 跳转到登录页 + protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException + { + String loginUrl = getForceLogoutUrl(); + WebUtils.issueRedirect(request, response, loginUrl); + } + +} diff --git a/src/main/java/com/ruoyi/project/shiro/web/sync/SyncOnlineSessionFilter.java b/src/main/java/com/ruoyi/project/shiro/web/sync/SyncOnlineSessionFilter.java new file mode 100644 index 000000000..1f78aa619 --- /dev/null +++ b/src/main/java/com/ruoyi/project/shiro/web/sync/SyncOnlineSessionFilter.java @@ -0,0 +1,35 @@ +package com.ruoyi.project.shiro.web.sync; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import org.apache.shiro.web.filter.PathMatchingFilter; +import org.springframework.beans.factory.annotation.Autowired; +import com.ruoyi.project.shiro.ShiroConstants; +import com.ruoyi.project.shiro.session.OnlineSessionDAO; +import com.ruoyi.project.system.online.domain.OnlineSession; + +public class SyncOnlineSessionFilter extends PathMatchingFilter +{ + @Autowired + private OnlineSessionDAO onlineSessionDAO; + + /** + * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前 + * + * @param request + * @param response + * @return + * @throws Exception + */ + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception + { + OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION); + // 如果session stop了 也不同步 + if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) + { + onlineSessionDAO.syncToDb(session); + } + return true; + } +} diff --git a/src/main/java/com/ruoyi/project/system/online/controller/UserOnlineController.java b/src/main/java/com/ruoyi/project/system/online/controller/UserOnlineController.java index b8a8b6e16..1b4ebaae1 100644 --- a/src/main/java/com/ruoyi/project/system/online/controller/UserOnlineController.java +++ b/src/main/java/com/ruoyi/project/system/online/controller/UserOnlineController.java @@ -1,22 +1,26 @@ package com.ruoyi.project.system.online.controller; import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; + import com.ruoyi.common.tools.StringTools; -import com.ruoyi.common.utils.TableDataInfo; import com.ruoyi.framework.core.controller.BaseController; import com.ruoyi.framework.core.domain.R; +import com.ruoyi.project.shiro.session.OnlineSessionDAO; +import com.ruoyi.project.system.online.domain.OnlineSession; import com.ruoyi.project.system.online.domain.UserOnline; import com.ruoyi.project.system.online.service.IUserOnlineService; @Controller -@RequestMapping("/monitor/userOnline") +@RequestMapping("/monitor/online") public class UserOnlineController extends BaseController { @@ -25,19 +29,21 @@ public class UserOnlineController extends BaseController @Autowired private IUserOnlineService userOnlineService; + @Autowired + private OnlineSessionDAO onlineSessionDAO; + @GetMapping() - public String userOnline() + public String online() { return prefix + "/online"; } @GetMapping("/list") @ResponseBody - public TableDataInfo list(Model model) + public List list(Model model) { List list = userOnlineService.selectUserOnlines(); - TableDataInfo tableDataInfo = new TableDataInfo(list, 12); - return tableDataInfo; + return list; } @GetMapping("/forceLogout") @@ -68,4 +74,32 @@ public class UserOnlineController extends BaseController } } + @ResponseBody + @RequestMapping("/forceLogout/{sessionId}") + public R forceLogout(@PathVariable("sessionId") String sessionId) + { + try + { + UserOnline online = userOnlineService.selectByOnlineId(sessionId); + if (online == null) + { + return R.error("用户已下线。数据不存在"); + } + OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId()); + if (onlineSession == null) + { + return R.error("用户已下线。会话不存在"); + } + onlineSession.setStatus(OnlineSession.OnlineStatus.off_line); + online.setStatus(OnlineSession.OnlineStatus.off_line); + userOnlineService.saveByOnline(online); + return R.ok(); + } + catch (Exception e) + { + return R.error(e.getMessage()); + } + + } + } diff --git a/src/main/java/com/ruoyi/project/system/online/domain/OnlineSession.java b/src/main/java/com/ruoyi/project/system/online/domain/OnlineSession.java index 41084abcd..34fbf7a7c 100644 --- a/src/main/java/com/ruoyi/project/system/online/domain/OnlineSession.java +++ b/src/main/java/com/ruoyi/project/system/online/domain/OnlineSession.java @@ -1,8 +1,5 @@ package com.ruoyi.project.system.online.domain; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import org.apache.shiro.session.mgt.SimpleSession; /** @@ -11,48 +8,20 @@ import org.apache.shiro.session.mgt.SimpleSession; public class OnlineSession extends SimpleSession { - // Serialization reminder: - // You _MUST_ change this number if you introduce a change to this class - // that is NOT serialization backwards compatible. Serialization-compatible - // changes do not require a change to this number. If you need to generate - // a new number in this case, use the JDK's 'serialver' program to generate - // it. - private static final long serialVersionUID = -7125642695178165650L; - static int bitIndexCounter = 0; - private static final int USER_ID_BIT_MASK = 1 << bitIndexCounter++; - private static final int USER_AGENT_BIT_MASK = 1 << bitIndexCounter++; - private static final int STATUS_BIT_MASK = 1 << bitIndexCounter++; - private static final int USERNAME_BIT_MASK = 1 << bitIndexCounter++; - // private static final int REMEMBER_ME_BIT_MASK = 1 << bitIndexCounter++; + private static final long serialVersionUID = 1L; - public static enum OnlineStatus - { - on_line("在线"), hidden("隐身"), force_logout("强制退出"); - private final String info; + // 用户ID + private Long userId; - private OnlineStatus(String info) - { - this.info = info; - } - - public String getInfo() - { - return info; - } - - @Override - public String toString() - { - return super.toString(); - } - } - - // 当前登录的用户Id - private String userId; - - // 登录名 + // 用户名称 private String loginName; + // 部门名称 + private String deptName; + + // 角色名称 + private String roleName; + // 登录IP地址 private String host; @@ -65,35 +34,8 @@ public class OnlineSession extends SimpleSession // 在线状态 private OnlineStatus status = OnlineStatus.on_line; - public OnlineSession() - { - super(); - } - - public OnlineSession(String host) - { - super(host); - } - - public String getUserId() - { - return userId; - } - - public void setUserId(String userId) - { - this.userId = userId; - } - - public String getLoginName() - { - return loginName; - } - - public void setLoginName(String loginName) - { - this.loginName = loginName; - } + // 属性是否改变 优化session数据同步 + private transient boolean attributeChanged = false; public String getHost() { @@ -125,6 +67,46 @@ public class OnlineSession extends SimpleSession this.os = os; } + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public String getLoginName() + { + return loginName; + } + + public void setLoginName(String loginName) + { + this.loginName = loginName; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getRoleName() + { + return roleName; + } + + public void setRoleName(String roleName) + { + this.roleName = roleName; + } + public OnlineStatus getStatus() { return status; @@ -135,11 +117,6 @@ public class OnlineSession extends SimpleSession this.status = status; } - /** - * 属性是否改变 优化session数据同步 - */ - private transient boolean attributeChanged = false; - public void markAttributeChanged() { this.attributeChanged = true; @@ -167,101 +144,20 @@ public class OnlineSession extends SimpleSession return super.removeAttribute(key); } - /** - * Serializes this object to the specified output stream for JDK Serialization. - * - * @param out output stream used for Object serialization. - * @throws java.io.IOException if any of this object's fields cannot be written to the stream. - * @since 1.0 - */ - private void writeObject(ObjectOutputStream out) throws IOException + public static enum OnlineStatus { - out.defaultWriteObject(); - short alteredFieldsBitMask = getAlteredFieldsBitMask(); - out.writeShort(alteredFieldsBitMask); - if (userId != null) + on_line("在线"), off_line("离线"); + private final String info; + + private OnlineStatus(String info) { - out.writeObject(userId); - } - if (browser != null) - { - out.writeObject(browser); - } - if (status != null) - { - out.writeObject(status); + this.info = info; } - if (loginName != null) + public String getInfo() { - out.writeObject(loginName); + return info; } } - /** - * Reconstitutes this object based on the specified InputStream for JDK Serialization. - * - * @param in the input stream to use for reading data to populate this object. - * @throws IOException if the input stream cannot be used. - * @throws ClassNotFoundException if a required class needed for instantiation is not available in the present JVM - * @since 1.0 - */ - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - short bitMask = in.readShort(); - - if (isFieldPresent(bitMask, USER_ID_BIT_MASK)) - { - this.userId = (String) in.readObject(); - } - if (isFieldPresent(bitMask, USER_AGENT_BIT_MASK)) - { - this.browser = (String) in.readObject(); - } - if (isFieldPresent(bitMask, STATUS_BIT_MASK)) - { - this.status = (OnlineStatus) in.readObject(); - } - if (isFieldPresent(bitMask, USERNAME_BIT_MASK)) - { - this.loginName = (String) in.readObject(); - } - } - - /** - * Returns a bit mask used during serialization indicating which fields have been serialized. Fields that have been - * altered (not null and/or not retaining the class defaults) will be serialized and have 1 in their respective - * index, fields that are null and/or retain class default values have 0. - * - * @return a bit mask used during serialization indicating which fields have been serialized. - * @since 1.0 - */ - private short getAlteredFieldsBitMask() - { - int bitMask = 0; - bitMask = userId != null ? bitMask | USER_ID_BIT_MASK : bitMask; - bitMask = browser != null ? bitMask | USER_AGENT_BIT_MASK : bitMask; - bitMask = status != null ? bitMask | STATUS_BIT_MASK : bitMask; - bitMask = loginName != null ? bitMask | USERNAME_BIT_MASK : bitMask; - return (short) bitMask; - } - - /** - * Returns {@code true} if the given {@code bitMask} argument indicates that the specified field has been serialized - * and therefore should be read during deserialization, {@code false} otherwise. - * - * @param bitMask the aggregate bitmask for all fields that have been serialized. Individual bits represent the - * fields that have been serialized. A bit set to 1 means that corresponding field has been serialized, 0 - * means it hasn't been serialized. - * @param fieldBitMask the field bit mask constant identifying which bit to inspect (corresponds to a class - * attribute). - * @return {@code true} if the given {@code bitMask} argument indicates that the specified field has been serialized - * and therefore should be read during deserialization, {@code false} otherwise. - * @since 1.0 - */ - private static boolean isFieldPresent(short bitMask, int fieldBitMask) - { - return (bitMask & fieldBitMask) != 0; - } } diff --git a/src/main/java/com/ruoyi/project/system/online/domain/UserOnline.java b/src/main/java/com/ruoyi/project/system/online/domain/UserOnline.java index 666812e1f..9513d2542 100644 --- a/src/main/java/com/ruoyi/project/system/online/domain/UserOnline.java +++ b/src/main/java/com/ruoyi/project/system/online/domain/UserOnline.java @@ -2,8 +2,7 @@ package com.ruoyi.project.system.online.domain; import java.io.Serializable; import java.util.Date; - -import com.ruoyi.common.utils.security.ShiroUtils; +import com.ruoyi.project.system.online.domain.OnlineSession.OnlineStatus; /** * 当前在线会话 sys_user_online @@ -17,14 +16,17 @@ public class UserOnline implements Serializable // 用户会话id private String sessionId; - // 当前登录的用户Id - private String userId; + // 部门名称 + private String deptName; - // 登录名 + // 登录名称 private String loginName; + // 角色名称 + private String roleName; + // 登录IP地址 - private String host; + private String ipaddr; // 浏览器类型 private String browser; @@ -32,17 +34,17 @@ public class UserOnline implements Serializable // 操作系统 private String os; - // 在线状态 - private OnlineSession.OnlineStatus status = OnlineSession.OnlineStatus.on_line; - - // 在线状态 + // session创建时间 private Date startTimestamp; // session最后访问时间 private Date lastAccessTime; - // 超时时间 - private Long timeout; + // 超时时间,单位为分钟 + private Long expireTime; + + // 在线状态 + private OnlineStatus status = OnlineStatus.on_line; // 备份的当前用户会话 private OnlineSession session; @@ -57,14 +59,14 @@ public class UserOnline implements Serializable this.sessionId = sessionId; } - public String getUserId() + public String getDeptName() { - return userId; + return deptName; } - public void setUserId(String userId) + public void setDeptName(String deptName) { - this.userId = userId; + this.deptName = deptName; } public String getLoginName() @@ -77,14 +79,24 @@ public class UserOnline implements Serializable this.loginName = loginName; } - public String getHost() + public String getRoleName() { - return host; + return roleName; } - public void setHost(String host) + public void setRoleName(String roleName) { - this.host = host; + this.roleName = roleName; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; } public String getBrowser() @@ -107,16 +119,6 @@ public class UserOnline implements Serializable this.os = os; } - public OnlineSession.OnlineStatus getStatus() - { - return status; - } - - public void setStatus(OnlineSession.OnlineStatus status) - { - this.status = status; - } - public Date getStartTimestamp() { return startTimestamp; @@ -137,14 +139,24 @@ public class UserOnline implements Serializable this.lastAccessTime = lastAccessTime; } - public Long getTimeout() + public Long getExpireTime() { - return timeout; + return expireTime; } - public void setTimeout(Long timeout) + public void setExpireTime(Long expireTime) { - this.timeout = timeout; + this.expireTime = expireTime; + } + + public OnlineStatus getStatus() + { + return status; + } + + public void setStatus(OnlineStatus status) + { + this.status = status; } public OnlineSession getSession() @@ -157,20 +169,24 @@ public class UserOnline implements Serializable this.session = session; } + /** + * 设置session对象 + */ public static final UserOnline fromOnlineSession(OnlineSession session) { UserOnline online = new UserOnline(); online.setSessionId(String.valueOf(session.getId())); - online.setUserId(ShiroUtils.getUser().getUserId() + ""); - online.setLoginName(ShiroUtils.getUser().getLoginName()); + online.setDeptName(session.getDeptName()); + online.setLoginName(session.getLoginName()); + online.setRoleName(session.getRoleName()); online.setStartTimestamp(session.getStartTimestamp()); online.setLastAccessTime(session.getLastAccessTime()); - online.setTimeout(session.getTimeout()); - online.setHost(session.getHost()); + online.setExpireTime(session.getTimeout()); + online.setIpaddr(session.getHost()); online.setBrowser(session.getBrowser()); online.setOs(session.getOs()); + online.setStatus(session.getStatus()); online.setSession(session); - return online; } diff --git a/src/main/java/com/ruoyi/project/system/online/service/UserOnlineServiceImpl.java b/src/main/java/com/ruoyi/project/system/online/service/UserOnlineServiceImpl.java index 453e3445a..e8fc3f3c3 100644 --- a/src/main/java/com/ruoyi/project/system/online/service/UserOnlineServiceImpl.java +++ b/src/main/java/com/ruoyi/project/system/online/service/UserOnlineServiceImpl.java @@ -75,7 +75,7 @@ public class UserOnlineServiceImpl implements IUserOnlineService { return; } - session.setTimeout(0); + session.setTimeout(1000); userOnlineDao.deleteByOnlineId(sessionId); } } diff --git a/src/main/java/com/ruoyi/project/system/user/controller/IndexController.java b/src/main/java/com/ruoyi/project/system/user/controller/IndexController.java index dade7af4f..7f9e29c22 100644 --- a/src/main/java/com/ruoyi/project/system/user/controller/IndexController.java +++ b/src/main/java/com/ruoyi/project/system/user/controller/IndexController.java @@ -35,7 +35,7 @@ public class IndexController extends BaseController } // 系统介绍 - @GetMapping("/main") + @GetMapping("/system/main") public String main() { return "main"; diff --git a/src/main/resources/mybatis/system/SystemOnlineMapper.xml b/src/main/resources/mybatis/system/SystemOnlineMapper.xml index bc0998d83..59ea7e7dc 100644 --- a/src/main/resources/mybatis/system/SystemOnlineMapper.xml +++ b/src/main/resources/mybatis/system/SystemOnlineMapper.xml @@ -6,21 +6,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - + + + - + - - @@ -34,8 +33,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - replace into sys_user_online(sessionId, user_id, login_name, ipaddr, browser, os, status, start_timestsamp, last_access_time, timeout) - values (#{sessionId}, #{userId}, #{loginName}, #{host}, #{browser}, #{os}, #{status}, #{startTimestamp}, #{lastAccessTime}, #{timeout}) + replace into sys_user_online(sessionId, login_name, dept_name, role_name, ipaddr, browser, os, status, start_timestsamp, last_access_time, expireTime) + values (#{sessionId}, #{loginName}, #{deptName}, #{roleName}, #{ipaddr}, #{browser}, #{os}, #{status}, #{startTimestamp}, #{lastAccessTime}, #{expireTime}) diff --git a/src/main/resources/static/js/appjs/sys/online/online.js b/src/main/resources/static/js/appjs/sys/online/online.js index d33d302c0..56bd73d87 100644 --- a/src/main/resources/static/js/appjs/sys/online/online.js +++ b/src/main/resources/static/js/appjs/sys/online/online.js @@ -1,4 +1,4 @@ -var prefix = "/sys/online" +var prefix = "/monitor/online" $(function() { load(); }); @@ -47,28 +47,32 @@ function load() { checkbox : true }, { - field : 'id', // 列字段名 - title : '序号' // 列标题 + field : 'sessionId', // 列字段名 + title : '会话编号' // 列标题 }, { - field : 'username', - title : '用户名' + field : 'loginName', + title : '登录名称' }, { - field : 'host', + field : 'deptName', + title : '部门名称' + }, + { + field : 'roleName', + title : '角色名称' + }, + { + field : 'ipaddr', title : '主机' }, { - field : 'startTimestamp', - title : '登录时间' + field : 'browser', + title : '浏览器' }, { - field : 'lastAccessTime', - title : '最后访问时间' - }, - { - field : 'timeout', - title : '过期时间' + field : 'os', + title : '操作系统' }, { field : 'status', @@ -82,13 +86,21 @@ function load() { } } }, + { + field : 'startTimestamp', + title : '登录时间' + }, + { + field : 'lastAccessTime', + title : '最后访问时间' + }, { title : '操作', field : 'id', align : 'center', formatter : function(value, row, index) { - var d = ' '; return d; } diff --git a/src/main/resources/templates/include.html b/src/main/resources/templates/include.html new file mode 100644 index 000000000..de841720f --- /dev/null +++ b/src/main/resources/templates/include.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index e5c992ba6..1a975ad1a 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -43,7 +43,7 @@
  • 主页
  • @@ -114,7 +114,7 @@
    + th:src="@{/system/main}" frameborder="0" seamless>
    @@ -146,7 +146,7 @@
    如果图片太小,可以点击图片放大。

    - 请使用手机支付宝或者微信扫码支付 + 请使用手机支付宝或者微信扫码支付

    @@ -155,7 +155,7 @@ - - + +