前兩天工作中遇到一個問題,運行的web應用依賴了一個使用native code的jar包,在編譯打包的時候,所有的jar包和依賴的native code都被打包到WEB-INF/lib/文件夾下。這時候就遇到了一個問題,大家都知道java的web應用中, WEB-INF/這個文件夾是受保護的,這里受保護的含義就是,你不能在代碼通過相對路徑來訪問WEB-INF/文件夾下面的資源,即下面的代碼會報FileNotFoundException:
objectA.load("/WEB-INF/**/*")
//或
objectA.load("WEB-INF/**/*")
那么這時候要如何才能讀到WEB-INF下面的資源呢?剛才始的時候,想到了兩種比較低級的方法來解決這個問題:1. 將所以需要的資源文件放到resin/lib/文件夾下面, 這時候就可以通過相對路徑lib/need_source/來直接訪問資源了,當然這樣所帶來的問題也是顯而易見的,就是應用的侵入性,所有運行此web應用的服務上都必須被放入所需的資源文件,其丑陋性可想而知。2. 換了一個方式思想,但是還沒有脫離丑陋的本質,就是加一個build.properties文件,這個文件里指定應用被unwar以后,WEB-INF/lib/目前的絕對路徑,然后在ant war打包的時候,就可以通過filter來設置這個值,但是這樣所帶來的不便也是很明顯的。就是為這兩個問題煩惱的時候,終於找到了最終的解決方案:問題簡單化:實際上我們的需求是獲取spring開發的web項目在服務器上的絕對路徑。而我們已經知道servletContext有一個servletContext.getRealPath("/");方法,這個方法就能獲取項目的絕對路徑。因此,我們的問題就變成如何在Spring管理的POJO的bean中得到servletContext這個對象。 這個一個很悖論的問題,因為Spring管理的BEAN是POJO的,根本見不着servletconfig和servletcontext的影子。
這里我需要指出spring給我們提供了兩個接口:org.springframework.web.context.ServletContextAware和
org.springframework.web.context.ServletConfigAware。我們可以讓我們的bean實現上邊的任何一個接口就能獲取到servletContext了 .
public class DicBean implements ServletContextAware{
private ServletContext servletContext;
public void setServletContext(ServletContext sc) {
this.servletContext=sc;
System.out.println("項目的絕對路徑為:"+servletContext.getRealPath("/"));
}
}
這樣,我們的bean就能夠直接獲取到servletContext了。
如果你想要servletConfig,那方法一樣,只是實現的接口不同了。
原理推想:應該是在創建spring的sessionFactory的時候,將應用服務器的相關屬性一並加載,查看創建的bean是否實現相關接口,如果實現了,就將相關值賦予bean。
注意點:
1、這東西是無法用junit進行單元測試的,因為他依賴於應用服務器
spring有幾個這樣的XXXAware接口,當然按這樣方法處理之后就違反了Spring一直堅持的非入侵性,但是這時候這樣很好的解決問題了,那么就OK了,有得必有失嘛!