1. 程式人生 > >Quartz每次排程時被執行兩次

Quartz每次排程時被執行兩次

[關鍵字:重複執行、重複呼叫、每次執行兩次、執行2次]

前言:


先說一下,專案背景。由於組內某成員在用Maven搭建專案時不規範,導致專案的名稱與實際訪問專案名稱不一致。
在部署專案時,必需要配一下虛擬路徑,對映到那個專案所在目錄下去,才能正常訪問。
舉個例子:專案名稱叫student-web,部署到Tomcat-webapps下,本地環境正常情況下的訪問url應該是:

127.0.0.1:8080/student-web

而實際訪問的url需要這樣:

127.0.0.1:8080/student

0x001: 初探


那首先想到問題的解決方案就是在Tomcat的server.xml內配置虛擬路徑,來對映到實際專案。比如這樣:

1 <Host .......>
2     <Context path="/student" docBase="D:\apache-tomcat\webapps\student-web"  reloadable="true"/>
3 </Host>

吶,一開始以為這樣問題就解決了。後來發現,實則不是。這樣做的後果是專案會被容器例項化兩次。

0x002: why?


首先需要了解<Host>標籤中的appBase屬性和<Context>標籤中的docBase屬性的作用和區別是什麼?
appBase屬性:這個目錄下面的子目錄將自動被部署為web應用,且war檔案將被自動解壓縮並部署為web應用(預設為Tomcat下webapps目錄)   注意這句話所說的每件(個)事(點)都可以被重新配置或取消。


docBase屬性: docBase屬性位於<Context>標籤中,而<Context>標籤的作用是用於指向不在webapps下的應用的所在目錄,在tomcat啟動時docBase屬性指向的目錄下的應用也被作為web專案同時啟動。

在有了以上了解後,那Quartz每次排程時被執行兩次方法的問題原因就找到了。

0x003: 解決方案

1.將<Host>標籤內的<Context>標籤去除,讓Tomcat自動去掃描webapps下的應用並部署。
2.若 ‘必需使用<Context>標籤’ 且 ‘必需配置虛擬路徑對映’ (注意這句話,後邊解釋),則必需將專案移出webapps目錄至某個新目錄,同時將<Context>標籤中的docBase屬性指向該新移至的目錄


(解釋一下第2條的前半句,經過測試發現,將student-web專案放到webapps目錄,且同時配置<Context>標籤的path屬性為“/專案名稱”,
啟動Tomcat,此時專案並不會跑兩遍,還是一遍,因為path屬性指定的值還是專案名稱,等於沒配置。如下:

1 <Host .......>
2     <Context path="/student-web" docBase="D:\apache-tomcat\webapps\student-web"  reloadable="true"/>
3 </Host>

若是配置<Context>標籤的path屬性值為 “/非專案名稱” 且 docBase屬性指向webapps目錄,那專案肯定會被容器例項化兩遍!如下:

1 <Host .......>
2     <Context path="/student" docBase="D:\apache-tomcat\webapps\student-web"  reloadable="true"/>
3 </Host>

至於選擇哪種解決方案,根據實際情況定,那我這裡只能選擇第2種。)

0x004: 宣告

導致Quartz排程任務被執行兩次的原因有很多,以上列舉的2種解決方案 可能 並 不適合你。亦可從其他方向查詢原因。
比如,檢查Quartz的xml配置檔案被載入了2次等等。

0x005: 完結
分享是技術進步的源泉,作者能力有限,如有錯誤,歡迎指出,不吝賜教。