一、war包中的文件的讀取在開發(fā)J2EE Web應(yīng)用時,在開發(fā)階段通常采用目錄的部署方式,而在正式運行時通常把web應(yīng)用打包為單個的.war文件進(jìn)行方便地部署。也就是在你的應(yīng)用目錄(比如WebLogic的DefaultWebApp)下,執(zhí)行下面的命令:
這樣,要部署到正式系統(tǒng)時就非常方便,只需要把這個.war文件拷貝到WebLogic的applications目錄或Tomcat的webapps目錄下即可自動進(jìn)行部署。Tomcat會對部署的.war應(yīng)用包進(jìn)行自動監(jiān)控、解包,所以不會出現(xiàn)下面提到的問題。而WebLogic并不會自動解包.war,所以如果在你的應(yīng)用中,需要讀取原來應(yīng)用中的配置文件或其它資源文件時,就會發(fā)現(xiàn),在解包部署時,正常運行的程序,在WebLogic中打包部署時,運行卻出錯,會報告找不到該文件。例如下面的應(yīng)用: |--DefaultWebApp 其中使用到了Log4J作為日志輸出工具,Log4J的配置文件log4j.propertes放在DefaultWebApp\WEB-INF目錄下。Log4J通過一個自動加載的Servlet進(jìn)行初始化,初始化代碼如下:
其中,context.getRealPath("/")得到當(dāng)前Web應(yīng)用的真實根目錄,比如,如果你的WebLogic安裝在D:\bea下,在Windows下context.getRealPath("/")通常會返回: D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp 在UNIX下類似: /bea/wlserver6.1/config/mydomain/applications/DefaultWebApp 這樣,和"/ WEB-INF /log4j.properties"拼接后,就得到了log4j.properties文件的真實路徑,Log4J通過文件IO讀取這個配置文件,完成初始化。 現(xiàn)在一切正常!測試通過后,將DefaultWebApp下的所有文件打為一個.war包,進(jìn)行部署時,發(fā)現(xiàn)系統(tǒng)報告找不到“D:\bea\wlserver6.1\null\ WEB-INF \log4j.properties”文件!如果你的應(yīng)用中還需要讀取其它已經(jīng)被打包到war包中的文件,都會報告找不到文件。并且,系統(tǒng)并不會到D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp目錄下尋找,而會到D:\bea\wlserver6.1\null下尋找。這是因為context.getRealPath("/")返回了null。查看ServletContext的API文檔, public String getRealPath(String path) …… The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive). 原來,對一個打包的應(yīng)用來說,是沒有RealPath的概念的,調(diào)用getRealPath只會簡單地返回null。其實,也很好理解,一個文件被打包入了.war文件,就不存在目錄結(jié)構(gòu)了(雖然包中仍然存在目錄結(jié)構(gòu),但這不等同于文件系統(tǒng)中的目錄結(jié)構(gòu))。所以,對war包中的資源是無法得到RealPath的。這樣也就無從通過文件IO進(jìn)行讀取了。那么,如何讀取war包中的資源呢?答案是使用ServletContext.getResourceAsStream(String)方法。 對于org.apache.log4j.PropertyConfigurator,有如下幾種配置方法:
既然,現(xiàn)在不能得到war包中的Log4J的配置文件,那么可以通過讀入InputStream,構(gòu)造一個Properties,通過configure(Properties properties)方法同樣可以完成配置。示例代碼如下:
那么,現(xiàn)在對于war應(yīng)用可以成功運行,但如果現(xiàn)在不通過war部署,直接通過目錄結(jié)構(gòu)部署應(yīng)用會不會又出現(xiàn)找不到資源的錯誤呢?請來看看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. 可見,通過getResourceAsStream可以獲取包括本地文件系統(tǒng)、遠(yuǎn)程文件系統(tǒng)、war包等資源。不會出現(xiàn)上面擔(dān)心的問題。 結(jié)論:在開發(fā)J2EE Web應(yīng)用時,如果需要讀取本應(yīng)用中的文件,盡量使用ServletContext.getResourceAsStream進(jìn)行,而不要使用文件IO。 二、Ant使用中的OutOfMemoryError解決在開發(fā)大型項目時,類文件通常有數(shù)千個之多,這時都需要采用一些make工具來輔助開發(fā)。有時需要編譯的類太多,使用Ant編譯時,會出現(xiàn)OutOfMemoryError的錯誤,使編譯進(jìn)程中斷。這時,通常通過先移出部分文件,分批編譯。但Java編譯過程的自動依賴編譯,通常很難確定究竟應(yīng)該先移出哪些文件、后移出哪些文件傷透腦筋。有沒有簡便的方法?有! 轉(zhuǎn)到你的Ant的安裝目錄,在bin子目錄中找到ant.bat,使用文字編輯器打開,修改:runAnt處的允許命令,添加如下參數(shù): :runAnt "%_JAVACMD%" -Xms128m -Xmx512m -classpath …… 如果你安裝了Jike,使用Jike編譯器,則需要修改:runAntWithJikes處的運行命令,同上。 結(jié)論:Java虛擬機默認(rèn)分配64M內(nèi)存,如果你的應(yīng)用比較大,超出64M內(nèi)存,Java虛擬機就會拋出OutOfMemoryError,并停止運行。不管是什么應(yīng)用(Web應(yīng)用、Application等),只需要修改你的機器上的運行Java命令,在java xxx命令中添加-Xms(最小使用內(nèi)存)、-Xmx(最大使用內(nèi)存)即可解決。當(dāng)然,這兒的內(nèi)存容量都是指物理內(nèi)存,不能超出你的機器的物理內(nèi)存的總?cè)萘俊?/strong> |
|