在SpringMVC中,控制器目标方法的返回值均会被装配为ModelAndView对象,其包含逻辑视图的名称和模型数据;逻辑视图即需要视图解析器来将其转换为实际的物理视图。
其中,视图和视图解析器的具体实现代码下载地址:http://download.csdn.net/download/bingbeichen/9793800。
1. 概述
装配: 无论请求处理方法的返回值类型是String、View或ModelMap,SpringMVC均会将其装配为ModelAndView对象,其包含逻辑视图的名称和模型对象信息。
解析: SpringMVC借助视图解析器(ViewResolver)获取最终的物理制图对象,其可以是JSP页面、Excel或JFreeChart等各种表现形式的视图。
2. 视图
为了实现视图模型和具体实现技术的解耦,Spring在org.springframework.web.servlet包中定义高度抽象的View接口;其作用是渲染模型数据,即将模型数据以某种形式呈现给用户。其中,视图对象由视图解析器负责实例化,由于视图是无状态的,故其不会有线程安全的问题。
其中,常用的视图实现类主要有:
大类 | 视图类型 | 说明 |
---|---|---|
资源视图 | InternalResourceView | 将JSP或其他资源封装为视图,是InternalResourceViewResolver默认使用的视图实现类 |
资源视图 | JstlView | 若JSP页面使用了JSTL国际化标签的功能,则需要使用该试图类 |
文档视图 | AbstractExcelView | Excel文档视图的抽象类,其基于POI构造Excel文档 |
文档视图 | AbstractPdfView | PDF文档视图的抽象类,其基于iText构造PDF文档 |
报表视图 | ConfigurableJasperReportsView | 使用JasperReports报表技术的视图 |
报表视图 | JasperReportsCsvView | 使用JasperReports报表技术的视图 |
报表视图 | JasperReportsMultiFormatView | 使用JasperReports报表技术的视图 |
报表视图 | JasperReportsHtmlView | 使用JasperReports报表技术的视图 |
报表视图 | JasperReportsPdfView | 使用JasperReports报表技术的视图 |
报表视图 | JasperReportsXlsView | 使用JasperReports报表技术的视图 |
JSON视图 | MappingJackson2JsonView | 将模型数据通过Jackson开元框架的ObjectMapper以JSON方式输出 |
3. 视图解析器
视图解析器的主要作用是将逻辑视图解析为具体的物理视图对象,可以在Spring WEB上下文中配置一种或多种解析策略,并指定其先后顺序;所有的视图解析器都必须实现ViewResolver接口。
其中,常用的视图解析器实现类主要有:
大类 | 视图类型 | 说明 |
---|---|---|
解析为Bean的名字 | BeanNameViewResolver | 将逻辑视图解析为一个Bean,其id对应于逻辑视图的名称 |
解析为URL文件 | InternalResourceViewResolver | 将逻辑视图解析为一个URL文件,通常解析为一个保存在WEB-INF下的程序文件(如JSP页面) |
解析为URL文件 | JasperResportsViewResolver | 将逻辑视图解析为一个报表文件对应的URL |
模板文件视图 | FreeMarkerViewResolver | 解析为基于FreeMarker模板技术的模板文件 |
模板文件视图 | VelocityViewResolver | 解析为基于Velocity模板技术的模板文件 |
模板文件视图 | VelocityLayoutViewResolver | 解析为基于Velocity模板技术的模板文件 |
说明:每个视图解析器均实现了Ordered接口,可通过其order属性指定解析器的优先顺序,order越小优先级越高;SpringMVC会按视图解析器的顺序对逻辑视图进行解析,直到解析成功并返回视图对象,否则将抛出ServletException异常。
4. InternalResourceViewResolver
JSP是最常见的视图技术,可以使用InternalResourceViewResolver作为视图解析器,SpringMVC会将逻辑视图解析为InternalResourceView对象。
<!-- 配置视图解析器:将逻辑视图解析为物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
5. JstlView
若在WEB-INF/lib目录下添加jstl.jar,则SpringMVC会自动将视图由InternalResourceView转为JstlView。
其中,使用JSTL的fmt标签则需要在SpringMVC的配置文件中配置国际化资源文件:
<!-- springmvc.xml文件:配置国际化资源文件 -->
<!-- 可以在success.jsp页面中导入fmt标签后,使用fmt:message显示对应信息 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
i18n.properties:
i18n.username=UserName
i18n.password=Password
i18n_zh_CN.properties:
i18n.username=\u7528\u6237\u540D
i18n.password=\u5BC6\u7801
i18n_en_US.properties
i18n.username=UserName
i18n.password=Password
6. mvc_view-controller标签
若希望直接响应通过SpringMVC渲染的页面,而不经过目标方法,可以在Spring的Bean配置文件中使用mvc_view-controller标签来实现。
<!-- 配置直接转发的页面 : 可以直接转发到相应页面而无需经过Handler的处理方法 -->
<mvc:view-controller path="springmvc/success" view-name="success"/>
<!-- 在实际开发中通常都需要配置 mvc:annotation-driven 标签 -->
<!-- 若配置mvc:view-controller时,务必要配置mvc:annotation-driven,否则易出错 -->
<mvc:annotation-driven></mvc:annotation-driven>
7. 自定义视图
第一步:创建自定义视图类,继承于View,并将其配置到IoC容器中;
package com.qiaobc.springmvc.view;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
@Component
public class MyView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.getWriter().print("time : " + new Date());
}
}
第二步:在SpringMVC的配置文件中,配置BeanNameViewResolver视图解析器,并配置其优先级;
<!-- 配置BeanNameViewResolver视图解析器 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="1"></property>
</bean>
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.qiaobc.springmvc"></context:component-scan>
第三步:在处理器中编写目标方法,其返回值对应自定义类的BeanName;
@RequestMapping("/springmvc")
@Controller
public class TestViewAndViewResolver {
@RequestMapping("/testView")
public String testView() {
System.out.println("testView...");
return "myView";
}
}
第四步:在index.jsp页面正常使用,即请求springmvc/testView即可。
8. Excel视图
若希望使用Excel展示数据列表,仅需要扩展SpringMVC提供的AbstractExcelView或AbstractJExcelView,实现其buildExcelDocument()方法,并在方法中使用模型数据对象构建Excel 文档即可。
其中,AbstractExcelView是基于POI API的,而AbstractJExcelView是基于JExcel API的。
视图对象需要配置为IOC 容器中Bean,即需要使用BeanNameViewResolver作为视图解析器。
若希望在浏览器中直接下载Excel文档,则可以设置其响应头Content-Disposition的值为attachment;filename=xxx.xls。
9. 重定向
一般情况下,控制器目标方法返回字符串类型的值会被当成逻
辑视图名来处理;但如果返回的字符串中带“forward:”或“redirect:”前缀时,SpringMVC 会对其进行特殊处理,即将“forward:”或“redirect:”当成指示符,其后的字符串作为URL来处理。
@RequestMapping("/springmvc")
@Controller
public class TestViewAndViewResolver {
@RequestMapping("/testRedirect")
public String testRedirect() {
System.out.println("testRedirect");
return "redirect:/index.jsp"; //重定向
}
}
注意:SpringMVC的实现流程具体可参考UrlBasedViewResolver类的createView(String, Locale)方法。