功能步骤:
1. 当用户访问登录页面时,Logincontroller的showLoginForm方法被调用,返回登录页面的视图名字。
2. 用户提交表单,调用LoginController的login方法。
3.login方法
4.登录验证通过,home方法会被调用,该方法从会话中取在线人数,并添加到模型中,之后返回home。
5.OnlineUserCounterListener
是一个实现了HttpSessionListener
接口的监听器,它监听会话(session)的创建和销毁事件。
每次登录验证通过,也就是登录成功,会话(session)都会被创建,sessionCreated
方法会被调用,这样就可以直接通过session来获取在线人数,但是为了更方便管理和操作在线用户的信息,可以再创建一个OnlineUserManager
类:
功能:添加用户,删除用户,统计在线人数,还可以拥有其他功能比如,比如获取在线用户的详细信息,这个可以根据实际需要再进行完善。
import java.util.HashSet;
import java.util.Set;
/**
* @author a1002
*/
public class OnlineUserManager {
private static Set<String> onlineUsers = new HashSet<>();
public static void addUser(String username) {
onlineUsers.add(username);
}
public static void removeUser(String username) {
onlineUsers.remove(username);
}
public static int getOnlineCount() {
return onlineUsers.size();
}
}
从OnlineUserManager
中获取在线人数,并将其存储在ServletContext
中,以便全局访问。
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
int onlineCount = OnlineUserManager.getOnlineCount();
servletContext.setAttribute("onlineCount", onlineCount);
}
为了使OnlineUserCounterListener
生效,需要将其注册为一个监听器。在配置类AppConfig
中,使用@Bean
注解将OnlineUserCounterListener
实例化,并将其返回。这样,它就会被自动注册到Spring的上下文中。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
@Bean
public OnlineUserCounterListener onlineUserCounterListener() {
return new OnlineUserCounterListener();
}
}
从以上步骤可以得出:OnlineUserManager是一个用户全局的用户管理,同时,里面存储的数据会在每一个session被创建的时候()同步到一个全局的servletContext中。
每当用户登录验证成功后,OnlineUserManager中的用户会加1,session中的onlineCount也会更新,并被发送给home.html用来在页面上显示数据。
扩展:
登录过程中通常会创建一个会话(session)。会话是在用户与应用程序之间建立的一个状态保持机制,用于跟踪用户的登录状态和存储相关的会话数据。
在Web应用程序中,会话是通过使用会话ID来实现的。当用户成功登录时,服务器会为该用户创建一个唯一的会话ID,并将其与用户的会话数据关联起来。会话ID可以通过Cookie、URL重写或其他方式发送到客户端,并在后续的请求中被客户端发送回服务器。
服务器可以根据接收到的会话ID识别特定的会话,并根据需要访问会话数据。在登录过程中,常见的做法是将用户的身份信息存储在会话中,存储用户对象在会话中的好处是,它允许在用户的后续请求中访问用户的相关信息,而无需重复进行身份验证。通过使用会话,在用户与应用程序之间保持登录状态,并且可以在需要时从会话中检索用户信息,以便进行授权、个性化设置或其他操作。
但是以上步骤还是存在一个问题,如果只删除了某个用户的会话(session),而未在OnlineUserManager
中更新相应的在线用户列表,可能会导致数据不一致的问题。
在典型的应用程序中,会话的创建和销毁通常是由应用程序框架或服务器自动处理的。当会话过期、用户注销或其他条件满足时,会话将被销毁。在这种情况下,会自动触发 HttpSessionListener
监听器中的 sessionDestroyed
方法,所以我们可以在该方法中更新 OnlineUserManager
中的在线用户列表。
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
User user = (User) session.getAttribute("user");
if (user != null) {
// 从在线用户列表中移除该用户
OnlineUserManager.removeUser(user.getUsername());
}
}
当然,也还有一些示例,比如
-
使用过期机制:在会话创建时设置合适的会话过期时间。这样,当会话超过一定时间没有活动时,它将自动销毁,并触发
HttpSessionListener
中的sessionDestroyed
方法。 -
错误处理和异常情况处理:在应用程序中处理会话销毁的异常情况。例如,通过定期检查会话是否仍然有效,并在发现无效会话时进行清理和更新。
扩展:ServletContext
是一个在整个应用程序范围内共享数据的对象,它可以存储和获取全局的数据。
当在线人数发生变化时,可以将最新的在线人数存储在 ServletContext
中,以便在整个应用程序范围内共享这个数据。同时,在每个会话中,也可以将当前的在线人数存储在会话的属性中,以便在该会话的请求中访问和使用。
通过将在线人数存储在 ServletContext中
,可以在整个应用程序中共享这个数据。而将在线人数存储在会话中,则可以在每个会话的请求中方便地获取并使用这个数据。
ServletContext
和会话(session)是不同的范围和生命周期的对象。ServletContext
是在应用程序启动时创建的,可以在整个应用程序的生命周期内共享数据。而会话是在用户与应用程序之间建立的,用于跟踪用户的状态和存储相关的会话数据。
所以,ServletContext
存储的在线人数是全局的,而会话中存储的在线人数是特定会话的状态。
这也就是上述补充的步骤中所在意的问题。
如果大家还有什么问题或者是发现还存在一些bug,都可以在评论区进行讨论,当然,如果应用到实际开发中的话,我这些东西是绝对不够用的
效果展示(页面有些拉,将就着看吧)
直接输入:http://localhost:8080/login
会跳转到:http://localhost:8080/home
之后再多开几个登录账号,但是如果账号与之前的有重复的话,这个是不计入在线人数中的。
登录不同的账号,进入主页都会发现在线人数会加1.