导航
- 先上思维图纸
- 第一步: 参考了课本(如题教材)实现了Listener
- 第二步:个性化适配
- 第三步:实现JSP界面
- 总体问题:
刚看到的时候心里想的是写一个Servlet集成Listener的相关接口实现。然后JSP的JS每1ms获取一次doGet()中的数据实时刷新。
但是中途不知道出现什么问题,老是不成功。
然后更换了在Listener之外重新写了一个Servlet,但是Context中的数据共享老是失败。
最后更换了方案,Listener将数据先传输到log.txt文件,JS实时将数据从txt文件中获取,传递给HTML。
但是这个方案出现了很大的问题,就是响应的时间过长(长到怀疑人生,中途我还以为自己方案出问题了,关闭服务器重新调试),这只是个“捷径方案”,在这篇总结写完之后还是要重新尝试Servlet集成的方案。响应时间应该可以正常一些。
其实就是懒得写Servlet (大雾)
先上思维图纸
第一步: 参考了课本(如题教材)实现了Listener
但是在后续发现需要个性化调整的部分有很多。
package com.filter;import java.io.PrintWriter
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;/*** Application Lifecycle Listener implementation class OnLineuser**/
@WebListener
public class OnLineuser implements ServletContextListener, HttpSessionListener {private int count=0;private ServletContext context=null;/*** Default constructor. */public OnLineuser() {// TODO Auto-generated constructor stub/*** @see HttpSessionListener#sessionCreated(HttpSessionEvent)*/public void sessionCreated(HttpSessionEvent se) { // TODO Auto-generated method stubcount++;context.setAttribute("count", (Integer)count);System.out.println("创建session方法启动,当前Session数:"+count);}/*** @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)*/public void sessionDestroyed(HttpSessionEvent se) { // TODO Auto-generated method stubcount--;context.setAttribute("count", (Integer)count);System.out.println("删除session方法启动,当前Session数:"+count);}/*** @see ServletContextListener#contextDestroyed(ServletContextEvent)*/public void contextDestroyed(ServletContextEvent sce) { // TODO Auto-generated method stubcontext=null;System.out.println("消除context方法启动");}/*** @see ServletContextListener#contextInitialized(ServletContextEvent)*/public void contextInitialized(ServletContextEvent sce) { // TODO Auto-generated method stubcontext=sce.getServletContext();System.out.println("创建context方法启动");}}
第二步:个性化适配
加上输出count输出到log.txt文件的方法,删去我们愚蠢的 方案不需要的Context监听接口。
package com.filter;import java.io.FileOutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;/*** Application Lifecycle Listener implementation class OnLineuser**/
@WebListener
public class OnLineuser implements ServletContextListener, HttpSessionListener {private int count=0;/*** Default constructor. */public OnLineuser() {// TODO Auto-generated constructor stub}private void logout(int message){PrintWriter out=null;try {out=new PrintWriter(new FileOutputStream("D://ServletDemo/src/main/webapp/log.txt"));out.println(message);out.close();}catch(Exception e) {out.close();e.printStackTrace();//控制台输出;}}/*** @see HttpSessionListener#sessionCreated(HttpSessionEvent)*/public void sessionCreated(HttpSessionEvent se) { // TODO Auto-generated method stubcount++;System.out.println("创建session方法启动,当前Session数:"+count);logout(count);}/*** @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)*/public void sessionDestroyed(HttpSessionEvent se) { // TODO Auto-generated method stubcount--;System.out.println("删除session方法启动,当前Session数:"+count);logout(count);}
}
第三步:实现JSP界面
着重注意JS部分,是实现AJAX技术的关键。注意实现URL:count+i的操作是实现多次请求的技术关键点。使服务器判断这重复发的请求不是一个而是多个,避免不需要的意外。关键使每1ms重复获取数据一次。
<script type="text/javascript">var xmlHttp;var i=0;function createXMLHttpRequest(){xmlHttp=new XMLHttpRequest();}function updateUser(){createXMLHttpRequest();xmlHttp.onreadystatechange=processor;i=i+1;xmlHttp.open("GET", "log.txt?count="+i);<!--关键1-->xmlHttp.send(null);}function processor(){if(xmlHttp.readyState==4){if(xmlHttp.status==200){document.getElementById("count").innerHTML=xmlHttp.responseText;}}}setInterval("updateUser();",1);<!--关键2-->
</script>
<title>动态显示在线人数</title>
</head>
<body>在线人数:<br><div id="count"></div><!-- 直接连接log.txt -->
</body>
</html>
总体问题:
长延迟是程序的最大问题,从Listener传递数据到log.txt的速度很快(正常),但是从txt到JS的反应速度慢的可怕。下一节使用Servlet内置Listener看看反应速度会不会快点。