Tomcat 启动后台程序

References:《Tomcat 启动时加载WEB应用中的后台程序》[1],《配置Tomcat Listener》[2]

 

要做的事情很简单,就是在Tomcat启动WEB服务器的时候同时启动一个后台程序,做一些事情。

[1]里面介绍的方法是通过不响应Request的Servlet来实现,通过设置<load-on-startup>标签和Servlet里面的static代码段来实现。

[2]介绍了另一个方法,通过实现ServletContextListener,并在web.xml文件里配置listener来实现后台程序的启动。

于是我打算先用第二种方法做一个demo:实现的功能:用户在页面输入值,action把这个值甩到一个消息队列里面,然后后台这个线程不断的从这个队列里面读值,输出到控制台

MyListener.java    version1

package Listeners;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import Support.MessageQManager;

import Support.MessageQueue;

public class MyListener implements ServletContextListener {

	@Override

	public void contextInitialized(ServletContextEvent sce) {

		System.err.println("DBConnListener Startup!");

		DemoThread dt = new DemoThread(MessageQManager.mq);

		Thread th1 = new Thread(dt);

		th1.start();

		System.err.println("DemoThread Startup!");

	}

	@Override

	public void contextDestroyed(ServletContextEvent sce) {

	}

}

DemoThread.java  ---version1

package BackStage;

import Support.MessageQueue;

public class DemoThread implements Runnable {

	private MessageQueue mq=null;

	public DemoThread(MessageQueue mq){

		this.mq=mq;

	}

	public void run() {

		while(true){

			readFromMsgQueue();

		}

	}

	public Object readFromMsgQueue(){

		Object o=mq.recv();

		System.err.println(o.toString());

		return o;

	}

}

MessageQueue.java

package Support;

import java.util.Vector;

public class MessageQueue {

	private Vector<Object> queue = null;

	public MessageQueue() {

		queue = new Vector<Object>();

	}

	public synchronized void send(Object o) {

		queue.addElement(o);

	}

	public synchronized Object recv() {

		if (queue.size() == 0)

			return null;

		Object o = queue.firstElement();

		queue.removeElementAt(0);// or queue[0] = null can also work

		return o;

	}

}

MessageQManager.java

package Support;

public class MessageQManager {

	public static MessageQueue mq=new MessageQueue();

}

前端代码就不贴出来了,就是把输入的值send到消息队列里面。

web.xml配置片段:<listener>标签要在filter-mapping标签下面

<listener>

	<listener-class>Listeners.MyListener</listener-class>

</listener>

然后满心欢喜的用eclipse启动服务器呢!O(∩_∩)O~

结果呢~出错了!!(⊙_⊙)

image

NoClassDefFoundError! 搜了一把,很多是因为找不到ServletContextListener,但是我的是能找到的,只是找不到自定义的类而已。研究了一段时间发现跟tomcat加载class的时间跟顺序有关系,貌似挺复杂的……没研究明白。

不管了先跑起来再说,于是果断把DemoThread甩到MyListener里面当一个内部类

MyListener.java    version2

package Listeners;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import Support.MessageQManager;

import Support.MessageQueue;

public class MyListener implements ServletContextListener {

	@Override

	public void contextInitialized(ServletContextEvent sce) {

		System.err.println("DBConnListener Startup!");

		DemoThread dt = new DemoThread(MessageQManager.mq);

		Thread th1 = new Thread(dt);

		th1.start(); 

		System.err.println("DemoThread Startup!");

	}

	@Override

	public void contextDestroyed(ServletContextEvent sce) {

		

	}

	public class DemoThread implements Runnable {

		private MessageQueue mq = null;

		public DemoThread(MessageQueue mq) {

			this.mq = mq;

		}

		public void run() {

			while (true) {

				readFromMsgQueue();

			}

		}

		public Object readFromMsgQueue() {

			Object o = mq.recv();

			if (o != null)

				System.err.println(o.toString());

			return o;

		}

	}

}

在运行,成功。

 

Demo是成功了,可是问题还有:

只能用内部类的方式不是太傻了么……怎样在Tomcat启动的时候加载自定义的类呢?理想状态是通过这一个线程作为入口启动好多个后台程序呢。

-------------------3月30日 更   新--------------------------

今天早上又用第一种方法尝试了一下,没有使用static代码段,而是在init()方法里启动线程,但是依然出现ClassNotFound的错误,直觉告诉我可能是DemoThread写的有问题,于是增加了空的构造函数!居然成功了!!

新的DemoThread.java代码

package BackStage;

import Support.MessageQManager;

import Support.MessageQueue;

public class DemoThread implements Runnable {

	public DemoThread() {

		System.err.println("DemoThread default constructor");

	}

	public void run() {

		while (true) {

			readFromMsgQueue(MessageQManager.mq);

		}

	}

	public Object readFromMsgQueue(MessageQueue mq) {

		Object o = mq.recv();

		if (o != null)

			System.err.println(o.toString());

		return o;

	}

}

代码用System.err主要是红色的输出信息比较惹眼哈╮(╯▽╰)╭

MyListener –version3

package Listeners;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import BackStage.DemoThread;

public class MyListener implements ServletContextListener {

	@Override

	public void contextInitialized(ServletContextEvent sce) {

		System.err.println("DBConnListener Startup!");

		DemoThread dt = new DemoThread();

		Thread th1 = new Thread(dt);

		th1.start(); 

		System.err.println("DemoThread Startup!");

	}

	@Override

	public void contextDestroyed(ServletContextEvent sce) {

		

	}

}

你可能感兴趣的:(tomcat)