Spring MVC 框架学习四:Spring MVC 中的视图和视图解析器

 

视图和视图解析器

请求处理方法执行完成后,最终返回一个 ModelAndView 对象,对于那些返回 String、View 或 ModelMap 等类型的处理方法,SpringMVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了视图逻辑和模型对象的信息

SpringMVC 借助视图解析器 (ViewResolver) 得到最终的视图对象 (View),这可能是我们常见的 JSP 视图,也可能是一个基于 FreeMarker、Velocity 模本技术的视图,还可能是PDF、Excel、XML、JSON等各种形式的视图。

对于最终究竟采用何种视图对象对模型数据进行渲染,处理器并不关心,处理器的工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分耦合

 

认识视图

  视图的作用是渲染模型数据,将模型数据里的数据以某种形式呈现给客户。视图对象可以是常见的 JSP,还可以是 Excel 或 PDF 等形式不一样的媒体形式。为了实现视图模型和具体实现技术的解耦,Spring在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口,该接口定义了两个方法:

1. String getContentType():视图对应的 MIME 类型,如 text/html、image/jpeg 等

2. void render(Map model, HttpServletRequest request, HttpServletResponse reponse):将模型数据以某种 MIME 类型渲染出来

视图对象是一个 Bean ,通常情况下,视图对象由视图解析器负责实例化。由于视图Bean是无状态的,所以它们不会有线程安全问题。

不同类型的视图实现技术对应不同的 View 实现类,这些实现类都位于 org.springframework.web.servlet.view 包中,常见的实现类如下

大类

视图类型

说明

URL 视图资源

InternalResourceView

将JSP或其他资源封装成一个视图,是InternalResourceViewResolver默认使用的视图实现类

Jstliew

如果JSP文件中使用了JSTL国际化标签的功能,则需要使用该视图类

文档视图

AbstractExcelView

Excel文件视图的抽象类。该视图类基于POI构造Excel文档

AbstractPdfView

PDF文档视图的抽象类。该视图类基于iText构造PDF文档

报表视图

ConfigurableJsperResportsView   

几个使用 JasperResports报表技术的视图

JasperReportsCsvView

JasperResportsMultiFormatView    

JasperResportsHtmlView

JasperResportsPdfView

JasperResportsXlsView

JSON视图

MappingJacksonJsonView

将模型数据通过 Jackson开源框架的ObjectMapper以JSON方式输出

 

认识视图解析器

  SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring Web 上下文配置一种或多种解析策略,并指定它们之间的先后顺序。每一种解析策略对应一个具体的视图解析器实现类,视图解析器的工作比较单一:将逻辑视图名解析为一个具体的视图对象。所有视图解析器都实现了 ViewResolver 接口,该接口仅有一个方法:

View resolveViewName(String viewName, Locale locale)

resolveViewName()的签名清楚地向我们传达了视图解析器工作的内涵:根据逻辑视图名和本地化对象得到一个视图对象。常用的视图解析器实现类如下表

大类

视图类型

说明

解析为Bean 的名字

BeanNameViewResolver

将逻辑视图名解析为一个BeanBean 的id等于逻辑视图名

 

解析为URL文件

InternalResolverViewResolver

将视图解析为一个URL文件,一般使用该解析器将视图名映射为一个保存在WEN-INF目录下的程序文件(JSP)

JasperResportsViewResolver

JasperResports是一个基于Java的开源报表工具,该解析器将视图名解析为报表文件对应的URL

 

 

模板文件

 FreeMarkerViewResolver

解析为基于FreeMarker模板技术的模板文件

VelocityViewResolver

 

解析为基于Velocity模板技术的模板文件

VelocityLayoutViewResolver

我们可以选择一种视图解析器或混用多种视图解析器。

每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。

SpringMVC会按视图解析器的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常。

JSP是最常见的视图技术,可以使用 InternalResourceViewResolver 作为视图解析器

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

若项目中使用了 JSTL,则SpringMVC 会自动把视图由 InternalResourceView 转为JstlView,若使用 JSTL 的 fmt 标签需要在 SpringMVC 的配置文件中配置国际化资源文件

    <bean class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"></property>
    </bean>

若希望直接响应转发的页面,而无需在经过 Handler 的方法,可以使用 <mvc:view-controller> 标签实现

<mvc:view-controller path="/success" view-name="success"/>

在实际开发时通常需要配置 <mvc:annotation-driven> 标签来配合使用

<mvc:annotation-driven></mvc:annotation-driven>

我们还可以实现自己的视图,实现自己的视图需要实现 View 接口。新建一个 HelloView 类

package com.bupt.springmvc.views;

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 HelloView 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("hello view, time " + new Date());
    }
}

springDispatcherSerlet-servlet.xml 配置解析器,我们使用视图名字来解析视图,所以需要实例化视图类

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.bupt.springmvc"/>
    
    <!-- 配置视图 BeanNameViewResolver 解析器:使用视图名字来解析视图 -->
    <!-- 通过 order 属性来定义视图的优先级,order 值越小优先级越高 -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="100"></property>
    </bean>

配置web.xml

    <!-- 自定义的spring 配置文件可以放置在src下,名字在属性中指定 -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

创建 Handler 方法类

@RequestMapping("/springmvc")
@Controller
public class SpringTest
{
    private static final String SUCCESS = "success"
    
    @RequestMapping("/testView")
    public String testView()
    {
        System.out.println("Test View");
        return "helloView";
    } 
}

定义一个index.jsp页面,编写一个超链接

<a href="springmvc/testView">Test View</a>

启动服务器,访问jsp页面点击超链接,可以看到程序跳转和控制台输出

 

重定向和转发

一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图处理,如果返回的字符串中带 forward: redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward:和 redirect: 当成指示符,其后的字符串作为 URL 来处理

- redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作

- forward:success.jsp:会完成一个到 success.jsp 的转发操作

在SpringTest类中增加映射,同时在index.jsp中增加超链接

    @RequestMapping("/testRedirect")
    public String testRedirect()
    {
        System.out.println("Test Redirect");
        return "redirect:/index.jsp";
     // return "forward:/index.jsp"; }
<a href="springmvc/testRedirect">Test Redirect</a>

当启动服务器点击超链接时,可以看到页面重新跳转回index.jsp页面

程序在执行重定向和转发操作时,会判断程序是以 redirect 还是 forward 作为前缀。如果以 redirect 作为前缀,则程序会在底层创建一个 RedirectView,若果是 forward 则会在低层创建一个 InternalResourceView。

 forward 转发和 redirect 重定向,二者直观的区别就是:forward 时浏览器地址栏不会变,但是有视图返回回来;redirect 时地址栏会发生变化。

二者其实在整个请求处理的过程中存在本质的区别,具体可以查看 javaweb 关于转发和重定向方面的资料。

原文地址:https://www.cnblogs.com/2015110615L/p/5633655.html