徹底解決java WEB項目的文件路徑問題(war包)


在j2EE項目中,我們通常會把項目打包公布,通常是war包,作為獨立單元,能夠遠程上傳,載入,公布,還能夠實現版本號控制,但這與我們開發過程中使用MyEclipse自己主動部署有所不同,下面做具體說明.

使用war包部署,在tomcat和WebLogic下部署有非常大的差別,tomcat會把war自己主動加壓到當前文件夾下,然后再用解壓的文件夾來公布,這與一般不會出現太大的意外,但假設是用WebLogic公布,就不會被解壓,假設開發過程中不注意,war包公布后就有可能出現找不到文件的現象。比如:使用下面方法獲取路徑:

 

this.getClass().getClassLoader().getResource("/").getPath(); 


這與得到的是絕對Uri路徑,比如::/D:/jboss-4.2.2.GA/server/default/deploy/hp.war/WEB-INF/classes/。帶盤符的路徑,顯然在war中無法依據盤符來找到文件

 

另外一種方式:

 

this.getClass().getResource("/").getPath(); 

那么這樣獲取行不行呢?

經試驗。這與獲取的是當前類的Uri文件夾,比如:/D:/jboss-4.2.2.GA/server/default/deploy/hp.war/WEB-INF/classes/com/jebel/helper/ 也是絕對路徑,顯然無法適用於war包。

事實上以上兩種方式都走入了岔路,由於讀取文件未必要讀取路徑。文件操作一般都要轉換為流的方式,既然要讀取文件,不如直接讀成輸入流,也少了一步封裝。請看下面方式:

InputStream is= this.getClass().getResourceAsStream("/config/bctcms/" + templateFileName);

意思是讀取classes文件夾中,文件夾config/bctcms/下。文件名稱為templateFileName的文件輸入流。經試驗在war中能夠正常讀取到。

 

該方法存在一個弊端。僅僅能讀取classes文件夾下的文件。對於其它文件夾下的文件無能為力,顯然並不適用於全部場景。

 

假設文件在WEB-INF文件夾下。怎樣進行讀取呢?

答案是使用ServletContext.getResourceAsStream(String)方法。

也就是先得到上下文信息,然后通過以project文件夾為root的絕對路徑。找到文件,舉例說明:

 

InputStream is= context.getResourceAsStream(templatePath + "/" + templateFileName);
templatePath="/WEB-INF/classes/config/bctcms/"
templateFileName="source.xls"

能夠看到templatePath是相對於context root 的路徑,而不是相對於classes,這樣即使文件在WEB-INF其它文件夾下。也能夠順利找到。經測試,對war的情況支持良好。

 

請來看看ServletContext.getResourceAsStream的API文檔,
Returns a URL to the resource that is mapped to a specified path. The path must begin with a "/" and is interpreted as relative to the current context root. 
This method allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file.

 

相信大家都看得懂。就不用贅述了。僅僅是有個問題,context是個什么東西?答案:ServletContext。上下文信息,在j2EE類中使用request獲得。如:

 

ServletContext context = request.getSession().getServletContext();

那么在普通類中怎樣獲取呢?臨時特別好的辦法。使用application是一種方式,第二種方式就是想辦法先后去request對象,如:

 

 

RequestAttributes ra = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
this.context = request.getSession().getServletContext();

這樣也是能夠獲得Context的

 

但假設是JSP中,能夠直接這么獲取輸入流:

 

application.getResourceAsStream("xxx”);


路徑問題不要糾結太久,依據以上辦法解決,最好都用ServletContext方法來獲取。僅僅須要知道一種情況就能夠了。達到目的才是最重要的。對吧?

 

有不正確之處,歡迎大家進行補充糾錯!

update:當使用spring定時器時:request和servletContext就獲取不到了,那么要使用這種辦法直接獲取ServletContext:

ContextLoader.getCurrentWebApplicationContext().getServletContext()

update20151228:

寫文件的時候可能須要獲得路徑,比方上傳文件的時候就須要輸出流。而通過ServletContext不可以直接獲得輸出流的,但可以直接獲取實際路徑。如:

 

servletContext.getRealPath("/")


這樣獲得的路徑是${context}/路徑,再依據子路徑和文件名稱獲取輸出流。

 

 

 

來源:https://www.cnblogs.com/zhchoutai/p/7124409.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM