做一個Javaweb的項目,涉及到圖片上傳,並且需要將圖片通過URL回顯給JSP頁面,在調試的時候發現,上傳到tomcat的圖片再重新部署之后就消失了。研究了半天發現才解決了。首先說一下,為什么要將圖片存放到tomcat服務器或者更直白點說是web工程目錄下的原因:
項目中對於圖片的處理在於用戶上傳比如自己的頭像,上傳后再查看時,就直接根據服務器的URL指定圖片的位置去查看圖片,通俗點就是jsp頁面中的<img >標簽的src屬性的路徑就直接指向服務器該圖片存放的位置。鑒於這一點,所以將圖片文件存放在了tomcat中,而不放在服務器磁盤文件系統中,這樣前端JSP就可以直接通過URL訪問到圖片資源。
發現的問題:在調試的時候,我的開發環境十分通用,就是eclipse for jee ,服務器為tomcat7.0。在配置eclipse runtime服務器運行環境時,工程發布的位置選擇的是直接將工程發布到tomcat的webapps目錄下。配置過程如下:
1.在為eclipse添加到tomcat7.0服務器后,將服務器的工程全部remove掉,如下圖:
remove all,然后右鍵clean一下,這時再open,如下圖
在server locations下選擇第二個,這時工程在ADD到服務器時就直接到了tomcat 的webapps目錄下了。
遇到的問題:發現上傳的圖片在改動eclipse上的代碼的時候,也就是重新部署后,tomcat下的webapps中的工程目錄下的圖片全部沒有了,很奇怪,經過研究發現,原因如下:
我們在Java代碼中上傳圖片時,圖片的路徑是通過代碼
request.getSession().getServletContext().getRealPath("/img")
來獲取路徑的,而這句代碼返回的路徑是tomcat中webapps目錄下的工程路徑,圖片就直接保存到了tomcat中。
當我們重新發布工程的時候,tomcat其實是先將原來的工程刪掉,然后再將改動過的新的工程放上去。而改動過的新的工程師來自與我們eclipse的工作空間中的工程,這就也難怪了,因為我們是把圖片直接上傳到的tomcat服務器下,而不是放到工作空間的工程目錄下,自然重新部署后圖片就沒了。
解決辦法:
歸根到底的原因就是因為
request.getSession().getServletContext().getRealPath("/img")
這句代碼搞的鬼,所以在調試時,我們在Java代碼中保存上傳的圖片位置時將圖片的保存路徑應該保存在eclipse工作空間的目錄下,如:
String path = "E:\\program\\eclipse project\\Server\\WebContent\\img";
這樣,圖片在上傳到該工作空間后,因為項目發生了改變,eclipse會再次發布工程,這時圖片便會同步到tomcat服務器中,這時,我們前端jsp頁面也就可以通過URL定位到圖片了。
注意的地方:
歸根到底這些問題其實還是因為我們是在調試的工程中,發布后肯定是不會出現這些問題的。因為你想想我們的web工程一般是發布到Linux下,發布了之后你的tomcat服務器只有關閉和打開,而不會對工程重新部署,自然也就不會出現這些問題。然后這也同時出現了另外一個問題,就是我們的web系統是在Linux下,也不會有eclipse環境,那也就更不用談什么工作空間了,所以如果在代碼中String path = "E:\\program\\eclipse project\\Server\\WebContent\\img";這么寫系統肯定會報錯咯。所以最終來說,改成這樣也只是權宜之計,方便我們在調試的時候用的,到項目正式發布的時候需要我們再將路徑改成request.getSession().getServletContext().getRealPath("/img")的。
---------------------------------------------------------------------------分割線--------------------------------------------------------------------------------------------------------------
還有另外一種說法:
背景:
相對路徑和絕對路徑, 這問題在原來的myeclipse或者eclipse中不是個大問題,因為在myeclipse或者eclipse中,項目通過tomcat發布都是發布到webapp目錄下的,而在上傳圖片這種靜態資源的時候,考慮到圖片不能隨着項目發布而消失,所以我們以前的解決方法就是在tomcat的webapp目錄下建一個與項目同級的files文件夾,用於存儲圖片,excel,word等靜態文件。這樣的話就可以有效的避免在項目發布的過程中靜態資源消失的問題。
但是換到idea中之后,由於在idea中,項目通過tomcat發布時,項目並不是存在tomcat里的,而是存在artifacts中的Output directory所對應的文件目錄下。
所以用了絕對路徑也找不到,用相對路徑更加不對,花了很多時間。后來想到,既然路徑可以自己定義那為什么不和以前一樣放在tomcat的webapp下面呢,不僅熟悉,而且安全,可以控制權限,這里建議大家不要把項目代碼或者靜態資源放在服務器的C、D、E這種硬盤上,如果被黑客入侵那么資源就沒了,tomcat的webapp目錄可以設置訪問修改權限所以比較安全。修改了項目發布的路徑就簡單了。
所以正確的做法如下:
*****事實上, 由於idea有個虛擬路徑這種東西
正確的配置上的話, 如下圖, 就可以訪問靜態資源等文件了
因此正確的步驟是:
在項目的入口請求中,也就是用戶整個系統的入口頁面跳轉請求中獲取服務器的根目錄,可以使用request.getSession().getServletContext().getRealPath("/");這個方法拿到localhost:8080/項目名, 在這個地址下,接下來通過String 的indexOf()方法和subString()方法把項目名替換掉加上剛剛配置的 /files/… 就可以了, 這樣圖片或者其他的靜態資源就正常的加載出來了。
//不推薦使用獲取工程的根路徑 String a = request.getRealPath("/") //獲取jsp的路徑,這個方法比較好用,可以直接在servlet和jsp中使用 String b = request.getRealPath(request.getRequestURI()); //獲取工程的根路徑,這個方法比較好用,可以直接在servlet和jsp中使用 String c = request.getSession().getServletContext().getRealPath("/"); //獲取工程classes 下的路徑,這個方法可以在任意jsp,servlet,java文件中使用,因為不管是jsp,servlet其實都是java程序,都是一個 class。所以它應該是一個通用的方法。 String d = this.getClass().getClassLoader().getResource("").getPath();
System.out.println("a等於:"+a); //a等於:D:\idea\idea_project\javahou\out\artifacts\storeSystem_war_exploded\
System.out.println("b等於:"+b); //b等於:D:\idea\idea_project\javahou\out\artifacts\storeSystem_war_exploded\storeSystem\AdminProductServlet
System.out.println("c等於:"+c); //c等於:D:\idea\idea_project\javahou\out\artifacts\storeSystem_war_exploded\
System.out.println("d等於:"+d); //d等於:/D:/idea/idea_project/javahou/out/artifacts/storeSystem_war_exploded/WEB-INF/classes/
配置 tomcat 中的靜態資源的上下文訪問路徑, 如下圖:
首先, 在其他的工具中, 使用絕對路徑或者相對路徑, 就可以訪問圖片等靜態資源, 在js或者jsp中最好直接使用絕對路徑,這樣會少掉很多問題。但是 idea中支持虛擬路徑,專門用於訪問靜態資源,首先, 點開tomcat的配置, 進行如下的操作
在需要使用到靜態資源的地方使用上圖中配置的靜態資源上下文路徑再加上資源的相對路徑即可, 如下圖
總結:
1. 使用eclipse,使用tomcat發布項目,將項目發布到tomcat目錄在的webapp目錄中
2. 使用idea,使用tomcat發布項目,靜tomcat發布到artifacts中的Output directory所對應的文件目錄下。
3. javaweb圖片上傳tomcat重啟部署,圖片消失
eclipse解決是將靜態資源存到與工程目錄同級目錄下或者存在eclipse工作空間的目錄下String path = “E:\program\eclipse project\Server\WebContent\img”; 這樣,圖片在上傳到該工作空間后,因為項目發生了改變,eclipse會再次發布工程,這時圖片便會同步到tomcat服務器中,這時,我們前端jsp頁面也就可以通過URL定位到圖片了。 當我們重新發布工程的時候,tomcat其實是先將原來的工程刪掉,然后再將改動過的新的工程放上去
4. idea 重新發布工程的時候。tomcat不將原來的工程刪掉,是在原基礎上將添加的內容追加上去