监听器应用:统计人数、自定义扫描器、踢人小案例(修订版)
从第一篇已经讲解过了监听器的基本概念,以及Servlet各种的监听器。这篇博文主要讲解的是监听器的应用。
统计网站在线人数
ps:这个可以使用WebSocket来做,但这里讲解的是监听器,所以这里以监听器来举例子!
分析
我们在网站中一般使用Session来标识某用户是否登陆了,如果登陆了,就在Session域中保存相对应的属性。如果没有登陆,那么Session的属性就应该为空。
现在,我们想要统计的是网站的在线人数。我们应该这样做:我们监听是否有新的Session创建了,如果新创建了Sesssion,那么在线人数就应该+1。这个在线人数是整个站点的,所以应该有Context对象保存。
大致思路:
- 监听Session是否被创建了
- 如果Session被创建了,那么在Context的域对象的值就应该+1
- 如果Session从内存中移除了,那么在Context的域对象的值就应该-1.
代码
- 监听器代码:
public class CountOnline implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { //获取得到Context对象,使用Context域对象保存用户在线的个数 ServletContext context = se.getSession().getServletContext(); //直接判断Context对象是否存在这个域,如果存在就人数+1,如果不存在,那么就将属性设置到Context域中 Integer num = (Integer) context.getAttribute("num"); if (num == null) { context.setAttribute("num", 1); } else { num++; context.setAttribute("num", num); } } public void sessionDestroyed(HttpSessionEvent se) { ServletContext context = se.getSession().getServletContext(); Integer num = (Integer) se.getSession().getAttribute("num"); if (num == null) { context.setAttribute("num", 1); } else { num--; context.setAttribute("num", num); } } } - 显示页面代码:
在线人数:${num} 测试
我们每使用一个浏览器访问服务器,都会新创建一个Session。那么网站的在线人数就会+1。
使用同一个页面刷新,还是使用的是那个Sesssion,所以网站的在线人数是不会变的。
自定义Session扫描器
我们都知道Session是保存在内存中的,如果Session过多,服务器的压力就会非常大。
但是呢,Session的默认失效时间是30分钟(30分钟没人用才会失效),这造成Seesion可能会过多(没人用也存在内存中,这不是明显浪费吗?)
当然啦,我们可以在web.xml文件中配置Session的生命周期。但是呢,这是由服务器来做的,我嫌它的时间不够准确。(有时候我配置了3分钟,它用4分钟才帮我移除掉Session)
所以,我决定自己用程序手工移除那些长时间没人用的Session。
分析
要想移除长时间没人用的Session,肯定要先拿到全部的Session啦。所以我们使用一个容器来装载站点所有的Session。。
只要Sesssion一创建了,就把Session添加到容器里边。毫无疑问的,我们需要监听Session了。
接着,我们要做的就是隔一段时间就去扫描一下全部Session,如果有Session长时间没使用了,我们就把它从内存中移除。隔一段时间去做某事,这肯定是定时器的任务呀。
定时器应该在服务器一启动的时候,就应该被创建了。因此还需要监听Context
最后,我们还要考虑到并发的问题,如果有人同时访问站点,那么监听Session创建的方法就会被并发访问了。定时器扫描容器的时候,可能是获取不到所有的Session的。
这需要我们做同步
于是乎,我们已经有大致的思路了
- 监听Session和Context的创建
- 使用一个容器来装载Session
- 定时去扫描Session,如果它长时间没有使用到了,就把该Session从内存中移除。
- 并发访问的问题
代码
- 监听器代码:
public class Listener1 implements ServletContextListener, HttpSessionListener { //服务器一启动,就应该创建容器。我们使用的是LinkList(涉及到增删)。容器也应该是线程安全的。 List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>()); //定义一把锁(Session添加到容器和扫描容器这两个操作应该同步起来) private Object lock = 1; public void contextInitialized(ServletContextEvent sce) { Timer timer = new Timer(); //执行我想要的任务,0秒延时,每10秒执行一次 timer.schedule(new MyTask(list, lock), 0, 10 * 1000); } public void sessionCreated(HttpSessionEvent se) { //只要Session一创建了,就应该添加到容器中 synchronized (lock) { list.add(se.getSession()); } System.out.println("Session被创建啦"); } public void sessionDestroyed(HttpSessionEvent se) { System.out.println("Session被销毁啦。"); } public void contextDestroyed(ServletContextEvent sce) { } } - 任务代码:
/* * 在任务中应该扫描容器,容器在监听器上,只能传递进来了。 * * 要想得到在监听器上的锁,也只能是传递进来 * * */ class MyTask extends TimerTask { private List<HttpSession> sessions; private Object lock; public MyTask(List<HttpSession> sessions, Object lock) { this.sessions = sessions; this.lock = lock; } @Override public void run() { synchronized (lock) { //遍历容器 for (HttpSession session : sessions) { //只要15秒没人使用,我就移除它啦 if (System.currentTimeMillis() - session.getLastAccessedTime() > (1000 * 15)) { session.invalidate(); sessions.remove(session); } } } } } - 测试:
15秒如果Session没有活跃,那么就被删除!
- 使用集合来装载我们所有的Session
- 使用定时器来扫描session的声明周期【由于定时器没有session,我们传进去就好了】
- 关于并发访问的问题,我们在扫描和检测session添加的时候,同步起来就好了【当然,定时器的锁也是要外面传递进来的】
踢人小案列
列出所有的在线用户,后台管理者拥有踢人的权利,点击踢人的超链接,该用户就被注销了。
分析
首先,怎么能列出所有的在线用户呢??一般我们在线用户都是用Session来标记的,所有的在线用户就应该用一个容器来装载所有的Session。。
我们监听Session的是否有属性添加(监听Session的属性有添加、修改、删除三个方法。如果监听到Session添加了,那么这个肯定是个在线用户!)。
装载Session的容器应该是在Context里边的【属于全站点】,并且容器应该使用Map集合【待会还要通过用户的名字来把用户踢了】
思路:
- 写监听器,监听是否有属性添加在Session里边了。
- 写简单的登陆页面。
- 列出所有的在线用户
- 实现踢人功能(也就是摧毁Session)
代码
- 监听器
public class KickPerson implements HttpSessionAttributeListener { // Public constructor is required by servlet spec public KickPerson() { } public void attributeAdded(HttpSessionBindingEvent sbe) { //得到context对象,看看context对象是否有容器装载Session ServletContext context = sbe.getSession().getServletContext(); //如果没有,就创建一个呗 Map map = (Map) context.getAttribute("map"); if (map == null) { map = new HashMap(); context.setAttribute("map", map); } //--------------------------------------------------------------------------------------- //得到Session属性的值 Object o = sbe.getValue(); //判断属性的内容是否是User对象 if (o instanceof User) { User user = (User) o; map.put(user.getUsername(), sbe.getSession()); } } public void attributeRemoved(HttpSessionBindingEvent sbe) { /* This method is called when an attribute is removed from a session. */ } public void attributeReplaced(HttpSessionBindingEvent sbe) { /* This method is invoked when an attibute is replaced in a session. */ } } - 登陆页面
<form action="${pageContext.request.contextPath }/LoginServlet" method="post"> 用户名:<input type="text" name="username"> <input type="submit" value="登陆"> </form> - 处理登陆Servlet
//得到传递过来的数据 String username = request.getParameter("username"); User user = new User(); user.setUsername(username); //标记该用户登陆了! request.getSession().setAttribute("user", user); //提供界面,告诉用户登陆是否成功 request.setAttribute("message", "恭喜你,登陆成功了!"); request.getRequestDispatcher("/message.jsp").forward(request, response); - 列出在线用户
<c:forEach items="${map}" var="me"> ${me.key} <a href="${pageContext.request.contextPath}/KickPersonServlet?username=${me.key}">踢了他吧</a> <br> </c:forEach> - 处理踢人的Servlet
String username = request.getParameter("username"); //得到装载所有的Session的容器 Map map = (Map) this.getServletContext().getAttribute("map"); //通过名字得到Session HttpSession httpSession = (HttpSession) map.get(username); httpSession.invalidate(); map.remove(username); //摧毁完Session后,返回列出在线用户页面 request.getRequestDispatcher("/listUser.jsp").forward(request, response); 测试
使用多个浏览器登陆来模拟在线用户(同一个浏览器使用的都是同一个Session)
监听Seesion的创建和监听Session属性的变化有啥区别???
- Session的创建只代表着浏览器给服务器发送了请求。会话建立
- Session属性的变化就不一样了,登记的是具体用户是否做了某事(登陆、购买了某商品)
文章来源:https://dwz.cn/kQKaUdDT
作者:Java3y
探索新时代网络工具:超越Shadowrocket的更好选择与使用指南
在当今互联网环境中,网络工具的需求日益增长,尤其是在许多用户面临实际浏览限制的情况下。虽然Shadowrocket作为一款VPN工具在市场上颇受欢迎,但技术的发展和用户需求的多样化催生了更多优秀的替代方案。本文将深入探讨一些比Shadowrocket更好用的工具,并提供详细的使用及配置教程,帮助读者在复杂的网络环境中找到最适合自己的解决方案。
为什么需要寻找Shadowrocket的替代工具?
Shadowrocket主要针对iOS设备设计,虽然在苹果用户中拥有一定的市场份额,但其跨平台兼容性相对较弱,功能上也可能无法满足所有用户的需求。随着网络环境的不断变化,用户对工具的要求也越来越高:包括连接速度、安全性、可用性以及多设备支持等方面。因此,探索更多灵活、高效且安全的工具显得尤为重要。
深度解析比Shadowrocket更好用的工具
在选择合适的工具时,我们需要综合考虑软件的功能、性能以及适用场景。以下是几款在市场上表现优异、广受好评的工具推荐:
1. V2Ray:灵活性与安全性的完美结合
V2Ray是一个开源项目,由社区驱动开发,旨在提供多种传输协议和强大的自定义功能。其设计理念强调灵活性和扩展性,能够适应各种复杂的网络环境。
优点详解: - 灵活的路由选择:V2Ray支持多种协议(如VMess、Shadowsocks等),用户可以根据需要自定义路由规则,实现流量的精细控制。 - 高安全性:通过先进的加密技术,V2Ray能够有效保护用户数据免受窃听和篡改,确保隐私安全。 - 强大的抗检测能力:V2Ray的流量伪装功能可以帮助用户绕过防火墙的监测,保持网络的稳定连接。
适用场景:适用于对网络自由度和安全性有较高要求的用户,如技术人员、隐私意识较强的互联网用户。
2. Clash:功能全面的跨平台代理客户端
Clash是一款功能强大且易于使用的代理客户端,支持Windows、macOS、Linux以及移动设备等多种平台。其设计注重用户体验,提供了直观的界面和丰富的配置选项。
优点详解: - 流量显示与规则分流:Clash可以实时显示网络流量,并根据用户设定的规则自动选择最优节点,提升浏览体验。 - 环境分析能力:工具内置智能分析功能,能够自动检测网络环境并调整连接策略,确保稳定性。 - 友好的用户界面:Clash的配置界面简洁明了,即使是初学者也能快速上手。
适用场景:适合需要多设备同步和规则自定义的用户,如经常在不同网络环境下切换的商务人士或学生。
3. Surfboard:智能高效的节点管理工具
Surfboard是一款专注于节点管理和分流功能的工具,以其快速的节点切换和智能分流能力著称。它的设计目标是简化用户的操作流程,提升连接效率。
优点详解: - 快速节点选择:Surfboard通过智能算法自动选择最佳节点,减少延迟和提高连接速度。 - 自适应分流:工具能够根据网络状况自动调整分流策略,确保流畅的浏览体验。 - 简洁易用的界面:Surfboard的界面设计直观,用户只需简单配置即可开始使用。
适用场景:适用于追求高效连接和简单操作的用户,如日常浏览和流媒体消费群体。
如何选择比Shadowrocket更好用的工具
在众多工具中做出选择时,可以考虑以下关键因素:
- 连接速度:工具的响应速度和延迟直接影响用户体验,建议通过测试多个节点选择最优解。
- 可用性:确保工具在国内外均能稳定使用,避免因地域限制导致连接中断。
- 安全性:优先选择支持强加密和隐私保护功能的工具,防止数据泄露。
- 兼容性:检查工具是否支持你的所有设备(如手机、电脑等),以便无缝切换使用。
详细配置与使用教程
以下是针对上述工具的简单配置步骤,帮助用户快速上手:
V2Ray的配置与使用
- 下载:访问V2Ray官方网站(如v2ray.com),根据你的操作系统下载对应的客户端版本。
- 配置:可以从社区获取现成的配置文件,或根据官方文档自定义设置(如选择传输协议和路由规则)。
- 运行:启动V2Ray客户端,导入配置文件后选择连接节点,即可开始使用。
Clash的配置与使用
- 安装:从Clash的GitHub页面或官方渠道下载适合你设备的客户端版本。
- 订阅:通过添加节点订阅链接(可从服务商获取),自动导入节点信息。
- 管理配置:在客户端中选择合适的规则集(如分流规则),测试连接后即可享受稳定服务。
Surfboard的配置与使用
- 安装:访问Surfboard官方网站或应用商店,下载并安装客户端。
- 节点配置:在设置中添加节点信息,并启用自动更新功能以保持节点列表最新。
- 连接测试:点击连接按钮,检查是否能正常访问网络,必要时切换节点优化体验。
常见问题解答(FAQ)
Shadowrocket和推荐工具有什么不同?
Shadowrocket主要专注于iOS平台,而V2Ray、Clash等工具支持跨平台使用,提供更灵活的配置和更强的性能,适合多设备用户。
如何提高VPN工具的速度?
可以尝试更换到负载较低的节点,或选择付费套餐以获得更稳定的带宽。定期进行速度测试也有助于优化连接。
免费节点是否安全?
免费节点往往存在速度慢和安全风险(如数据日志记录),建议选择信誉良好的付费服务以确保隐私和网络稳定。
总结与点评
通过以上分析和比较,我们可以看到,V2Ray、Clash和Surfboard等工具在功能、安全性和易用性方面均表现出色,超越了Shadowrocket的局限性。在选择时,用户应根据自身需求(如设备兼容性、网络环境)进行权衡,优先考虑那些提供高质量服务和支持的工具。
语言精彩的点评:
在当今这个信息爆炸的时代,网络工具不仅是技术产品,更是用户通往自由世界的桥梁。V2Ray以其开源社区的活力,展现了技术创新的无限可能;Clash则像一位细心的管家,通过智能分流和友好界面,让复杂变得简单;Surfboard则以高效和自适应,成为快节奏生活中的得力助手。这些工具不仅仅是替代品,更是新时代网络自由的使者,帮助我们在数字世界中 navigate with confidence and ease. 最终,选择适合自己的工具,就像选择一位可靠的旅伴,能让每一次网络之旅都变得更加顺畅和安心。
希望本文能帮助读者找到理想的工具,享受更自由、安全的网络体验。如果有任何疑问,欢迎在评论区交流分享!
版权声明:
作者: freeclashnode
链接: https://www.freeclashnode.com/news/article-1920.htm
来源: FreeClashNode
文章版权归作者所有,未经允许请勿转载。
热门文章
- 11月4日|19.4M/S,Singbox节点/Shadowrocket节点/V2ray节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月15日|21M/S,Clash节点/V2ray节点/Singbox节点/SSR节点|免费订阅机场|每天更新免费梯子
- 10月30日|22.4M/S,SSR节点/V2ray节点/Clash节点/Singbox节点|免费订阅机场|每天更新免费梯子
- 11月1日|19.4M/S,Singbox节点/Clash节点/V2ray节点/Shadowrocket节点|免费订阅机场|每天更新免费梯子
- 10月29日|21M/S,V2ray节点/Singbox节点/SSR节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月6日|19.7M/S,Clash节点/V2ray节点/Shadowrocket节点/Singbox节点|免费订阅机场|每天更新免费梯子
- 10月31日|19.4M/S,Clash节点/V2ray节点/SSR节点/Singbox节点|免费订阅机场|每天更新免费梯子
- 11月8日|22.1M/S,Shadowrocket节点/Singbox节点/Clash节点/V2ray节点|免费订阅机场|每天更新免费梯子
- 10月25日|20.2M/S,Singbox节点/SSR节点/V2ray节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月5日|18.6M/S,Shadowrocket节点/Clash节点/V2ray节点/Singbox节点|免费订阅机场|每天更新免费梯子
最新文章
- 11月19日|18.7M/S,V2ray节点/SSR节点/Singbox节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月18日|19.6M/S,Singbox节点/Clash节点/V2ray节点/SSR节点|免费订阅机场|每天更新免费梯子
- 11月17日|22.9M/S,Clash节点/V2ray节点/Singbox节点/Shadowrocket节点|免费订阅机场|每天更新免费梯子
- 11月16日|21.4M/S,Shadowrocket节点/Singbox节点/V2ray节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月15日|21M/S,Clash节点/V2ray节点/Singbox节点/SSR节点|免费订阅机场|每天更新免费梯子
- 11月14日|18.2M/S,Singbox节点/Shadowrocket节点/Clash节点/V2ray节点|免费订阅机场|每天更新免费梯子
- 11月13日|21.1M/S,Singbox节点/SSR节点/Clash节点/V2ray节点|免费订阅机场|每天更新免费梯子
- 11月12日|22.4M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费订阅机场|每天更新免费梯子
- 11月11日|22.8M/S,V2ray节点/Singbox节点/Clash节点/Shadowrocket节点|免费订阅机场|每天更新免费梯子
- 11月10日|19.4M/S,Clash节点/V2ray节点/Shadowrocket节点/Singbox节点|免费订阅机场|每天更新免费梯子
归档
- 2025-11 32
- 2025-10 56
- 2025-09 55
- 2025-08 49
- 2025-07 31
- 2025-06 30
- 2025-05 31
- 2025-04 31
- 2025-03 383
- 2025-02 360
- 2025-01 403
- 2024-12 403
- 2024-11 390
- 2024-10 403
- 2024-09 388
- 2024-08 402
- 2024-07 424
- 2024-06 446
- 2024-05 184
- 2024-04 33
- 2024-03 32
- 2024-02 29
- 2024-01 50
- 2023-12 53
- 2023-11 32
- 2023-10 32
- 2023-09 3