package org.quickbundle.project.login; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.jws.WebMethod; import javax.jws.WebService; import javax.servlet.http.HttpSession; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.quickbundle.base.beans.factory.RmBeanFactory; import org.quickbundle.config.RmClusterConfig; import org.quickbundle.config.RmConfig; import org.quickbundle.project.IGlobalConstants; import org.quickbundle.project.RmProjectHelper; import org.quickbundle.project.common.vo.RmCommonVo; import org.quickbundle.project.listener.RmSessionListener; import org.quickbundle.project.login.RmUserVo.RmUserSessionVo; import org.quickbundle.tools.helper.RmPopulateHelper; import org.quickbundle.tools.helper.RmSqlHelper; import org.quickbundle.util.RmSequenceMap; import org.springframework.jdbc.core.RowMapper; @WebService(targetNamespace="http://login.project.quickbundle.org/", endpointInterface = "org.quickbundle.project.login.IRmSessionService") public class RmSessionService implements IRmSessionService { public static IRmSessionService getRemoteSessionService(String clusterNodeId) { String callWsUrl = RmClusterConfig.getSingleton().getSelfNode().get(RmClusterConfig.NodeKey.webServiceUrl.name()); if(callWsUrl == null) { return null; } String address = callWsUrl + "RmSession"; JaxWsProxyFactoryBean jw = new JaxWsProxyFactoryBean(); jw.setServiceClass(IRmSessionService.class); jw.setAddress(address); Object obj = jw.create(); IRmSessionService ss = (IRmSessionService) obj; return ss; } private IRmLoginService getLoginService() { return (IRmLoginService) RmBeanFactory.getBean(IRmLoginService.class.getName()); //得到Service对象,受事务控制 } @WebMethod(exclude=true) public int getRecordCount(String queryCondition) { String yesterday = new Timestamp(System.currentTimeMillis() - 1000*60*60*24*1).toString().substring(0, 19); String sql = "select count(*) from RM_USER u " + "join RM_USER_ONLINE_RECORD uor on (u.id=uor.user_id and u.last_login_date=uor.login_time and uor.logout_time is null) " + "where u.usable_status='1' and u.login_status='1' and u.last_login_date>" + RmSqlHelper.getSqlDateStr(yesterday); return RmProjectHelper.getCommonServiceInstance().doQueryForInt(sql); } @WebMethod(exclude=true) public List<RmUserSessionVo> queryByCondition(String queryCondition, String orderStr, int startIndex, int size) { List<RmUserSessionVo> result = new ArrayList<RmUserVo.RmUserSessionVo>(); final Map<String, HttpSession> mSession = RmSessionListener.getSessions(); String yesterday = new Timestamp(System.currentTimeMillis() - 1000*60*60*24*1).toString().substring(0, 19); String sql = "select uor.cluster_node_id, uor.login_sign, uor.login_uuid, u.* from RM_USER u " + "join RM_USER_ONLINE_RECORD uor on (u.id=uor.user_id and u.last_login_date=uor.login_time and uor.logout_time is null) " + "where u.usable_status='1' and u.login_status='1' and u.last_login_date>" + RmSqlHelper.getSqlDateStr(yesterday) + " order by u.last_login_date desc"; //sessionId -> RmUserSessionVo对象 final Map<String, RmUserSessionVo> mResult = new RmSequenceMap<String, RmUserSessionVo>(); //对clusterNodeId分组存放 final Map<String, List<String>> mOther = new RmSequenceMap<String, List<String>>(); RmProjectHelper.getCommonServiceInstance().doQueryStartIndex(sql, new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { RmUserSessionVo vo = new RmUserSessionVo(); RmPopulateHelper.populate(vo, rs); vo.setSessionId(rs.getString("login_sign")); //登录服务器主机名 vo.setClusterNodeId(rs.getString("cluster_node_id")); if(mSession.containsKey(vo.getSessionId())) { //如果在本机 HttpSession session = mSession.get(vo.getSessionId()); populateSessionVo(vo, session); } else { if(!mOther.containsKey(vo.getClusterNodeId())) { mOther.put(vo.getClusterNodeId(), new ArrayList<String>()); } mOther.get(vo.getClusterNodeId()).add(vo.getSessionId()); } mResult.put(vo.getSessionId(), vo); return null; } }, startIndex, size); //通过soa查询其他节点的session for(String clusterNodeId : mOther.keySet()) { String[] sessionIds = mOther.get(clusterNodeId).toArray(new String[0]); try { IRmSessionService remoteSs = getRemoteSessionService(clusterNodeId); if(remoteSs == null) { continue; } List<RmUserSessionVo> lBrother = remoteSs.listSessionLocal(sessionIds); for(RmUserSessionVo sourceVo : lBrother) { if(sourceVo == null) { continue; } RmUserSessionVo destinationVo = mResult.get(sourceVo.getSessionId()); if(sourceVo.getId() != null) { RmPopulateHelper.populate(destinationVo, sourceVo); } else { populateSessionVo(destinationVo, sourceVo); } } } catch (Exception e) { e.printStackTrace(); } } for(String sessionId : mResult.keySet()) { result.add(mResult.get(sessionId)); } return result; } public RmUserSessionVo findSessionLocal(String sessionId) { List<RmUserSessionVo> lvo = listSessionLocal(new String[]{sessionId}); if(lvo.size() > 0) { return lvo.get(0); } else { return null; } } private void populateSessionVo(RmUserSessionVo target, HttpSession session) { target.setSessionId(session.getId()); //session创建时间 target.setCreationTime(session.getCreationTime()); //最后访问时间 target.setLastAccessedTime(session.getLastAccessedTime()); //最大非活动间隔 target.setMaxInactiveInterval(session.getMaxInactiveInterval() * 1000); { //custom owner org this login, cluster begin if(session.getAttribute(IGlobalConstants.RM_USER_VO) != null) { target.setParty_id_org_name(((org.quickbundle.project.login.RmUserVo)session.getAttribute(IGlobalConstants.RM_USER_VO)).getParty_id_org_name()); } } //custom owner org this login, cluster end } private void populateSessionVo(RmUserSessionVo target, RmUserSessionVo source) { target.setCreationTime(source.getCreationTime()); target.setLastAccessedTime(source.getLastAccessedTime()); target.setMaxInactiveInterval(source.getMaxInactiveInterval()); target.setParty_id_org_name(source.getParty_id_org_name()); } @WebMethod(exclude=true) public boolean forceLogoutUser(String user_id, String session_id) { String msg = "您被管理员强制退出了,请重新登录。如有帐号异常,请联系管理员。"; boolean sendRemoteSuccess = false; if(RmConfig.getSingleton().isClusterMode()) { //销毁集群下兄弟节点的session if(user_id != null && user_id.length() > 0) { List<RmCommonVo> lvo = RmProjectHelper.getCommonServiceInstance().doQuery("select * from RM_USER_ONLINE_RECORD where user_id='" + user_id + "' and login_sign='" + session_id + "'"); if(lvo.size() > 0) { RmCommonVo vo = lvo.get(0); String cluster_node_id = vo.getString("cluster_node_id"); IRmSessionService remoteSs = getRemoteSessionService(cluster_node_id); if(remoteSs != null) { int result = remoteSs.forceLogoutUserLocal(new String[]{session_id}, msg); sendRemoteSuccess = result == 1; } } } } if(!sendRemoteSuccess) { //如果单机模式或集群模式下调用远程失败,本地执行清理动作 forceLogoutUserLocal(new String[]{session_id}, msg); } return true; } public List<RmUserSessionVo> listSessionLocal(String[] sessionIds) { final Map<String, HttpSession> mSession = RmSessionListener.getSessions(); List<RmUserSessionVo> result = new ArrayList<RmUserVo.RmUserSessionVo>(); for(String sessionId : sessionIds) { RmUserSessionVo vo = null; HttpSession session = mSession.get(sessionId); if(session != null) { vo = new RmUserSessionVo(); if(session.getAttribute(IGlobalConstants.RM_USER_VO) != null) { org.quickbundle.project.login.RmUserVo userVo = (org.quickbundle.project.login.RmUserVo)session.getAttribute(IGlobalConstants.RM_USER_VO); RmPopulateHelper.populate(vo, userVo); populateSessionVo(vo, session); } } result.add(vo); } return result; } public int forceLogoutUserLocal(String[] sessionIds, String message) { int result = 0; for(String sessionId : sessionIds) { HttpSession session = RmSessionListener.getSessionById(sessionId); if(session != null) { session.setAttribute(IRmLoginConstants.LOGOUT_TYPE, IRmLoginConstants.LogoutType.FORCE_LOGOUT.value()); getLoginService().executeDestroyUserInfo(session); session.setAttribute(IGlobalConstants.SystemPara.system_message.name(), message); result ++; } } return result; } }