筆記29 視圖解析 ——InternalResourceViewResolver


Spring自帶了13個視圖解析器,能夠將邏輯視圖名轉換為物理實現

首先將會介紹 InternalResourceViewResolver,這個視圖解析器一般會用來 解析JSP視圖。

 1.  Spring提供了兩種支持JSP視圖的方式: 

  • InternalResourceViewResolver會將視圖名解析為JSP文 件。另外,如果在你的JSP頁面中使用了JSP標准標簽庫 (JavaServer Pages Standard Tag Library,JSTL)的 話,InternalResourceViewResolver能夠將視圖名解析為 JstlView形式的JSP文件,從而將JSTL本地化和資源bundle變量暴 露給JSTL的格式化(formatting)和信息(message)標簽。
  • Spring提供了兩個JSP標簽庫,一個用於表單到模型的綁定,另一 個提供了通用的工具類特性。

考慮一個簡單的場景,假設邏輯視圖名為home。通用的 實踐是將JSP文件放到Web應用的WEB-INF目錄下,防止對它的直接 訪問。如果我們將所有的JSP文件都放在“/WEB-INF/views/”目錄下, 並且home頁的JSP名為home.jsp,那么我們可以確定物理視圖的路徑 就是邏輯視圖名home再加上“/WEB-INF/views/”前綴和“.jsp”后綴。如下圖所示:

 

當使用@Bean注解的時候,我們可以按照如下的方式配 置Internal-ResourceView Resolver,使其在解析視圖時,遵 循上述的約定。

1     @Bean // 配置JSP視圖解析器
2     public ViewResolver viewResolver() {
3         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
4         resolver.setPrefix("/WEB-INF/views/");
5         resolver.setSuffix(".jsp");
6         resolver.setExposeContextBeansAsAttributes(true);
7         return resolver;
8     }

2.  解析JSTL視圖

如果在JSP中使用JSTL標簽來處理格式化和信息的話,那么就會讓InternalResourceViewResolver將視圖解析為JstlView。 JSTL的格式化標簽需要一個Locale對象,以便於恰當地格式化地域 相關的值,如日期和貨幣。信息標簽可以借助Spring的信息資源和 Locale,從而選擇適當的信息渲染到HTML之中。通過解析 JstlView,JSTL能夠獲得Locale對象以及Spring中配置的信息資 源。 

如果想讓InternalResourceViewResolver將視圖解析 為JstlView,而不是InternalResourceView的話,那么我們只需設置它的viewClass屬性即可:

1     @Bean // 配置JSP視圖解析器
2     public ViewResolver viewResolver() {
3         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
4         resolver.setPrefix("/WEB-INF/views/");
5         resolver.setSuffix(".jsp");
6         resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
7         resolver.setExposeContextBeansAsAttributes(true);
8         return resolver;
9     }

3.  Spring的JSP庫 

Spring提供了兩個JSP標簽庫,用來幫助定義 Spring MVC Web的視圖。其中一個標簽庫會用來渲染HTML表單標 簽,這些標簽可以綁定model中的某個屬性。另外一個標簽庫包含了 一些工具類標簽

3.1  將表單綁定到模型上

Spring的表單綁定JSP標簽庫包含了14個標簽,它們中的大多數都用來 渲染HTML中的表單標簽。但是,它們與原生HTML標簽的區別在於 它們會綁定模型中的一個對象,能夠根據模型中對象的屬性填充值。 標簽庫中還包含了一個為用戶展現錯誤的標簽,它會將錯誤信息渲染 到最終的HTML之中。 

為了使用表單綁定庫,需要在JSP頁面中對其進行聲明:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>

需要注意,將前綴指定為“sf”,但通常也可能使用“form”前綴。 在聲明完表單綁定標簽庫之后,就可以使用14個相關的標簽了。如下圖所示:

重寫registerForm.jsp,程序如下:

 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>
 3 <%
 4 String path = request.getContextPath();
 5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 6 %>
 7 
 8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 9 <html>
10   <head>
11     <base href="<%=basePath%>">
12     
13     <title>注冊</title>
14     
15     <meta http-equiv="pragma" content="no-cache">
16     <meta http-equiv="cache-control" content="no-cache">
17     <meta http-equiv="expires" content="0">    
18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
19     <meta http-equiv="description" content="This is my page">
20     <!--
21     <link rel="stylesheet" type="text/css" href="styles.css">
22     -->
23 
24   </head>
25   
26   <body>
27         <sf:form method="POST" modelAttribute="spitter">
28             First Name:<sf:input path="firstName"/>
29             Last Name:<sf:input path="lastName"/>
30             Email:<sf:input path="email"/>
31             UserName:<sf:input path="username"/>
32             Password:<sf:password path="password"/>
33             <input type="submit" value="注冊">
34         </sf:form>
35   </body>
36 </html>

<sf:form>會渲染會一個HTML <form>標簽,但它也會通過 commandName屬性構建針對某個模型對象的上下文信息。在其他的 表單綁定標簽中,會引用這個模型對象的屬性。 

將commandName屬性設置為spitter。因 此,在模型中必須要有一個key為spitter的對象,否則的話,表單 不能正常渲染(會出現JSP錯誤)。這意味着需要修改一 下SpitterController,以確保模型中存在以spitter為key的 Spitter對象:

1     @RequestMapping(value = "/register", method = RequestMethod.GET) // 處理對“/spitter/register”的GET請求
2     public String showRegistrationForm(Model model) {
3         model.addAttribute(new Spitter());
4         return "registerForm";
5     }

修改后的showRegistrationForm()方法中,新增了一 個Spitter實例到模型中。

3.2  展現錯誤

相對於標准的HTML標簽,使用Spring的表單綁定標簽能夠帶來一定 的功能提升,在校驗失敗后,表單中會預先填充之前輸入的值。但 是,這依然沒有告訴用戶錯在什么地方。為了指導用戶矯正錯誤,需要使用<sf:errors>。 

如果存在校驗錯誤的話,請求中會包含錯誤的詳細信息,這些信息是 與模型數據放到一起的。我們所需要做的就是到模型中將這些數據抽 取出來,並展現給用戶。<sf:errors>能夠讓這項任務變得很簡 單。 

1 <sf:errors path="firstName">
2             <span id="firstName.errors">必須大於2個字符</span>
3         </sf:errors>

將<sf:errors>用到First Name輸入域的場景,它的path屬性設置成了firstName,也就是指定了要顯示Spitter 模型對象中哪個屬性的錯誤。如果firstName屬性沒有錯誤的話, 那么<sf:errors>不會渲染任何內容。但如果有校驗錯誤的話,那 么它將會在一個HTML <span>標簽中顯示錯誤信息。 

4.  Spring通用的標簽庫

除了表單綁定標簽庫之外,Spring還提供了更為通用的JSP標簽庫。要使用Spring通用的標簽庫,我們必須要在頁面上對其進行聲明:

1 <%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>

標簽庫聲明之后,我們就可以使用下表中的十個JSP標簽了。

 

4.1  展現國際化信息

對於渲染文本來說,是很好的方案,文本能夠位於一個或多個屬性文 件中。借助<s:message>,我們可以將硬編碼的歡迎信息替換為如 下的形式:

按照這里的方式,<s:message>將會根據key為spittr.welcome 的信息源來渲染文本。因此,如果我們希望<s:message>能夠正常 完成任務的話,就需要配置一個這樣的信息源。 

Spring有多個信息源的類,它們都實現了MessageSource接口。在 這些類中,更為常見和有用的 是ResourceBundleMessageSource。它會從一個屬性文件中加 載信息,這個屬性文件的名稱是根據基礎名稱(base name)衍生而來 的。如下的@Bean方法配置了 ResourceBundleMessageSource:

1     @Bean
2     public MessageSource messageSource() {
3         ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
4         messageSource.setBasename("message");
5         return messageSource;
6     }

在這個bean聲明中,核心在於設置basename屬性。你可以將其設置 為任意的值,在這里,我將其設置為message。將其設置 為message后,ResourceBundle-MessageSource就會試圖在根 路徑的屬性文件中解析信息,這些屬性文件的名稱是根據這個基礎名 稱衍生得到的。

另外的可選方案是使 用ReloadableResourceBundleMessageSource,它的工作方 式與ResourceBundleMessageSource非常類似,但是它能夠重 新加載信息屬性,而不必重新編譯或重啟應用。如下是配 置ReloadableResourceBundle-MessageSource的樣例:

1     @Bean
2     public MessageSource messageSource2() {
3         ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
4         messageSource.setBasename("file:///etc/spittr/message");
5         messageSource.setCacheSeconds(10);
6         return messageSource;
7     }

這里的關鍵區別在於basename屬性設置為在應用的外部查找(而不 是像ResourceBundleMessageSource那樣在類路徑下查 找)。basename屬性可以設置為在類路徑下(以“classpath:”作 為前綴)、文件系統中(以“file:”作為前綴)或Web應用的根路徑 下(沒有前綴)查找屬性。在這里,我將其配置為在服務器文件系統 的“/etc/spittr”目錄下的屬性文件中查找信息,並且基礎的文件名 為“message”。

這兩個bean放在WebConfig.java中

創建屬性文件:message.properties 位置:src下,類的根目錄

1 spittr.welcome=Welcome to Spittr\! 

4.2  創建URL 

<s:url>是一個很小的標簽。它主要的任務就是創建URL,然后將其 賦值給一個變量或者渲染到響應中。它是JSTL中<c:url>標簽的替 代者,但是它具備幾項特殊的技巧。

按照其最簡單的形式,<s:url>會接受一個相對於Servlet上下文的 URL,並在渲染的時候,預先添加上Servlet上下文路徑。例如,考慮 如下<s:url>的基本用法:

如果應用的Servlet上下文名為spittr,那么在響應中將會渲染如下 的HTML:

這樣,在創建URL的時候,就不必再擔心Servlet上下文路徑是什 么了,<s:url>將會負責這件事。 

另外,還可以使用<s:url>創建URL,並將其賦值給一個變量供 模板在稍后使用:

默認情況下,URL是在頁面作用域內創建的。但是通過設置scope屬 性,我們可以讓<s:url>在應用作用域內、會話作用域內或請求作 用域內創建URL:

如果希望在URL上添加參數的話,那么可以使用<s:param>標 簽。比如,如下的<s:url>使用兩個內嵌的<s:param>標簽,來設 置“/spittles”的max和count參數:

重點:創建帶有路徑 (path)參數的URL

當href屬性中的占位符匹配<s:param>中所指定的參數時,這個參 數將會插入到占位符的位置中。如果<s:param>參數無法匹配href 中的任何占位符,那么這個參數將會作為查詢參數。 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

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



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