1.情景說明
在eclipse中,為什么Java文件修改后,重啟tomcat class文件才能生效?
為什么jsp修改后,不需重啟tomcat就能立即生效?
為什么靜態資源(*.js,*.css,*.html,圖片、pdf)等文件修改后,會即時生效?
2.探究eclipse的自動構建功能(Build Automatically)
自動構建的對象:src目錄下的所有文件;
src目錄被指定用來存放Java源文件(*.java)及配置文件(*.xml,*.properties等),也可以存放其它格式文件。
自動構建功能有2層含義:
其一,Java文件;
當Java文件有變動(Java文件被創建、修改、刪除)時,eclipse會自動調用jdk的編譯命令,
將Java文件編譯成class文件並輸出到WEB/INF/classes目錄下。
其二,非Java文件(如:配置文件)。
當配置文件有變動(Java文件被創建、修改、刪除)時,不管是什么樣的文件格式,只要是存在於src目錄下,
eclipse都會自動將其復制到WEB/INF/classes目錄下。
證明:
測試一:修改LoginAction.java文件
修改前
修改后:
測試二:在src目錄下新建一個text文件
WEB-INF/classes目錄下同樣被復制了一份
關閉自動編譯功能,將導致Java文件修改后不會被重新編譯, 配置文件不會同步!
測試三:刪除配置文件txt
先關閉自動構建功能(取消勾選即可)
在eclipse中,剛才新建的txt文件刪除
你會發現:WEB-INF/classes目錄下該文件並沒有被刪除。
重新勾選上 Build Automatically
WEB-INF/classes目錄下該文件已經被刪除。
3.在eclipse中,項目開發階段,探究運行JavaWeb項目的常用的4種方式及區別
方式一:選中項目-->右鍵-->Run As-->Run on Server
方式二:選中項目-->右鍵-->Debug As-->Debug on Server
方式三:將項目拷貝到tomcat的webapps目錄下,啟動tomcat;
方式四:修改tomcat的server.xml,在Host標簽內配置Context標簽,啟動tomcat。
探究一:
前提:項目發布在tomcat的webapps目錄下;
當文件內容發生變化后,是eclipse將變化后的文件更新至tomcat,還是tomcat自動將更新后的文件拷貝至webapps目錄下?
前兩種方式,通過eclipse自動將項目發布至tomcat的webapps目錄下;
第三種,自己手動將項目拷貝至tomcat的webapps目錄下。
測試1:第一種發布方式測試
打開base_login.js
打開webapps下對應的該文件
在eclipse中修改該文件
切換到notepad++,你會發現該文件同樣發生了變化
至此,我們還分不清到底時eclipse更新了該文件還是tomcat更新了該文件。
測試2:第三種發布方式測試
在eclipse中修改base_login.js文件后,webapps下對應的該文件並未發生變化!
2018/11/16
測試3:關閉eclipse中負責啟動這個項目的tomcat的自動發布功能
切換到server窗口
雙擊打開你要修改的tomcat,選擇第一個(默認為第二個),保存,不用重啟tomcat就會生效。
對文件進行修改后,webapps目錄下該項目對應的文件並未更新!
結論:
在eclipse中,所有格式的文件發生變化后(文件新增、修改、刪除),要想實現將更新后的資源自動發布至tomcat,需要滿足2個條件:
其一:通過eclipse將項目發布至tomcat的webapps目錄下,判斷依據:
對應的服務器下會展示已經發布的項目。
其二:需要開啟“當資源發生變化時,自動發布至tomcat的檢測功能”(這個是默認選中的)。
第三種方式之所以不能實現實時更新,是因為不能滿足第一個條件!
原生的tomcat是沒有第二個功能的;
所以說,是eclipse負責將變化后的文件更新至webapps中的對應項目下,
與原生的tomcat服務器無關,它只負責從webapps對應的項目下讀取文件!
探究二:
前提:前3種發布方式中,
哪種發布方式,eclipse會自動將class格式文件更新至tomcat?
測試3:debug模式下運行項目(debug as)
打開LoginAction.java
在tomcat的webapps目錄下找到並使用Java反編譯工具打開該文件
修改該文件
使用反編譯工具重新打開對應的文件
tomcat服務器被重新啟動
訪問這個Java類對應的controller,控制台輸出結果:
測試4:普通模式下運行項目(run as)
在eclipse中修改LoginAcion.java文件后,webapps下對應的class文件並未發生變化!
結論:
手動將項目拷貝到webaps目錄下進行發布項目,在eclipse對文件進行修改后,並不能實時更新文件,這種方式只適合項目正式運行階段使用;
只有以Debug as方式發布項目,eclipse才會將class格式文件更新至tomcat。
探究三:
不管是以run as還是debug as的形式發布項目,
當jsp文件發生變化(文件新增、修改、刪除)時,eclipse會自動將變化后的文件更新至tomcat的webapps目錄下對應文件。
為什么?因為eclipse為tomcat推送的是jsp文件,tomcat負責將jsp轉換成servlet,並編譯成class文件
測試5:tomcat負責jsp的編譯工作
jsp文件被編譯后會被放到tomcat的work目錄下;
只有請求時才會對jsp文件進行編譯;
每個目錄下都有jsp文件
因為只請求了登錄頁面,所以tomcat只對其對應的jsp進行了編譯工作
每次對該頁面進行請求時,tomcat都會檢測對應的jsp文件是否更新,如果已經更新就會對其進行重新編譯。
jsp處理流程圖
探究四:
配置Context標簽發布項目(熱部署)的方式,直接啟動tomcat即可。
具體方法:在eclipse中修改響應的tomcat的server.xml
在Host標簽內添加Context標簽
<Context docBase="D:\workspace-eclipse\jkkywpt_pydzk\web" path="/jkkywpt_pydzk"/>
tomcat的Context標簽的docBase屬性的值指定為web項目的發布目錄(WebContent/WebRoot)后,啟動tomcat后,
tomcat會直接訪問將該目錄下的文件並將其加載到tomcat容器中,不會再將項目發布到webapps目錄下;
測試6:tomcat不會再將項目發布到webapps目錄下
啟動tomcat
webapps目錄下並未發布該項目
因此,eclipse就省去了將更新后的資源推送到tomcat的webapps目錄下的步驟。
測試7:eclipse中tomcat服務器的 “當資源發生變化時,自動發布至tomcat的檢測功能”會失效。
關閉tomcat的自動發布功能
普通模式下,啟動tomcat
base_login.jsp頁面的原標題為aaa
瀏覽器展示效果
修改標題為測試
刷新頁面后
由此,已經證明: eclipse的服務器的自動發布功能已經不起作用了。
測試8:只有在debug模式下運行項目,Java文件修改后會即時生效!
普通模式下,修改LoginAction.java文件
class文件已經更新
頁面請求后,控制台並無輸出內容
debug模式運行該項目
修改Java文件
瀏覽器刷新后,控制台輸出結果:
由此,可以證明:在eclipse中,只有在debug模式下,無需重啟tomcat,Java虛擬機會即時生效。
原理說明:
對於Java類的更新:當監聽到class文件被修改后,通過動態修改內存中的字節碼,將修改過的class文件再次裝載到JVM中;
對於jsp的更新:jsp每次被調用時,tomcat容器都會通過ClassLoader重新加載相應的jsp編譯后的class文件並裝載到JVM中,
tomcat在調用jsp前,會檢測該文件是否被更新,如果被更新,會重新編譯這個jsp文件。
注意:
只有在修改方法體內的Java代碼這一種情況,不需要重啟tomcat!
4.總結
總的來說,文件修改后,之所以不用重啟tomcat是因為eclipse的自動構建功能,
自動構建,將文件更新至tomcat的webapps目錄下(class文件除外);
普通模式運行下,java文件重新編譯后,並不會被推送至webapps目錄下;
debug模式運行下,java文件重新編譯后,class文件會被推送至webapps目錄下,並且被tomcat更新至JVM;
jsp文件之所以不用重啟tomcat,也是依賴於eclipse的自動構建功能;
tomcat負責jsp的編譯工作。
發布及運行項目,對比說明:
拷貝至webapps下發布項目:
運行方式:將項目拷貝至weapps目錄下或者將項目打成的war包再放到weapps目錄下
需要說明的是:tomcat並不是從war包解讀所需文件,而是將war進行解壓,也就是說tomcat本身並識別war包,只是被賦予了一個解壓功能而已!
tomcat運行后,自動執行了解壓功能
是否指定解壓功能依賴於server.xml中Host標簽的unpackWARs屬性,默認值為true
特點:這種方式只適合在運行階段使用;
缺點:不適用於開發階段,無法進行代碼調試!
使用eclipse發布項目,並以普通模式運行項目(run):
當Java文件發生變化后,不會即時生效的原因有二:
其一,tomcat里的對應class文件並未更新,
其二,eclipse中,只有debug模式啟動項目,Java代碼才會即時生效。
特點:適合開發階段使用,但不建議使用;
缺點:不重啟tomcat的前提下,只適合前端調試,修改Java文件,必須重啟tomcat。
使用eclipse發布項目,並以debug模式運行項目(debug):
當Java文件發生變化后,可以即時生效的原因有二:
其一,tomcat里的對應class文件被同步更新,
其二,在eclipse中,以debug模式啟動項目,Java代碼會被更新至Java虛擬機,因此會即時生效。
特點:適合開發階段使用,大部分人會使用。
當Java文件修改后,eclipse雖然會將更新后的文件更新至tomcat,但是默認會重啟tomcat。
如何關閉tomcat重啟?見文末推薦。
(因為就算是不重啟tomcat,jvm也會即時生效)
缺點有二:
其一,Java文件修改后,會重啟tomcat,我們必須等待項目重啟后才能操作;(通過上面的方式可以解決);
其二,eclipse會將項目發布至tomcat的webapps目錄下,當我們不需要改項目時,需手動將其刪除。
配置Context標簽發布並運行項目(熱部署):
這種方式就是我們常說的熱部署!
運行方式:直接啟動tomcat(普通模式、debug模式);
特點:適合開發階段使用, 推崇以debug模式啟動項目。
優點:
加載的項目會隨着的tomcat的啟動和關閉而產生或死亡,不會留下任何痕跡(work文件夾除外);
而將項目發布到tomcat的方式,實際上是將項目發布到tomcat指定的發布目錄webapps文件夾,需要將清理webapps文件夾才能保證只加載該項目到tomcat中;
而采用熱部署的方式不會直接從WebContent目錄下讀取項目,不會在tomcat的webapps下產生任何文件;
方便調試、Java代碼方法體內代碼修改無需重啟;
當然了,可以在server.xml下配置多個項目。