spring mvc 在Web.xml中自動掃描Spring的配置檔案及resource時classpath*:與classpath:的區別
首先在web.xml中配置監聽器listener,讓spring進行自動獲取。具體加入的程式碼如下:
- <listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
- <!-- Context Configuration locations for Spring XML files -->
- <context-param><param-name>contextConfigLocation</param-name>
- <!-- <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> -->
-
<!-- 加入你的配置檔案放在了src下的,命名規則為:applicationContext-*.xml形式,則可以從以下方式配置-->
- <param-value>classpath:applicationContext-*.xml</param-value>
- </context-param>
這樣的話,在伺服器啟動的時候就會自動的去classpa也就是src目錄下找所有的以:applicationContext-*.xml檔案並將它們初始化。
Spring可以通過指定classpath*:與classpath:字首加路徑的方式從classpath載入檔案,如bean的定義檔案.classpath*:的出現是為了從多個jar檔案中載入相同的檔案.classpath:只能載入找到的第一個檔案.
比如 resource1.jar中的package 'com.test.rs' 有一個 'jarAppcontext.xml' 檔案,內容如下:
<bean name="ProcessorImplA" class="com.test.spring.di.ProcessorImplA" />
resource2.jar中的package 'com.test.rs' 也有一個 'jarAppcontext.xml' 檔案,內容如下:
<bean id="ProcessorImplB" class="com.test.spring.di.ProcessorImplB" />
通過使用下面的程式碼則可以將兩個jar包中的檔案都載入進來
ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath*:com/test/rs/jarAppcontext.xml");
而如果寫成下面的程式碼,就只能找到其中的一個xml檔案(順序取決於jar包的載入順序)
ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:com/test/rs/jarAppcontext.xml");
classpath*:的使用是為了多個component(最終釋出成不同的jar包)並行開發,各自的bean定義檔案按照一定的規則:package+filename,而使用這些component的呼叫者可以把這些檔案都載入進來.
classpath*:的載入使用了classloader的 getResources()
方法,如果是在不同的J2EE伺服器上執行,由於應用伺服器提供自己的classloader實現,它們在處理jar檔案時的行為也許會有所不同。 要測試classpath*:
是否有效,可以用classloader從classpath中的jar檔案里加載檔案來進行測試:getClass().getClassLoader().getResources("<someFileInsideTheJar>")
。(上面的例子是在sun的jre中執行的狀態)
從Spring的原始碼,在PathMatchingResourcePatternResolver類中,我們可以更清楚的瞭解其對的處理:如果是以classpath*開頭,它會遍歷classpath.
- protected Resource[] findAllClassPathResources(String location) throws IOException {
- String path = location;
- if (path.startsWith("/")) {
- path = path.substring(1);
- }
- Enumeration resourceUrls = getClassLoader().getResources(path);
- Set<Resource> result = new LinkedHashSet<Resource>(16);
- while (resourceUrls.hasMoreElements()) {
- URL url = (URL) resourceUrls.nextElement();
- result.add(convertClassLoaderURL(url));
- }
- return result.toArray(new Resource[result.size()]);
- }
http://blog.csdn.net/kkdelta/article/details/5560210,簡介了在JAVA裡遍歷classpath中讀取找到的所有符合名稱的檔案.
另外在載入resource的時候,其他字首的意義如下表所示:注意classpath*只能用與指定配置檔案的路徑,不能用在用於getResource的引數.如appContext.getResource("classpath*:conf/bfactoryCtx.xml")會異常的.
字首 | 例子 | 說明 |
---|---|---|
classpath: |
|
從classpath中載入。 |
file: |
|
作為 |
http: |
|
作為 |
(none) |
|
根據 |
- public Resource getResource(String location) {
- Assert.notNull(location, "Location must not be null");
- if (location.startsWith(CLASSPATH_URL_PREFIX)) {
- returnnew ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
- }
- else {
- try {
- // Try to parse the location as a URL...
- URL url = new URL(location);
- returnnew UrlResource(url);
- }
- catch (MalformedURLException ex) {
- // No URL -> resolve as resource path.
- return getResourceByPath(location);
- }
- }
- }
getResourceByPath會被不同
ApplicationContext
實現覆蓋.
如 GenericWebApplicationContext覆蓋為如下:
- protected Resource getResourceByPath(String path) {
- returnnew ServletContextResource(this.servletContext, path);
- }
- 如 FileSystemXmlApplicationContext覆蓋為如下:
- protected Resource getResourceByPath(String path) {
- if (path != null && path.startsWith("/")) {
- path = path.substring(1);
- }
- returnnew FileSystemResource(path);
- }
最終從檔案載入的時候仍然是JAVA中常見的讀取檔案的方法:
如ClassPathResource得到inputstream的方法是利用class loader.
- public InputStream getInputStream() throws IOException {
- InputStream is;
- if (this.clazz != null) {
- is = this.clazz.getResourceAsStream(this.path);
- }
如FileSystemResource得到inputstream的方法是利用FileInputStream.
public InputStream getInputStream() throws IOException {
return new FileInputStream(this.file);
}
如ServletContextResource得到inputstream的方法是利用servletContext.getResourceAsStream.
- public InputStream getInputStream() throws IOException {
- InputStream is = this.servletContext.getResourceAsStream(this.path);
- if (is == null) {
- thrownew FileNotFoundException("Could not open " + getDescription());
- }
- return is;
- }