目录
- 一、简介(使用的Java监听器)
- 1、使用HttpSessionAttributeListener , HttpSessionListener 来显示的在线统计和计数功能。使用的 springboot框架!
- 2、使用ServletContext容器,对在线统计、登录统计、登录信息进行存储。
- 3、确保了只有一个账号是登录状态,其他电脑登录,会将当前登出。
- 4、确保一台计算机只能同时登录一个账号。登录其他person,会将当前的person登出。
- 二、自定义的控制层(controller层)
- 1、person登录
- 2、person退出。
- 三、自定义的监听器
- 四、监听器注入web容器中
一、简介(使用的Java监听器)
1、使用HttpSessionAttributeListener , HttpSessionListener 来显示的在线统计和计数功能。使用的 springboot框架!
2、使用ServletContext容器,对在线统计、登录统计、登录信息进行存储。
3、确保了只有一个账号是登录状态,其他电脑登录,会将当前登出。
4、确保一台计算机只能同时登录一个账号。登录其他person,会将当前的person登出。
二、自定义的控制层(controller层)
1、person登录
@ApiOperation(value = "person登录!")
@PostMapping(value = "/loginPerson")
public Result<Person> loginPerson(String username , String password , HttpSession session){
//判断用户是否正确!
Result<Person> result = personService.selectByUsername(username.trim());
Person person = result.getData();
if(person != null){
Person inP = new Person();
inP.setPersonId(person.getPersonId());
inP.setUsername(username.trim());
inP.setPassword(password.trim());
Person outP = EncryptUserUtil.encryPerson(inP);
if(!outP.getPassword().equals(person.getPassword())){
return new Result("-1","密码错误!");
}
}else {
return new Result("-1","该用户名不存在!");
}
//如果改session中已经绑定person信息,那么删除这个。
ConcurrentHashMap<String , HttpSession> personL = (ConcurrentHashMap<String , HttpSession>)session.getServletContext().getAttribute("personL");
Person pe = (Person) session.getAttribute("person");
if(pe != null){
if(personL != null && personL.containsKey(pe.getUsername().trim())){
//peronsL中移除改person及其对应的session信息。
personL.remove(pe.getUsername().trim());
//更新容器。
session.getServletContext().setAttribute("personL" , personL);
System.out.println(pe.getUsername() + ":out!");
}
session.removeAttribute("person");
}
//如果改username已经在其他地方登录,那么销毁该username的session数据。(换机器登录了)
if(personL != null && personL.containsKey(username.trim())){
//从personL中拿到username对应的session数据,并且销毁!
//注意:personL数据的更新在销毁线程的函数中。
personL.get(username.trim()).invalidate();
System.out.println(username.trim() + ":out!");
}
//获取登录人数!
Integer count = (Integer)session.getServletContext().getAttribute("login");
//对登录人数进行限制,下为测试,限制三人。
if(count!= null && count>= 3){
return new Result<>("-5","登录人数已满,请耐心等候,或者刷新登录");
}
//如果personL是空的。那么创建该map。
if(personL == null){
personL = new ConcurrentHashMap<String , HttpSession>();
}
//将当前session与当前的person进行绑定。在监听器中,更新personL数据。
session.setAttribute("person" , person);
return new Result<Person>(person);
}
2、person退出。
@ApiOperation(value = "用户退出登录。")
@GetMapping("/lostPerson")
public Result lostPerson(HttpSession session){
Person person = (Person)session.getAttribute("person");
if(person != null){
HashMap<String , HttpSession> personL = (HashMap<String , HttpSession>)session.getServletContext().getAttribute("personL");
if(personL != null && personL.containsKey(person.getUsername().trim())){
personL.remove(person.getUsername().trim());
session.getServletContext().setAttribute("personL" , personL);
}
session.removeAttribute("person");
}
return new Result();
}
三、自定义的监听器
package com.cc.listener;
import com.cc.model.Person;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ServletContext;
import javax.servlet.http.*;
import java.util.concurrent.ConcurrentHashMap;
/*
* 关于HttpSessionAttributeListener的总结
* 1、attributeAdded 方法,是在session添加setAttribute时被触发!
* 2、attributeRemoved方法,是在session移除removeAttribute后被触发。注意是属性已经移除后,才被触发!不能获取相关属性。
* 3、sessionCreated方法,是在session被创建的时候被触发。
* 4、sessionDestroyed方法,是在session被销毁的时候被触发。在改方法中可以获取设置的相关属性。
* 5、sessionDestroyed方法执行:先执行改方法,再执行attributeRemoved方法;
*/
@Data
@Slf4j
public class MyLoginListener implements HttpSessionAttributeListener , HttpSessionListener {
//在线计数
private static int activeSessions = 0;
//登录人员计数
private static int activeLoginSessions = 0;
//存放person的username和登录对应的session!
private static ConcurrentHashMap<String , HttpSession> personL;
/**
* controller中session.setAttribute("person" , person)的时候触发!-代表person登录。
* @param se
*/
public void attributeAdded(HttpSessionBindingEvent se) {
//获取session.setAttribute("person" , person)中的 “person”
String name = se.getName();
//如果是person登录
if("person".equalsIgnoreCase(name)){
HttpSession session = se.getSession();
Person person = (Person)session.getAttribute("person");
//获取容器
ServletContext app = session.getServletContext();
//容器中获取所有person的登录信息。
personL = (ConcurrentHashMap<String , HttpSession>)app.getAttribute("personL");
if(personL == null){
//如果容器中没有,那么初始化一个personL.
personL = new ConcurrentHashMap<String , HttpSession>();
}
//将当前用户放入到personL中。
personL.put(person.getUsername() , session);
//登录计数添加。
activeLoginSessions++;
//将登录计数,和person对应的session的map数据放入到app容器中。
app.setAttribute("login" , activeLoginSessions);
app.setAttribute("personL" , personL);
System.out.println(person.getUsername() + ":login!");
}
}
/**
* 某个person用户退出session.removeAttribute("person")的时候触发!
* @param se
*/
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("------------测试销毁调用!-----------");
String name = se.getName();
//把session.removeAttribute("person")定义为退出登录。
if("person".equalsIgnoreCase(name)){
HttpSession session = se.getSession();
ServletContext app = session.getServletContext();
//登录计数减少!
if(activeLoginSessions > 0){
activeLoginSessions--;
}
//重新写入到容器中。
app.setAttribute("login" , activeLoginSessions);
System.out.println("----outPerson----");
/*app.setAttribute("personL" , personL);*/
}
}
public void attributeReplaced(HttpSessionBindingEvent se) {
}
/**
* session创建的时候触发!
* @param se
*/
public void sessionCreated(HttpSessionEvent se){
//在线计数加一。
activeSessions++;
//后去容器。
ServletContext servletContext = se.getSession().getServletContext();
//将在线计数写入容器中。
servletContext.setAttribute("online" , activeSessions);
/*System.out.println("----create----" + personL);*/
}
/**
* session销毁的时候触发!
* 注意:这里不需要登录计数减一,经过实测,再执行sessionDestroyed方法后,会自动执行attributeRemoved方法
* @param se
*/
public void sessionDestroyed(HttpSessionEvent se) {
//在线计数减一。
if(activeSessions > 0){
activeSessions--;
}
//在线计数更新到容器中
ServletContext servletContext = se.getSession().getServletContext();
servletContext.setAttribute("online" , activeSessions);
//获取销毁的session。
HttpSession session = se.getSession();
//如果改session中含person,说明是person登录的session。
Person person = (Person)session.getAttribute("person");
if(person != null ){
//在容器中获取person的信息map数据。
personL = (ConcurrentHashMap<String , HttpSession>)servletContext.getAttribute("personL");
if(personL != null){
//如果personL数据存在,那么将personL中对应的perosn登录session信息移除!
personL.remove(person.getUsername());
}else {
personL = new ConcurrentHashMap<String , HttpSession>();
}
//更新容器中的personL。
servletContext.setAttribute("personL" , personL);
}
System.out.println("--------destroy session--------:" + person);
}
}
四、监听器注入web容器中
@Configuration
@Data
public class MyLoginLisConfig {
final MyLoginListener myLoginListener;
public MyLoginLisConfig (){
this.myLoginListener = new MyLoginListener();
}
@Bean
public ServletListenerRegistrationBean<MyLoginListener> listenerRegistrationBean() {
ServletListenerRegistrationBean<MyLoginListener> registrationBean = new ServletListenerRegistrationBean<>();
registrationBean.setListener(myLoginListener);
return registrationBean;
}
}