• 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 关于转发和重定向方面的资料。

  • 相关阅读:
    Scala 深入浅出实战经典 第62讲:Scala中上下文界定内幕中的隐式参数实战详解
    Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
    Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
    Scala 深入浅出实战经典 第58讲:Scala中Abstract Types实战详解
    第58讲:Scala中Abstract Types实战详解
    Scala 深入浅出实战经典 第57讲:Scala中Dependency Injection实战详解
    Scala 深入浅出实战经典 第55讲:Scala中Infix Type实战详解
    Scala 深入浅出实战经典 第54讲:Scala中复合类型实战详解
    Scala 深入浅出实战经典 第53讲:Scala中结构类型实战详解
    Scala 深入浅出实战经典 第52讲:Scala中路径依赖代码实战详解
  • 原文地址:https://www.cnblogs.com/2015110615L/p/5633655.html
Copyright © 2020-2023  润新知