SpringMVC--視圖


本章簡介

視圖(View)和視圖解析器(ViewResolver)的工作流程:

當請求處理方法處理完請求之后,會返回String、ModelAndView或View對象,如return “success”;但返回值最終都會被SpringMVC統一轉為ModelAndView對象並返回;隨后Spring就會用ViewResolver,把返回的ModelAndView對象中的View渲染給用戶看(即返回給瀏覽器),如圖,

圖28-01

28.1 視圖View

視圖View的作用是渲染數據,將數據以JSP、PDF、EXCEL等形式呈現給用戶。SpringMVC通過View接口來支持視圖,該接口提供了各種各樣的視圖,並且可以讓用戶自定義視圖。

在客戶端的每一次請求時,視圖解析器ViewResolver都會產生一個新的視圖View對象。

視圖View接口的實現類及部分簡介如下

圖28-02

視圖類型 簡介
URL視圖資源圖 InternalResourceView 將JSP或其他資源封裝成一個視圖。被視圖解析器InternalResourceViewResolver默認使用。
JstlView InternalResourceView的子類。如果JSP中使用了JSTL的國際化標簽,就需要使用該視圖類。
文檔視圖 AbstractExcelView Excel文檔視圖的抽象類。
AbstractPdfView PDF文檔視圖的抽象類
報表視圖 ConfigurableJasperReportsView 常用的JasperReports報表視圖
JasperReportsHtmlView
JasperReportsPdfView
JasperReportsXlsView
JSON視圖 MappingJackson2JsonView 將數據通過Jackson框架的ObjectMapper對象,以JSON方式輸出

28.2 視圖解析器ViewResolver

SpringMVC提供了一個視圖解析器的上級接口ViewResolver,所有具體的視圖解析器必須實現該接口。

常用的視圖解析器實現類及簡介如下

圖28-03

視圖解析器類型 簡介
解析為bean BeanNameViewResolver 將視圖解析后,映射成一個bean,視圖的名字就是bean的id。
解析為映射文件 InternalResourceViewResolver 將視圖解析后,映射成一個資源文件。例如將一個視圖名為字符串“success.jsp”的視圖解析后,映射成一個名為success的JSP文件。
JasperReportsViewResolver 將視圖解析后,映射成一個報表文件。
解析為模板文件 FreeMarkerViewResolver 將視圖解析后,映射成一個FreeMarker模板文件。
VelocityViewResolver 將視圖解析后,映射成一個Velocity模板文件。
VelocityLayoutViewResolver

InternalResourceViewResolver是JSP最常用的視圖解析器,可以通過prefix給響應字符串加上前綴,通過suffix加上后綴。例如我們之前曾在springMVC的配置文件中配置了一個視圖解析器InternalResourceViewResolver,如下:

springmvc.xml

復制
  1. <beans>
  2. <!-- 配置視圖解析器:把handler處理類的返回值,加工成最終的視圖路徑-->
  3. <bean class="org.springframework.web.servlet.view
  4. .InternalResourceViewResolver">
  5. <property name="prefix" value="/views/"></property>
  6. <property name="suffix" value=".jsp"></property>
  7. </bean>
  8. </beans>

此外,視圖解析器還可以通過解析JstlView進而實現國際化、通過解析<mvc:view-controller>進而指定請求的跳轉路徑、通過“redirect:”和“forward:”指定跳轉方式等等。

(1)通過解析JstlView實現國際化

JstlViewInternalResourceView的子類。如果在JSP中使用了JSTL,那么InternalResourceViewResolver就會自動將默認使用的InternalResourceView視圖類型轉變為JstlView類型。

以下,在SpringMVC中使用JSTL的fmt標簽來實現國際化:

所謂“國際化”,就是指同一個程序,對於不同地區/國家的訪問,提供相應的、符合來訪者閱讀習慣的頁面或數據。例如,同一個用JSP開發的歡迎頁面,中國地區訪問時顯示“歡迎您”,而美國地區訪問時則顯示“Welcome”。以下是實現國際化的具體步驟:

①對於不同地區/國家,創建不同的資源文件

將程序中的提示信息、錯誤信息等放在資源文件中,為不同地區/國家編寫對應資源文件。這些資源文件使用共同的基名,通過在基名后面添加語言代碼、國家及地區代碼來區分不同地域的訪問者。如下是一些常見的資源文件命名方式及簡介:

資源文件名 簡介
基名_en.properties 所有英文語言的資源
基名_en_US.properties 針對美國地區、英文語言的資源
基名_zh.properties 所有的中文語言的資源
基名_zh_CN.properties 針對中國大陸的、中文語言的資源
基名_zh_HK.properties 針對中國香港的、中文語言的資源
基名.properties 默認資源文件。如果請求相應語言的資源文件不存在,將使用此資源文件。例如,若是中國大陸地區用戶,應該訪問“基名_zh_CN.properties”,而如果不存在此文件,就會去訪問默認的“基名.properties”。

例如,如果訪問此項目的用戶來自美國和中國兩個國家,就需要創建美國和中國兩個地區的資源文件:在項目的src目錄中,新建美國地區的資源文件i18n_en_US.properties,和中國內地的資源文件i18n_ zh_CN.properties,如下:

美國地區的資源文件:i18n_en_US.properties

復制
  1. resource.welcome=WELCOME
  2. resource.exist=EXIST

中國內地的資源文件:i18n_ zh_CN.properties

復制
  1. resource.welcome=\u6B22\u8FCE\u60A8
  2. resource.exist=\u9000\u51FA

說明:

在中文使用的i18n_ zh_CN.properties中,用戶輸入的原文是:

resource.welcome=歡迎您

resource.exist=退出

但Eclipse會自動將“歡迎您”等漢字自動轉為相應的ASCII,供屬性文件使用。 如果讀者使用的Eclipse版本不能自動的將漢字轉為ASCII,也可以使用JDK安裝目錄中bin中的native2ascii.exe工具進行轉換。

不同資源文件的基名必須保持一致(如i18n),並且資源文件的內容是由很多key-value對組成,key必須一致(如resource.welcome),value隨語言/國家地區不同而不同(如美國是“WELCOME”,中國是“歡迎您”)。

本例使用的基名i18n是internationalization(國際化)的縮寫。internationalization的首尾字母i和n中間有18個字母,所以簡稱i18n。

②在SpringMVC的配置文件中,加載國際化資源文件

springmvc.xml

復制
  1. <beans>
  2. <bean id="messageSource" class="org.springframework
  3. .context.support.ResourceBundleMessageSource">
  4. <property name="basename" value="i18n" />
  5. </bean>
  6. </beans>

Spring容器在初始化時,會自動加載idmessageSource,且類型為org.springframework.context.MessageSourceBean,並加載該Bean中通過basename屬性指定基名的國際化資源文件。

③使用JSTL標簽實現國際化顯示

先導入JSTL依賴的2個JAR:jstl.jarstandard.jar,再在顯示頁success.jsp中導入JSTL用於支持國際化的庫,並使用<fmt:message …>實現國際化顯示,如下:

顯示頁success.jsp

復制
  1. <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
  2. <body>
  3. <fmt:message key="resource.welcome"></fmt:message>
  4. <br><br>
  5. <fmt:message key="resource.exist"></fmt:message>
  6. <br><br>
  7. </body>

fmt標簽的key值會根據瀏覽器的語言環境去匹配資源文件中的key,若匹配則會顯示相應資源文件中key對應的value值。例如,中國內陸地區下載的火狐瀏覽器默認的語言是中文,所以會在i18n_zh_CN.properties中尋找key為“resource.welcome”、“resource.exist”的value值,並顯示到頁面上,如下:

發送請求頁index.jsp

<a href="FirstSpringDemo/testI18n">testI18n</a><br/>

請求處理類:FirstSpringDemo.java

復制
  1. @Controller
  2. @RequestMapping(value = "/FirstSpringDemo")
  3. public class FirstSpringDemo
  4. {
  5. @RequestMapping("/testI18n")
  6. public String testI18n(){
  7. return "success";
  8. }
  9. }

顯示頁面:success.jsp

復制
  1. <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
  2. <body>
  3. <fmt:message key="resource.welcome"></fmt:message>
  4. <br>
  5. <fmt:message key="resource.exist"></fmt:message>
  6. </body>

執行index.jsp中的超鏈接,運行結果:

圖28-04

如果將火狐瀏覽器的語言切換為英文,如下:

圖28-05

再次執行index.jsp中的超鏈接,運行結果:

圖28-06

以上就實現了國際化的顯示操作,JSP頁面會根據瀏覽器的語言環境自動尋找相應的資源文件,並依據key值進行顯示。

注意:就本例來說,國際化顯示標簽必須在success.jsp中才會起作用,而如果將放在index.jsp中則無法實現國際化。這是因為在springmvc.xml中配置的MessageSource(具體是ResourceBundleMessageSource實現類)是用來處理響應的,也就是說只有在請求處理方法返回String、View或ModelAndView對象以后執行響應時,才會通過MessageSource來執行國際化操作。而如果直接在index.jsp中執行<fmt:message ..>,因為此時還沒有“處理響應”這一過程,所以就不會涉及到MessageSource,也就不會根據basename屬性來指定的資源文件基名,因此本例的index.jsp中不能直接實現國際化顯示。

(2)<mvc:view-controller>

我們之前使用SpringMVC的流程大致都是

請求頁index.jsp—>使用@RequestMapping標識的請求處理類FirstSpringDemo.java中的方法–>結果顯示頁success.jsp

除此以外,我們還可以省略②,讓流程簡化為①—>③,即省略請求處理方法。簡化的方法是在springmvc.xml中配置<mvc:view-controller/>,如下:

springmvc.xml

復制
  1. <beans>
  2. <mvc:view-controller path="/testViewController"
  3. view-name="success"/>
  4. </beans>

其中path用來匹配請求路徑(類似於@RequestMappingvalue值),view-name用來指定響應跳轉的頁面(類似於請求處理方法中的return “success”)。以上配置,就表示凡是請求路徑為“testViewController”的,就會被直接跳轉到“success”頁面(“success”會加上InternalResourceViewResolver中設置的前綴和后綴)。如下:

index.jsp(請求路徑是:<mvc:view-controller/>path指定的testViewController)

<a href="testViewController">testViewController</a><br/>

點擊此超鏈接后,就會直接跳轉到view-name指定的success頁面(/view/success.jsp),即略過了@RequestMapping標識的請求處理方法。

但是,此時如果我們再點擊index.jsp中之前編寫的其他超鏈接,就都會報“HTTP Status 404”異常。解決辦法就是再在springmvc.xml中加入<mvc:annotation-driven></mvc:annotation-driven>,如下:

springmvc.xml

復制
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. <mvc:view-controller path="/testViewController"
  4. view-name="success"/>
  5. <mvc:annotation-driven></mvc:annotation-driven>
  6. </beans>

一般情況,在使用<mvc:view-controller/>的同時,也需要加入<mvc:annotation-driven/>標簽。

(3)頁面跳轉方式

當請求處理方法的返回值是字符串時,視圖解析器InternalResourceViewResolver會給返回值加上前綴、后綴,然后默認以請求轉發的方式進行頁面跳轉。此外,我們還可以通過給返回值加上forward:”redirect:”來指定跳轉方式為請求轉發或重定向。

①通過forward:”指定跳轉方式為請求轉發

復制
  1. @RequestMapping("/testForward")
  2. public String testForward(){
  3. return "forward:/views/success.jsp";
  4. }

②通過redirect:”指定跳轉方式為重定向

復制
  1. @RequestMapping("/testRedirect")
  2. public String testRedirect(){
  3. return "redirect:/views/success.jsp";
  4. }

需要注意,加上forward:”redirect:”后,視圖解析器將不會再給返回值加上前綴、后綴,需要我們自己寫上完整的響應地址。

28.3 處理靜態資源

如果我們在項目的WebContent目錄下新建imgs目錄,並存放一張圖片logo.png,如圖,

圖28-07

然后啟動tomcat服務來訪問此圖片http://localhost:8888/SpringMVCDemo/imgs/logo.png,就會看到瀏覽器顯示“HTTP Status 404”異常。這是因為我們之前在web.xml中配置了DispatcherServlet,如下:

web.xml

復制
  1. <servlet>
  2. <servlet-name>springDispatcherServlet</servlet-name>
  3. <servlet-class>
  4. org.springframework.web.servlet.DispatcherServlet
  5. </servlet-class>
  6. <init-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:springmvc.xml</param-value>
  9. </init-param>
  10. <load-on-startup>1</load-on-startup>
  11. </servlet>
  12. <servlet-mapping>
  13. <servlet-name>springDispatcherServlet</servlet-name>
  14. <url-pattern>/</url-pattern>
  15. </servlet-mapping>

DispatcherServlet的url-pattern是“/”,表示會攔截所有請求。因此,當訪問圖片、js文件、視頻等靜態資源時,也會被DispatcherServlet所攔截並去嘗試匹配相應的@RequestMapping方法,但靜態資源一般不會有相應的@RequestMapping,因此會報404異常。為了解決此異常,以便能夠訪問靜態資源,可以在springmvc.xml中加上<mvc:default-servlet-handler/><mvc:annotation-driven></mvc:annotation-driven>,如下:

springmvc.xml

復制
  1. <beans>
  2. <mvc:default-servlet-handler/>
  3. <mvc:annotation-driven></mvc:annotation-driven>
  4. </beans>

之后,就可以成功訪問到項目中的靜態資源。

<mvc:default-servlet-handler/>標簽的作用是:此標簽會在SpringMVC上下文中定義一個DefaultServletHttpRequestHandler,它會對所有DispatcherServlet處理的請求進行篩查,如果發現某個請求沒有相應的@RequestMapping進行處理(如請求的是圖片等靜態資源),就會將該請求交給WEB服務器(如Tomcat)默認的Servlet處理,而默認Servlet就會直接去訪問該靜態資源。

說明:

Tomcat默認的Servlet是在“tomcat安裝目錄\conf\web.xml”中定義的,如下

復制
  1. <servlet>
  2. <servlet-name>default</servlet-name>
  3. <servlet-class>
  4. org.apache.catalina.servlets.DefaultServlet
  5. </servlet-class>
  6. </servlet>

配置了<mvc:default-servlet-handler/>之后,就可以解決訪問靜態資源時產生的異常。而加入<mvc:annotation-driven></mvc:annotation-driven>的目的是為了在訪問靜態資源的同時,也能正常的訪問其他非靜態資源。如果只加<mvc:default-servlet-handler/>而不加<mvc:annotation-driven></mvc:annotation-driven>,就會造成只能訪問靜態資源,而無法訪問非靜態資源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM