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: 完結
分享是技術進步的源泉,作者能力有限,如有錯誤,歡迎指出,不吝賜教。