平台默认提供的在线用户列表中没有记录用户登录的终端,因此要分别控制pc和mobile一个用户只能登录一次,需要自己记录用户登录的终端等信息
第一步:可以定义一个全局的map,在登录后把登录的用户名和终端作为key,登录产生的session做为value存储到map中
第二步:在登录前获取到当前登录的用户名和终端,判断map中是否有,如果有说明已经登录过了,可以抛出异常不让登录
第三步:当注销和session超时应该删除map中的信息,可以监听session失效实现
定义全局的map和监听session失效,可以在BusinessServer下创建servlet和listener实现,具体实现如下:
在\runtime\BusinessServer\WEB-INF下创建src
在src下创建servlet:/com/justep/user/OnLineMap.java,注意有包名目录/com/justep/user
package com.justep.user; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServlet; public class OnLineMap extends HttpServlet { //定义一个mapping存在登录者的相关信息 public static Map<String, Object> OnLineMaps = new HashMap<String, Object>(); }
创建listener:/com/justep/user/SessionListener.java,注意有包名目录/com/justep/user
package com.justep.user; import java.util.Map.Entry; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class SessionListener implements HttpSessionListener { public void sessionDestroyed(HttpSessionEvent event) { //session失效时获取map中value为此session的信息,并且map中删除 HttpSession session = event.getSession(); String user = ""; for (Entry<String, Object> entry : OnLineMap.OnLineMaps.entrySet()) { HttpSession userSession = (HttpSession) entry.getValue(); if(session.equals(userSession)){ user = entry.getKey(); } } OnLineMap.OnLineMaps.remove(user); } public void sessionCreated(HttpSessionEvent arg0) { // TODO 自动生成的方法存根 } }
最终运行是执行的java编译的class文件,可以在studio中切换到java视图,然后把\runtime\BusinessServer导入
直接复制上面的java代码在WEB-INF/src上粘贴就可以生产对应的java类和对应的class文件
在\runtime\BusinessServer\WEB-INF\web.xml中配置servlet和listener
注意:servlet和listener的配置要放到平台默认配置的前面
如下,com.justep.x.loader.NativeLoaderListener这个配置就是平台默认的:
<listener> <listener-class>com.justep.user.SessionListener</listener-class> </listener> <servlet> <servlet-name>getOnLine</servlet-name> <servlet-class>com.justep.user.OnLineMap</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>getOnLine</servlet-name> <url-pattern>/getOnLine</url-pattern> </servlet-mapping> <listener> <listener-class>com.justep.x.loader.NativeLoaderListener</listener-class> </listener> <listener>
登录后和登录前的操作可以在loginAction的执行前后事件中操作,通过扩展空间在/BIZ/SA_X/OPM/system/system.process.m的loginAction上添加事件
注意:事件默认生成的java的名字是System,需要自己修改一下名字,对应的procedure中配置的java的名字也需要修改,本案例用的是SystemTest
import java.util.Map; import javax.servlet.http.HttpSession; import com.justep.system.context.*; import com.justep.user.*; public class SystemTest { public static void systemProcessBeforeLoginAction() throws Exception { String user = ((String) ContextHelper.getActionContext().getParameter("name")); Map<Object, Object> options = (Map<Object, Object>) ContextHelper.getActionContext().getParameter("options"); String deviceType = (String) options.get("DeviceType"); String userDeviceType = user+":"+deviceType; //获取登录输入的name和设备类型,判断map中是否存在 if (OnLineMap.OnLineMaps.containsKey(userDeviceType)) { throw new Exception("此用户已经在当前终端类型登录,请切换其他用户登录"); } } public static void systemProcessAfterLoginAction() { String user = ((String) ContextHelper.getActionContext().getParameter("name"));// 获取登录输入的name // 获取设备类型 Map<Object, Object> options = (Map<Object, Object>) ContextHelper.getActionContext().getParameter("options"); String deviceType = (String) options.get("DeviceType"); HttpSession session = ContextHelper.getSessionContext().getSession();//获取登录产生的session String userDeviceType = user+":"+deviceType; // 把name和设备类型拼接做为key,session做为value放到Map中 OnLineMap.OnLineMaps.put(userDeviceType, session); } }
用map存储的这个方案可用于非集群的环境,如果集群的环境要控制,把map修改为数据库表,把登录人员的信息存储的数据库表中操作
评一波