平台:Windows 7 64位旗舰
工具:MyEclipse 10
服务器:Tomcat 7.0
语言:Java
1、需求
最近在做一个关于Web开发的项目,要求部署在Tomcat上面的主服务器程序运行过程中另外开辟一个后台线程完成间隔时间内休眠的数据库处理程序,对web开发中的线程开辟不是很熟悉,特意记下来以后回顾。
2、功能实现
开辟一个线程固然很简单,但是如何在web部署到服务器上的时候就让他跟随服务器一起启动呢?刚开始挺头疼的,查了几篇博客终于了解了,目前可以实现这种效果的方法有两种:
第一种:利用Listener监听器方式
Listener方式很常用,在servlet的api里面有很多关于监听器的描述,主要用来监听web应用的内部事件,允许web内部事件发生时回调监听器的方法,常见的事件有这些:web应用启动和停止、session的开始和退出、用户请求的到达等等,详情可以看下servlet的监听器部分:
在众多的监听器里面,监听web应用启动和停止,从而实现我们目的的就是ServletContexListener,我们可以利用它的监听,来实现服务器启动就开始启用我们的后台进程。
ServletContexListener有两个方法分别是初始化和销毁的方法,第一个方法是void contextInitialized(ServletContextEvent sce),这个方法在Container初始化整个Web应用时调用,运行在该Web应用中servlet和filter初始化之前;第二个是void contextDestroyed(ServletContextEvent sce),这个方法在Container卸载整个Web应用时调用,运行在该Web应用中servlet和filter的destroy()方法之后。
代码展示:
首先定义一个后台的服务线程:
public class run implements Runnable{ @Override public void run() { while(true){ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("you mother call you to go home to eat......") } } }
定义一个监听器的类:
package com.cims; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyListener implements ServletContextListener { public void contextDestroyed(ServletContextEvent e) { } public void contextInitialized(ServletContextEvent e) { System.out.println("------------web start-------"); new Thread(new run()).start(); } }
最后需要在web.xml进行一下配置:
<Listener> <Listener-class>com.wikey.listener</Listener-class> </Listener>
Web应用启动时,后台自动启动一个线程,启动项目,你就会发现自己的代码在运行了.
第二种:采用Servlet方式
首先需要向上面一样实现一个线程的方法:
package cn.wikey.Utils; public class GetErrorUtil extends Thread{ public GetErrorUtil(){} @Override public void run() { while (true) { try { System.out.println("我正在获取后台数据库的数据并推送给用户"); sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
然后在新建一个Servlet,并且在init()方法中进行线程的开启:
public void init() throws ServletException { // Put your code here String str = null; if (str == null && getError == null) { getError = new GetErrorUtil(); getError.start(); // servlet 上下文初始化时启动 socket } }
最后配置一下web.xml如下:
<servlet> <servlet-name>LoopGetErrorServlet</servlet-name> <servlet-class>cn.wikey.Servlet.LoopGetErrorServlet</servlet-class> <load-on-startup>9</load-on-startup>
其中9是一个非常重要的参数,他决定了servlet的启动方式和优先级,如果没有,servlet就会按照默认的方式在用户访问的时候启用init(),如果设置了这个参数,并且为正数,就会在服务器启动的时候启动,并初始化,它的参数可以随便设置某个正整数,只不过越接近1,它的优先级越高,也就是启动的顺序越靠前。
自此,你再重新启动服务器,就会看到自己的线程在运行了。
效果图:
3、总结
参考某大神的一篇博客,得知这两种方式其实是不同的,其中最大的不同就是启动的时间是不同的,前者是在start之前就已经启动完成,几乎是同时启动的;后者是在启动之后再启用这个servlet,详情请见这位前辈的博客http://blog.sina.com.cn/s/blog_6810dfc20101ipzq.html