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 {@Overridepublic 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! ");
}@Overridepublic 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~
結果呢~出錯了!!(⊙_⊙)
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 {@Overridepublic 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! ");
}@Overridepublic 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 {@Overridepublic 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! ");
}@Overridepublic void contextDestroyed(ServletContextEvent sce) {}}
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
