今天在修改了某個jsp后發現:tomcat容器啟動后,訪問該jsp返回的結果依然是修改之前的內容,略感不解,於是乎研究了一下Tomcat中work目錄的作用。
Tomcat中work目錄的作用:
- jsp運行時都要先轉換成servlet,tomcat容器啟動時會在目錄下的work目錄中生成一系列的文件夾和.java文件和編譯后的.class文件。
- jsp最終轉化為servlet,work的作用就是加快速度,如果jsp沒有變化(依據時間戳)就不再重新編譯。
看到這似乎豁然開朗了,之后看了一下work中文件的最后修改時間,居然比當前時間還大,由此判斷有人在某時修改過系統時間(修改到了將來),而恰巧當時這個jsp頁面進行了第一次的編譯,所以產生了開頭所描述的現象。
進一步研究一下jsp編譯的相關內容:
當請求jsp頁面時,Tomcat將請求交由JspServlet來處理,我們來看一下在JspServlet的service()方法
boolean precompile = preCompile(request);
它會判斷你請求jsp頁面時有沒有帶?jsp_precompile查詢字符串,如果帶了就會重新編譯
然后再由serviceJspFile(request, response, jspUri, null, precompile)進一步判斷是否要進行編譯jsp文件,下面是JspServletWraper的service方法片段
1
if
(options.getDevelopment()
||
firstTime ) {
2 synchronized ( this ) {
3 if (firstTime) {
4 firstTime = false ;
5 }
6 ctxt.compile();
8 }
9 }
2 synchronized ( this ) {
3 if (firstTime) {
4 firstTime = false ;
5 }
6 ctxt.compile();
8 }
9 }
關鍵就在Compiler的isOutDated(boolean checkClass) 的判斷上 。
判斷標准是:如果jsp文件最后修改時間晚於目標文件的最后修改時間要重新編譯。還有一種情況是即使jsp的最后修改時間早於目標文件的最后修改時間,但只要jsp中用了include指令包含的某個文件的最后修改時間晚於對應目標文件的修改時間的話,也需要重新編譯主jsp文件。
