情景:
今天想把一個web應用中的上傳路勁更改一下
於是就在配置文件作了如下變動:
<bean id="uploadServelt" class="com.xxxx.servlet.UploadServlet" scope="request" autowire="byType"> <property name="savePath" ><value>"C:\\Users\\admin\\Desktop\\upload"</value></property> </bean>
然後savePath這個變量仍然沒有生效
然後就想,會不會是沒有關聯到配置文件
ApplicaitonContext的幾種生成方法
一、ClassPathXmlApplicationContext
這種方式是通過類名路徑去找到配置文件,所以配置文件只能放在項目內部
二、FileSystemXmlApplicationContext
這個跟java.io.File差不多,所以配置文件可以放在項目外部
三、WebApplicationContextUtils
有兩種方法去得到ApplicationContext
- getRequiredWebApplicationContext(ServletContext)
- getWebApplicationContext(ServletContext)
推薦第一種方法,因爲第一種方法當獲取失敗的時候會拋出異常,第二種只會返回null
原因
重點來了!!爲什麼第三種方法會有可能獲取失敗呢??
注意,這兩種方法的參數都是ServletContext,所以推測,ApplicationContext是放在ServletContext裏面
查一查源碼
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); } public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { Assert.notNull(sc, "ServletContext must not be null"); Object attr = sc.getAttribute(attrName); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (attr instanceof Exception) { throw new IllegalStateException((Exception) attr); } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr; }
從源碼看,ApplicationContext果然是放在ServletContext裏面的,所以在獲取之前,如果ServletContext裏面沒有ApplicationContext,那麼就會拋出異常
ApplicationContext儲存在ServletContext的默認屬性名是"org.springframework.web.context.WebApplicationContext.ROOT"
然而,平時的慣性思維都以爲,這種獲取ApplicaitonContext的方法是spring自動完成的,不需要我們new
解決方案
先在ApplicationListener初始化的時候,用方法一或者方法二創建一個ApplicaitonContext,然後set到ServletContext裏面去,然後之後就可以用第三種方法獲取了,注意set的時候的屬性名稱,可以自定義也可以用默認的"org.springframework.web.context.WebApplicationContext.ROOT"
如果是自定義的話,就要用這個方法去獲取ApplicationContext了
WebApplicationContext.getWebApplicationContext(ServletContext sc, String attrName)
更正
之前說的有點不對 如果是web應用 當spring的ContextLoaderListener啓動的時候,會將WebApplicationContext放入ServletContext裏面去, 所以我們就大膽的使用方法三來獲取吧
查看原文:http://139.129.55.235/2016/05/30/%e8%8e%b7%e5%8f%96spring%e5%ae%b9%e5%99%a8%e8%a6%81%e5%b0%8f%e5%bf%83%e7%9a%84%e5%9d%91/