91. Spring MVC 還提供了一個特別點的 Controller 類型就是 ThrowawayController,它自成一個接 口,ThrowawayController 和 Controller 的關系是平行的。什麼叫做 ThrowawayController 呢,中文 叫做一次性控制器,也就像一次性筷子那樣用完即丟,下次要用又拿新的。表現在實例上就是相應 Bean 配置為 singleton="false",每次初始化一個新實例。與其他 Controller 的區別完全就是 WebWork 或 Struts2 的 Action 與 Struts1 的 Action 的區別。因為它是多例的,所以可以用實例變量來接受請求 參數,執行方法無參數;而不像其他的 Controller ,因為共享實例,所以需要通過執行方法的來傳遞請 求參數以保證線程安全(P273)
92. 在《Spring in Action》第一版 274 頁說 DispatcherServlet 使用缺省 ControllerHandlerAdapter 時只會把控制權分發給 Controller 接口類型的類,而要配置 ThrowawayControllerHandlerAdapter 後,Dispatcherservlet 就把控制權分發給 ThrowawayController ,配置如下:
<bean id="throwawayHandler" class="org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter" />
<bean id="throwawayHandler" class="org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter" />
同時要是應用系統中要混用兩種控制器的話,還得在前面的基礎上配置一個 SimpleControllerHandlerAdapter,配置如下:
<bean id="simpleHandler" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<bean id="simpleHandler" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
然而我在實際測試中,仍用缺省的 ControllerHandlerAdapter,同樣能在一個應用中混合使用兩種類 型的控制器,尚不知不加上面那兩個配置會出什麼問題(P274)
93. 視圖解析器(實現接口 org.springframework.web.servlet.ViewResolver) 用來把 ModelAndView 對象的邏輯視圖名解析成一個用於將結果渲染給用戶的視圖 Bean。Spring 有 4 種 ViewResolver 實現 ,相當於不同 Struts2 的 result 類型:
·InternalResourceViewResolver -- 將邏輯視圖名解析為一個用模板文件(如 JSP 和 Velocity 等 模板) 渲染的視圖對象。
·BeanNameViewResolver -- 解析為一個 DispatcherServlet 應用上下文中的視圖 Bean
·ResourceBundleViewResolver -- 解析為 ResourceBundler 中的視圖 對象
·XmlViewResolver -- 從一個 XML 文件中解析視圖 Bean,這個文件是從 DispatcherServlet 應用上下文中分離出來的。
注意:在 org.springframework.web.servlet.view 包下只有 XmlViewResolver,而沒有 XmlViewResolver,書中是筆誤。
94. InternalResourceViewResolver 的使用,假如 Controller 中是 return new ModelAndView ("userDetail"),要轉向到 /WEB-INF/jsp/userDetail.jsp 時應配置為:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
<be an id="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"&g t;
<property name="prefix"><value>/WEB- INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
"/WEB-INF/jsp/userDetail.jsp" 中分別包含了前面指定的前綴、視圖邏輯名和後綴名。
如果這個 JSP 中使用了 JSTL 標簽,就應該為 InternalResourceViewResolver 指定 viewClass 屬 性為 JstlView,這時候的配置如下:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value> </property>
<property name="prefix"><value>/WEB- INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
<be an id="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"&g t;
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value> </property>
<property name="prefix"><value>/WEB- INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
這個 JstlView 就能解析 JSTL 特定的請求屬性,也就讓你可以在 JSP 中利用 JSTL 的化支持了 (P276)
95. BeanNameViewResolver 的使用,用如下的配置:
<bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean id="courseList" class="com.unmi.controller.CourseListPdfview"/>
<bean id="beanNameViewResolver"class="org.springframework.web.servlet.view.BeanNameViewResolver"/& gt;
<bean id="courseList" class="com.unmi.controller.CourseListPdfview"/>
對於 return new ModelAndView("courseList"); 就會被 beanNameViewResolver 解析到 courseList 來顯示結果(P278)
96. XmlViewResolver 與 BeanNameViewResolver 的工作方式類似,只不過它不是從主應用上下文中 尋找視圖 Bean,而是在一個獨立的 XML 文件中查找,用法如下:
<bean id="xmlViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location"><value>/WEB-INF/training- views.xml</value></property>
</bean>
<bean id="xmlViewResolver"class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location"><value>/WEB-INF/training- views.xml</value></property>
</bean>
這時候,對於 return new ModelAndView("courseList"); 就會到 /WEB-INF/training-views.xml 中 尋找 courseList 的 Bean。XmlViewResolver 的缺少 location 屬性值為 /WEB-INF/views.xml(P278)
97. ResourceBundleViewResolver,一看這名字中的 ResourceBundle 就是跟屬性文件、國際化有關 。來看看這樣一個配置:
<bean name="bundleViewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename"><value>views</value></property>
</bean>
< ;bean name="bundleViewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename"><value>views</value></property>
</bean>
並在 classpath 下有四個屬性文件,文件名及內容分別是:
views.properties 文件和 views_zh_CN.properties 文件的內容是:
courseList.class=com.unmi.training.mvc.CourseListPdfView
courseList.class=com.unmi.training.mvc.CourseListPdfView
views_en_US.properties 文件內容是:
courseList.class=com.unmi.training.mvc.CourseListExcelView
courseList.class=com.unmi.training.mvc.CourseListExcelView
views_de_DE.properties 文件的內容是:
courseList.class=org.springframework.web.servlet.view.JstlView
#這下面就是設置 JstlView 的 url 屬性
courseList.url=/WEB-INF/jsp/courseList.jsp
courseList.class=org.springframework.web.servlet.view.JstlView
#這下面就是設置 JstlView 的 url 屬性
courseList.url=/WEB-INF/jsp/courseList.jsp
很好也很自然的理解,通過上面的配置就能根據不同區域的用戶用不同類型的視圖呈現給用戶,例如 對於 new ModelAndView("courseList"),中國人訪問解析到了 CourseListPdfView(PDF 展示),美國人 訪問顯示了一個 Excel 表格(CourseListExcelView),給德國的是一個使用 JSTL 標簽 JSP 頁面。也了 解到視圖 Bean 是根據 properties 文件中的配置來初始化的(P279)
98. 項目中使用模板頁面居多,所以常用的是 InternalResourceViewResolver。不過我常見得這一視 圖解析器比起 Struts 和 WebWork 有不足之處resolver是,它的邏輯視圖名還攜速了文件名信息,要導 向到別的 JSP 文件還得修改代碼。其他三個視圖解析器 BeanNameViewResolver、XmlViewResolver 和 ResoureBundlerViewResolver 的區別只在它們從哪兒獲得視圖實現,應根據實際情況選用。
如果一個系統中要多個視圖解析器,該怎麼辦呢?那就在配置文件中配置多個了,用 order 屬性指定 應用的順序,從小至大,即 ViewResolver 的:
<property name="order"><value>1</value></property>
書中 P281 中給 InternalResourceViewResolver 配置了 order 屬性,而我查過 Spring 1.2.4/1.2.8/1.2.9 的 InternalResourceViewResolver 代碼,它並沒有直接或簡接的實現 Ordered 接 口,也就是不能對它配置 order 屬性。在 Spring 2.0 的 InternalResourceViewResolver 才簡接的實 現了 Ordered 接口,看得出這本書確有些超前。那還有一個問題,一個邏輯視圖名,給哪個視圖解析器 都是能執行的,那優先級低的視圖解析器在什麼時機能應用上(P281)
99. 關於 spring.tld 標簽,只提供了初步的功能,還難用,且必須搭配 JSTL 標簽。要顯示一個信 息特麻煩,每顯示個東西都要先 <spring:bind/> 一下,再 <c:out/>。綁定到的 status 有三個屬性 expression、value 和 errorMessages。因此有條件的話還是用 Spring 2.x 的 spring- form.tld 標簽,只能用 spring 1.x 時可考慮把 spring-form.tld 移植過來。
100. 每一套 MVC 框架都少不得異常處理機制,都有相應的配置來處理異常。Spring MCV 也一樣,直 接看如下的配置吧:
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">friendlyError</prop>
</props>
</property>
</bean>
exceptionMappings 屬性是一個 java.util.Properties,它映射了異常類名和邏輯視圖名。這樣任何 從 Spring MVC 控制器拋出來的 java.lang.Exception 異常被 SimpleMappingExceptionResolver 獲得 ,然後得到相應的邏輯視圖名,邏輯視圖名由視圖解析器導向到顯示錯誤的頁面,或是別的視圖 Bean。 exceptionMappings 中可以對多種異常作不同的映射(P283)