刚看到的时候心里想的是写一个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 stub
count++;
context.setAttribute("count", (Integer)count);
System.out.println("创建session方法启动,当前Session数:"+count);
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generated method stub
count--;
context.setAttribute("count", (Integer)count);
System.out.println("删除session方法启动,当前Session数:"+count);
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
context=null;
System.out.println("消除context方法启动");
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
context=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 stub
count++;
System.out.println("创建session方法启动,当前Session数:"+count);
logout(count);
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generated method stub
count--;
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看看反应速度会不会快点。