这些天,一直在做一个web小项目,也就是练习一下
Servlet,昨晚,想在网站中增加一个统计
访问量的功能,因为考虑到用多
线程每隔一定的时间去自动的保存访问量,会更准确(因为,你不用隔一段去保存访问量,如果突然断电了,访问量就会失去了),想法是好的,但做起来,还真的不容易:
以下程序是没有加载线程
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public
class InitServlet extends HttpServlet {
/**
* 关掉服务器时,会执行这个函数
*/
public void destroy() {
this.Thread_Init();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("</HTML>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
private void Thread_Init()
{
System.out.println("
thread调用");
String FilePath = this.getServletContext().getRealPath("Nums.text");
try {
FileWriter fileReader = new FileWriter(FilePath);
BufferedWriter buffer = new BufferedWriter(fileReader);
// 从ServletContext中读取数据
String nums = (String) this.getServletContext()
.getAttribute("nums");
// 把数据存到文本中
buffer.write(nums);
buffer.close();
fileReader.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
}
/**
* Initialization of the servlet. <br>
*
* @throws 初始化会先调用这个函数
*/
public void init() throws ServletException {
System.out.println("第一次调用");
String FilePath = this.getServletContext().getRealPath("Nums.text");
try {
FileReader fileReader = new FileReader(FilePath);
BufferedReader buffer = new BufferedReader(fileReader);
String num = buffer.readLine();
// 把数据存到ServletContext中
this.getServletContext().setAttribute("nums", num);
System.out.println("num=" + num);
buffer.close();
fileReader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
我用了
Runnable的线程
接口
public class InitServlet extends HttpServlet implements Runnable{ }
在 public void init() throws ServletException {}方法中增加了:
InitServlet tmp = new InitServlet();
Thread al = new Thread(tmp);
al.start();
在Run中增加了以下代码,测试吗,就5秒钟保存一次结果
public void run() {
int u = 0;
while (true) {
u++;
try {
Thread.sleep(5000);
System.out.println("你运行了"+u+"次");
this.Thread_Init();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果是它只运行一次,就不动了,也不报错,估计是取不到ServletContext()中的值
怎么办呢?新建一个线程类,它又取不到ServletContext,用
构造函数传过来,也麻烦,突然间,我想到了内部类,用内部类是不是,可以解决呢,试一下再说:
public void init() throws ServletException {
System.out.println("第一次调用");
String FilePath = this.getServletContext().getRealPath("Nums.text");
try {
FileReader fileReader = new FileReader(FilePath);
BufferedReader buffer = new BufferedReader(fileReader);
String num = buffer.readLine();
this.getServletContext().setAttribute("nums", num);
System.out.println("num=" + num);
buffer.close();
fileReader.close();
class Al extends Thread{
public void run() {
int u = 0;
while (true) {
synchronized (this) {
u++;
try {
System.out.println("第" + u + "秒");
Thread.sleep(5000);
Thread_Init();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Al thread = new Al();
thread.start();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
运行一下,果然可以
信息: Server startup in 3218 ms
thread调用
第2秒
thread调用
第3秒
thread调用
第4秒
thread调用
第5秒
id= 1 password= 123
++++++++++++++++++++++
thread调用
第6秒
thread调用
第7秒
id= 1 password= 123
++++++++++++++++++++++
thread调用
第8秒
再登陆几次
现在是登陆了5次
强制关掉服务器(这样它没有机会调用destroy方法了),果然把访问量保存到文本中了
重启浏览器,再登录,果然是6次
如果你用Tomcat 6.0
版本,还是会出问题,原因就是当你正常关掉服务器时,线程还在运行,这样,线程就取不到ServletContext的值,
Tomcat 7.0的版本我测试过没有这种问题,所以最好加上这句,就是主线程结束,后台线程也结束,就什么问题都没有了(想了好久才想到这个方法)
Al thread = new Al();
thread.setDaemon(true); //后台线程
thread.start();
这样,线程就可以每隔一段时间,自动保存访问量了,解决自己的难题,真的很开心啊
- 大小: 10.9 KB
- 大小: 46.1 KB
- 大小: 57.2 KB
- 大小: 6.7 KB
- 大小: 42.9 KB