1.Spring MVC如何解析視圖
請求處理方法執行完成後,最終傳回一個 ModelAndView對象。對于那些傳回 String,View 或 ModeMap 等類型的處理方法,Spring MVC 也會在内部将它們裝配成一個ModelAndView 對象,它包含了邏輯名和模型對象的視圖。
• Spring MVC 借助視圖解析器(ViewResolver)得到最終的視圖對象(View),最終的視圖可以是 JSP ,也可能是Excel、JFreeChart 等各種表現形式的視圖。
• 對于最終究竟采取何種視圖對象對模型資料進行渲染,處理器并不關心,處理器工作重點聚焦在生産模型資料的工作上,進而實作 MVC 的充分解耦。
原理:對于那些傳回 String,View 或 ModeMap 等類型的處理方法,Spring MVC 會在内部将它們裝配成一個ModelAndView 對象,Spring MVC 借助視圖解析器(ViewResolver)得到最終的視圖對象(View),最終調用view對象的render方法得到結果。
2.視圖
• 視圖的作用是渲染模型資料,将模型裡的資料以某種形式呈現給客戶。
• 為了實作視圖模型和具體實作技術的解耦,Spring 在org.springframework.web.servlet 包中定義了一個高度抽象的 View
接口:
• 視圖對象由視圖解析器負責執行個體化。由于視圖是無狀态(就是每一次請求都會建立一個新的輸出對象)的,是以它們不會有線程安全的問題
• 常用的視圖實作類:主要是前三個類
3.視圖解析器
• SpringMVC 為邏輯視圖名的解析提供了不同的政策,可以在 Spring WEB 上下文中配置一種或多種解析政策,并指定他們之間的先後順序。每一種映射政策對應一個具體的視圖解析器實作類。
• 視圖解析器的作用比較單一:将邏輯視圖解析為一個具體的視圖對象。
• 所有的視圖解析器都必須實作 ViewResolver 接口:
• 常用的視圖解析器實作類:主要前兩個
我們可以選擇一種視圖解析器或混用多種視圖解析器
• 每個視圖解析器都實作了 Ordered 接口并開放出一個 order 屬性,可以通過 order 屬性指定解析器的優先順序,order 越小優先級越高。
• SpringMVC 會按視圖解析器順序的優先順序對邏輯視圖名進行解析,直到解析成功并傳回視圖對象,否則将抛出 ServletException 異常
4.InternalResourceViewResolver
• JSP 是最常見的視圖技術,可以使用InternalResourceViewResolver 作為視圖解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--視圖路徑,轉發後會到這去找檔案-->
<property name="prefix" value="/WEB-INF/views/"></property>
<!--找字尾為jsp的檔案-->
<property name="suffix" value=".jsp"></property>
</bean>
若項目中使用了 JSTL,則 SpringMVC 會自動把視圖由InternalResourceView 轉為 JstlView
• 若使用 JSTL 的 fmt 标簽則需要在 SpringMVC 的配置檔案中配置國際化資源檔案
dispatcher-servlet.xml
<!--配置國際化資源檔案-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
在類路徑下建立國際化資源檔案
i18.properties
i18n.username=Username
i18n.password=Password
i18n_en_US.properties
i18n.username=Username
i18n.password=Password
i18n_zh_CN.properties
i18n.username=使用者名
i18n.password=密碼
然後導入JSTL的兩個jar包
測試類:
private static final String SUCCESS = "success";
@RequestMapping("/testView")
public String testView(){
System.out.println("Test View");
return SUCCESS;
}
success.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:message key="i18n.username"></fmt:message>
<br/>
<fmt:message key="i18n.password"></fmt:message>
- 注意:我一開始運作後随便點選以前的路徑,都會出現500,出現 The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml 異常。
- 我的原因是 Tomcat中缺少這兩個jar包,雖然剛剛jar已經導入項目,但是沒有放入Tomcat下,直接複制兩個jar放入項目路徑下的out\artifacts\項目名\WEB-INF\lib中,就可以運作了
最後注意不要在谷歌浏覽器測試國際化資源,我本以為哪裡錯了,谷歌浏覽器切換成英文國際化資源還是不能變英文,我覺得原因是谷歌浏覽器的英文語言為 en而不是en-US吧。在火狐浏覽器就沒問題
• 若希望直接響應通過 SpringMVC 渲染的頁面,可以使用 mvc:viewcontroller 标簽實作
注意:假設沒有配置mvc:annotation-driven,那麼一旦使用mvc:viewcontroller标簽那麼會導緻其他的 Handler方法失效(Handler方法就是@Controller類下的那些方法),是以先加上,以後再學mvc:annotation-driven
dispatcher-servlet.xml
<!--配置直接轉發頁面-->
<mvc:view-controller path="/su" view-name="success"></mvc:view-controller>
<!--在實際開發中通常要配置 mvc:annotation-driven 标簽-->
<mvc:annotation-driven></mvc:annotation-driven>
通路時直接:
,就會跳轉到目标頁面- success.jsp
5. Excel 視圖
若希望使用 Excel 展示資料清單,僅需要擴充SpringMVC 提供的 AbstractExcelView 或AbstractJExcel View 即可。實作 buildExcelDocument()方法,在方法中使用模型資料對象建構 Excel 文檔就可以了。
• AbstractExcelView 基于 POI API,而AbstractJExcelView 是基于 JExcelAPI 的。
• 視圖對象需要配置 IOC 容器中的一個 Bean,使用BeanNameViewResolver 作為視圖解析器即可
<!--配置視圖 BeanNameViewResolver 解析器:使用視圖名來解析視圖-->
<!--通過 order 屬性來定義 視圖解析器的優先級,order值越小優先級越高-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
• 若希望直接在浏覽器中直接下載下傳 Excel 文檔,則可以設定響應頭 Content-Disposition 的值為
attachment;filename=xxx.xls
注意:最好設定一下視圖解析的優先級,使用order屬性來指定,order的值越低優先級越高,InternalResourceViewResolver的優先級為Integer.MAV_VALUE,也就是優先級最低
例子:先配置好上面那個xml檔案先
自定義的View類:
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.getWriter().println("My View Time is " + new Date());
}
}
測試類
@RequestMapping("/testMyView")
public String testMyView(){
System.out.println("My View");
return "helloView";
}
如果遇到:HTTP Status 404 - /WEB-INF/views/helloView.jsp,則看看自定義的View是否有加入Spring中:
<!--配置自動掃描的包-->
<context:component-scan base-package="路徑"></context:component-scan>
6.關于重定向
• 一般情況下,控制器方法傳回字元串類型的值會被當成邏輯視圖名處理
• 如果傳回的字元串中帶 forward: 或 redirect: 字首時,SpringMVC 會對他們進行特殊處理:将 forward: 和redirect: 當成訓示符,其後的字元串作為 URL 來處理
– redirect:success.jsp:會完成一個到 success.jsp 的重定向的操作
– forward:success.jsp:會完成一個到 success.jsp 的轉發操作