创建logout.Java用来记录当前在线的用户
@SuppressWarnings(value = "ALL")
public final class Logout implements Runnable {
private static final HashMap<String, LoginLog> MAP = new HashMap<>();
/**
* 在登陆时将已登录的用户信息放入map中
*
* @param userId 用户id
* @param loginLog 用户信息
*/
public static void putUserLoginLog(String userId, LoginLog loginLog) {
MAP.put(userId, loginLog);
}
/**
* 通过用户id得到用户信息
*
* @param userId
* @return
*/
public static LoginLog getLoginLog(String userId) {
return MAP.get(userId);
}
/**
* 通过用户信息更新用户最后操作时间
*
* @param userId
*/
public static void updateLoginLastTime(String userId) {
MAP.get(userId).setLastTime(System.currentTimeMillis());
}
/**
* 每30分钟检测一次map中的用户是否长时间不在线,防止用户不在线和还存在map中占用内存
*/
@Override
public void run() {
while (true) {
for (String userid : MAP.keySet()) {
if (System.currentTimeMillis() - MAP.get(userid).getLastTime() > 30 * 60 * 1000) {
MAP.remove(userid);
}
}
try {
Thread.sleep(30 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
创建拦截器类实现HandlerInterceptor
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object
o) throws Exception {
return true;
}
/**
* 通过shiro方法获取当前用户,
* 如果当前用户为空,表示第一次登陆,则可以继续执行,
* 否则通过用户id得到当前用户登陆信息,
* 如果没有获取到登陆信息,继续执行,
* 判断用户的sessionId是否相同并且用户最后登陆时间是否小于30分钟
* 如果成立则在shiro中退出登陆同时重定向到登陆页
*
* @param request
* @param response
* @param o
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o,
ModelAndView modelAndView) throws Exception {
//
LoginUser loginUser = CommonUtil.getLoginUser();
if (loginUser != null) {
String sessionId = request.getSession().getId();
String personId = loginUser.getPersonId();
LoginLog loginLog = Logout.getLoginLog(personId);
if (loginLog != null) {
long time = (System.currentTimeMillis() - loginLog.getLastTime()) / 1000 / 60 / 30;
if (!sessionId.equals(loginLog.getSessionId()) && time < 30) {
SecurityUtils.getSubject().logout();
response.sendRedirect(request.getContextPath() + "/index");
} else {
Logout.updateLoginLastTime(personId);
}
}
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e)
throws Exception {
}
}
创建监听器实现ApplicationContextAware
/**
* 在项目启动时开启用户登陆信息扫描的线程
*/
@Component
public class LogoutListener implements ApplicationContextAware {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Thread thread = new Thread(new Logout());
thread.start();
}
}