监听器通常用于监听 Web 应用程序中对象的创建、销毁等动作的发送,同时对监听的情况作出相应的处理,最常用于统计网站的在线人数、访问量等。
监听器大概分为以下几种:
- ServletContextListener:用来监听 ServletContext 属性的操作,比如新增、修改、删除。
- HttpSessionListener:用来监听 Web 应用种的 Session 对象,通常用于统计在线情况。
- ServletRequestListener:用来监听 Request 对象的属性操作。
通过 HttpSessionListener来统计当前在线人数、ip等信息,为了避免并发问题我们使用原子int来计数。
import lombok.extern.slf4j.Slf4j;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.concurrent.atomic.AtomicInteger;
@WebListener
@Slf4j
public class CustomHttpSessionListener implements HttpSessionListener {
public static AtomicInteger activeCount = new AtomicInteger(0);
@Override
public void sessionCreated(HttpSessionEvent sessionEvent) {
log.info("-------Incrementing Session Counter--------");
activeCount.incrementAndGet();
log.info("-------Session Created--------");
sessionEvent.getSession().setAttribute("onlineCount", activeCount.get());
log.info("【在线人数】人数增加为:{}", activeCount.get());
}
@Override
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
log.info("-------Session Destroyed--------");
activeCount.getAndDecrement();
sessionEvent.getSession().getServletContext().setAttribute("sessionCount", activeCount.get());
log.info("【在线人数】人数减少为:{}", activeCount.get());
}
}
或者使用 @Configuration + @Bean 的组合来创建:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@Configuration
public class WebCommoneConfig {
@Bean
public HttpSessionListener httpSessionListener() {
return new HttpSessionListener() {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Session Created with session id+" + se.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("Session Destroyed, Session id:" + se.getSession().getId());
}
};
}
}
创建 controller 控制器
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/admin")
public class AdminSessionController {
@GetMapping("addSession")
public String addSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("name", "haixiang");
return "当前在线人数" + session.getServletContext().getAttribute("onlineCount") + "人";
}
@GetMapping("removeSession")
public String removeSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "当前在线人数" + session.getServletContext().getAttribute("onlineCount") + "人";
}
@GetMapping("online")
public String online() {
return "当前在线人数" + CustomHttpSessionListener.activeCount.get() + "人";
}
}
HttpSession session = httpServletRequest.getSession(); 作用:该用户如果没有sesision则创建session ,有则取得session不创建。
一个浏览器对应一个session,你打开2个浏览器,看到count是2 ,是对的。但是你关了一个浏览器,再打开,应该是2不变才对,但是变成3 了,原因是session销毁的方法没有执行,重新打开时,服务器找不到用户原来的session ,重新创建了一个session,于是有3个session了,但是浏览器只有2个,也就是模拟应该是只有2个人在线上。