spring配置詳解
阿新 • • 發佈:2019-06-19
springmvc的配置檔案,也不是固定命名的,而是同spring配置檔案一樣,在web.xml中指定的:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
下面我們還是老規矩,一步步的來分析spring mvc配置檔案
一.root標籤
跟spring配置一樣,root標籤是beans,畢竟springmvc是spring的一個模組
二.自動掃描
這部分我們在spring也講過。在springmvc裡,自動掃描主要是配置controller:
<context:component-scan base-package="com.xxx.controller"/>
三.解析器Resolver
解析器有很多種,比較重要的是ViewResolver
ViewResolver也有很多種,其中比較重要和常用的是InternalResourceViewResolver(內部資源檢視解析器)
先上程式碼再說明:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
如果沒有檢視解析器,我們在controller裡面的程式碼是這樣的:
@Controller
public class LoginActionController {
@RequestMapping("/index")
public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
return "/WEB-INF/jsp/index.jsp";
}
而使用了檢視解析器,我們的程式碼是這樣的:
@Controller
public class LoginActionController {
@RequestMapping("/index")
public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
return "index";
}
區別在最後一句,我們不需要給出目標檢視的全路徑了。
InternalResourceViewResolver的主要作用也在於此,給出內部資源的路徑和前後綴。
當然還有其他的檢視解析器,比如XmlViewResolver,UrlBasedViewResolver等,不再鋪開解釋。
也還有別的解析器,比如處理檔案上傳的解析器CommonsMultipartResolver,統一處理異常的解析器SimpleMappingExceptionResolver。
這裡多說兩句SimpleMappingExceptionResolver,程式碼如下:
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="warnLogCategory" value="warn" />
<property name="defaultStatusCode" value="500"/>
<property name="defaultErrorView" value="/error/500"/>
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">/error/500</prop>
</props>
</property>
<property name="statusCodes">
<props>
<prop key="/error/404">404</prop>
<prop key="/error/404">400</prop>
<prop key="/error/500">500</prop>
</props>
</property>
</bean>
四.對靜態資源的處理
在web.xml裡面,我們配置了springmvc的DispatcherServlet:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
注意看servlet-mapping部分,這部分的url-pattern是"/",這表明,DispatcherServlet會幫我們截獲所有的url請求,並將請求傳送給對應的controller。
對,是所有的請求!也包括靜態檔案,比如.js檔案,圖片檔案,css檔案的請求。
顯然這是有問題的,因為沒有controller會去處理靜態檔案,這會導致靜態檔案查詢不到。
這也是為什麼我們在一些早期的文章或者書籍中,看到的servlet-mapping是下面這樣的:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
然後在controller裡面,我們會這麼寫:
@Controller
public class LoginActionController {
@RequestMapping("/index.do")
public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
return "index";
}
注意這裡的RequestMapping的value是index.do
通過這種方式,等於是我們只讓DispatcherServlet去處理了.do字尾的請求,controller也只會處理.do字尾的請求。
對應的,我們的url是這樣的:www.test.com/index.do
很顯然這樣看著很奇怪,而且不符合REST風格。
所以spring團隊給出了2種解決方案:
方案一:
你可以在springmvc的配置檔案裡面加上這麼一句:
<mvc:default-servlet-handler />
這表示,如果發現是靜態資源的請求,就將該請求轉由Web應用伺服器預設的Servlet處理,如果不是靜態資源的請求,才由DispatcherServlet繼續處理。
方案二:
<mvc:resources />
<mvc:default-servlet-handler />將靜態資源的處理經由Spring MVC框架交回Web應用伺服器處理。而<mvc:resources />更進一步,由Spring MVC框架自己處理靜態資源,並新增一些有用的附加值功能:
首先你可以把你的靜態檔案放到專案的任何地方,比如/WEB-INF下面,classpath下面。而傳統的方案,我們只能把靜態檔案放到web應用的根目錄下面。然後通過location屬性告訴spring我們的靜態資源放在哪裡
PS:補充一個知識,什麼叫做web應用部署的根目錄:http://blog.csdn.net/l00149133/article/details/78984083
其次依據當前著名的Page Speed、YSlow等瀏覽器優化原則對靜態資源提供優化。你可以通過cacheSeconds屬性指定靜態資源在瀏覽器端的快取時間,一般可將該時間設定為一年,以充分利用瀏覽器端的快取。在輸出靜態資源時,會根據配置設定好響應報文頭的Expires 和 Cache-Control值。在接收到靜態資源的獲取請求時,會檢查請求頭的Last-Modified值,如果靜態資源沒有發生變化,則直接返回303相應狀態碼,提示客戶端使用瀏覽器快取的資料,而非將靜態資源的內容輸出到客戶端,以充分節省頻寬,提高程式效能。
另外,通過mapping屬性我們還可以指定靜態資源的訪問路徑。
舉例說明:
<mvc:resources location="/,/WEB-INF/js,classpath:/resource" mapping="resource/**"/>
這裡,我們把web部署的根目錄"/",以及WEB-INF下的js目錄,還有build路徑下的resource目錄都設定成了靜態資源目錄,並且對映成resource路徑。
假設我們:
在根目錄下有個image資料夾,裡面有個icon.png檔案
在WEB-INF下的js目錄下有個test.js檔案
在build路徑下的resource目錄裡有個css/test.css檔案
我們可以分別通過:
www.test.com/resource/iamge/icon.png
www.test.com/resource/js/test.js
www.test.com/resource/css/test.css
來訪問。
五.<mvc:annotation-driven />
這個有點像是我們之前講的註解裝配<context:annotation-config>,兩者都是用來隱式的註冊註解所需的bean。
比如你想要用@Autowired註解,如果沒有<context:annotation-config>,那你需要手動去宣告AutowiredAnnotationBeanPostProcessor的Bean:
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>
而<context:annotation-config>的作用,就是隱式的幫你聲明瞭這些註解的bean。包括AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及 RequiredAnnotationBeanPostProcessor 這 4 個BeanPostProcessor。
這樣你就可以使用諸如@Required, @Autowired, @PostConstruct這些註解。
但是!<context:annotation-config>並沒有幫我們宣告controller所用的註解,比如@RequestMapping, @Controller。所以我們需要<mvc:annotation-driven />。
實際上<mvc:annotation-driven />註冊了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter兩個bean,配置一些messageconverter。即解決了@Controller註解的使用前提配置。
六.mvc:message-converters訊息轉換器
這實際上是mvc:annotation-driven的一個子標籤,可以看到它主要處理的是response返回的值,比如預設編碼,比如支援Fastjson,當然你可以可以加入對其他返回型別的支援,比如gson,protobuf等等
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- @ResponseBody亂碼問題,將StringHttpMessageConverter的預設編碼設為UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<!-- 配置Fastjson支援 -->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="charset" value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>application/json</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="features">
<list>
<value>WriteMapNullValue</value>
<value>QuoteFieldNames</value>
<value>WriteDateUseDateFormat</value>
<value>WriteEnumUsingToString</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
七.springmvc攔截器mvc:interceptors
mvc:interceptors用來攔截url請求。
正常的流程,應該是DispatcherServlet先獲取所有的URL請求,然後依據規則分發給可以處理這些請求的controller。
而是用mvc:interceptors後,流程變成了:DispatcherServlet先獲取所有的URL請求,對於符合攔截器要求格式的URL,先分發給攔截器處理,最後再分發給可以處理這些請求的controller。
舉例說明:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**" />
<bean class="com.xxx.interceptor.LoginRequiredInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
這個攔截器表示,它會攔截所有的URL請求,除了static路徑下的請求,並交給LoginRequiredInterceptor來處理