Spring实战第六章(待完善)

渲染视图

1、视图解析器

在控制器方法都没有直接产生浏览器中渲染所需的HTML。这些方法只是将一些数据填充到模型中,然后将模型传递给一个用来渲染的视图。Spring MVC使得控制器中请求处理的逻辑和视图中的渲染实现解耦。

控制器方法和视图的实现会在模型内容上达成一致,这是两者的最大关联,除此之外,两者应该保持足够的距离。

视图解析器的基础:

Spring MVC定义了一个名为ViewResolver的接口,它大致如下所示:

当给resolveViewName()方法传入一个视图名和Locale对象时,它会返回一个View实例。View是另外一个接口,如下所示:

View接口的任务就是接受模型以及Servlet的request和response对象,并将输出结果渲染到response中。我们所需要做的就是编写ViewResolver和View的实现,将要渲染的内容放到response中,进而展现到用户的浏览器中。

但是:一般来讲,我们并不需要关心这些接口。Spring提供了多个内置的实现,如表6.1所示,它们能够适应大多数的场景。

Spring自带了12个视图解析器,能够将逻辑视图名转换为物理实现。

视图解析器 描  述
BeanNameViewResolver

将视图解析为Spring应用上下文中的bean,其中
bean的ID与视图的名字相同

ContentNegotiatingViewResolver

通过考虑客户端需要的内容类型来解析视图,
委托给另外一个能够产生对应内容类型的视图
解析器

FreeMarkerViewResolver 将视图解析为FreeMarker模板
InternalResourceViewResolver

将视图解析为Web应用的内部资源(一般为
JSP)

JasperReportsViewResolver 将视图解析为JasperReports定义
ResourceBundleViewResolver 将视图解析为资源bundle(一般为属性文件)
TilesViewResolver

将视图解析为Apache Tile定义,其中tile ID与视
图名称相同。注意有两个不同的
TilesViewResolver实现,分别对应于Tiles 2.0和
Tiles 3.0

UrlBasedViewResolver

直接根据视图的名称解析视图,视图的名称会
匹配一个物理视图的定义

VelocityLayoutViewResolver

将视图解析为Velocity布局,从不同的Velocity模
板中组合页面

VelocityViewResolver 将视图解析为Velocity模板
XmlViewResolver

将视图解析为特定XML文件中的bean定义。类
似于BeanNameViewResolver

XsltViewResolver 将视图解析为XSLT转换后的结果

2、创建jsp视图

Spring提供了两种支持JSP视图的方式:
  1、InternalResourceViewResolver会将视图名解析为JSP文件。另外,如果在你的JSP页面中使用了JSP标准标签库(JavaServer Pages Standard Tag Library,JSTL)的话,InternalResourceViewResolver能够将视图名解析为JstlView形式的JSP文件,从而将JSTL本地化和资源bundle变量暴露给JSTL的格式化(formatting)和信息(message)标签。

  2、Spring提供了两个JSP标签库,一个用于表单到模型的绑定,另一个提供了通用的工具类特性。

 不管你使用JSTL,还是准备使用Spring的JSP标签库,配置解析JSP的视图解析器都是非常重要的。尽管Spring还有其他的几个视图解析器都能将视图名映射为JSP文件,但就这项任务来讲,InternalResourceViewResolver是最简单和最常用的视图解析器

 InternalResourceViewResolver遵循一种约定,会在视图名上添加前缀和后缀,进而确定一个Web应用中视图资源的物理路径。

  例如:一个简单的场景,假设逻辑视图名为home。通用的实践是将JSP文件放到Web应用的WEB-INF目录下,防止对它的直接访问。如果将所有的JSP文件都放在“/WEB-INF/views/”目录下,并且home页的JSP名为home.jsp,那么我们可以确定物理视图的路径就是逻辑视图名home再加上“/WEB-INF/views/”前缀和“.jsp”后缀。

如何配置InternalResourceViewResolver视图解析器:

  1、在Javaconfig中配置方式:

    @Bean
    public ViewResolver viewResolver(){   //配置JSP视图解析器
        InternalResourceViewResolver resolver = 
                new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }
    

  2、或在xml中配置

InternalResourceViewResolver配置就绪之后,它就会将逻辑视图名解析为JSP文件

例子:books/detail将会解析为“/WEB-INF/views/books/detail.jsp”

注意:当逻辑视图名中包含斜线时,这个斜线也会带到资源的路径名中。因此,它会对应到prefix属性所引用目录的子目录下的JSP文件。

2.1解析JSTL视图

  如果这些JSP使用JSTL标签来处理格式化和信息的话,那么应该InternalResourceViewResolver将视图解析为JstlView。

  JSTL的格式化标签需要一个Locale对象,以便于恰当地格式化地域相关的值,如日期和货币。信息标签可以借助Spring的信息资源和Locale,从而选择适当的信息渲染到HTML之中。通过解析JstlView,JSTL能够获得Locale对象以及Spring中配置的信息资源。(Locale 对象表示了特定的地理、政治和文化地区。需要 Locale 来执行其任务的操作称为语言环境敏感的 操作,它使用 Locale 为用户量身定制信息。例如,显示一个数值就是语言环境敏感的操作,应该根据用户的国家、地区或文化的风俗/传统来格式化该数值。)

  如果想让InternalResourceViewResolver将视图解析为JstlView,而不是InternalResourceView的话,那么我们只需设置它的viewClass属性即可:

    @Bean
    public ViewResolver viewResolver(){   //配置JSP视图解析器
        InternalResourceViewResolver resolver = 
                new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

 

  (配置org.springframework.web.servlet.view.JstlView,是因为要解析成jstlview,但是当导入了JSTL的标签jar包,不配也可以解析)

  或者在xml中:

2.2 JSP库

Spring提供了两个JSP标签库,用来帮助定义Spring MVC Web的视图。其中一个标签库会用来渲染HTML表单标签,这些标签可以绑定model中的某个属性。另外一个标签库包含了一些工具类标签,我们随时都可以非常便利地使用它们。

 a、表单绑定到模型上

Spring的表单绑定JSP标签库包含了14个标签,它们中的大多数都用来渲染HTML中的表单标签。但是,它们与原生HTML标签的区别在于它们会绑定模型中的一个对象能够根据模型中对象的属性填充值。标签库中还包含了一个为用户展现错误的标签,它会将错误信息渲染到最终的HTML之中。

  使用表单绑定库,需要在JSP页面中对其进行声明:

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

 

 十四个相关的标签

JSP标签 描  述
<sf:checkbox>

渲染成一个HTML <input>标签,其中type属性设置
为checkbox

<sf:checkboxes>

渲染成多个HTML <input>标签,其中type属性设置
为checkbox

<sf:errors> 在一个HTML <span>中渲染输入域的错误
<sf:form>

渲染成一个HTML <form>标签,并为其内部标签暴露绑定路
径,用于数据绑定

<sf:hidden> 渲染成一个HTML <input>标签,其中type属性设置为hidden
<sf:input> 渲染成一个HTML <input>标签,其中type属性设置为text
<sf:label> 渲染成一个HTML <label>标签
<sf:option>

渲染成一个HTML <option>标签,其selected属性根据所绑定
的值进行设置

<sf:options>

按照绑定的集合、数组或Map,渲染成一个HTML <option>标
签的列表

<sf:password>

渲染成一个HTML <input>标签,其中type属性设置
为password

<sf:radiobutton> 渲染成一个HTML <input>标签,其中type属性设置为radio
<sf:radiobuttons> 渲染成多个HTML <input>标签,其中type属性设置为radio
<sf:select> 渲染为一个HTML <select>标签
<sf:textarea> 渲染为一个HTML <textarea>标签

介绍略

3、Tiles视图定义布局

Spring MVC以视图解析器的形式为Apache Tiles提供了支持,这个视图解析器能够将逻辑视图名解析为Tile定义。

3.1配置Tiles视图解析器

在Spring中使用Tiles,需要配置几个bean。

需要一个TilesConfigurer bean,它会负责定位和加载Tile定义并协调生成Tiles。除此之外,还需要TilesViewResolver bean将逻辑视图名称解析为Tile定义。

TilesConfigurer bean把其定义在了WebConfig中, 

      // Tiles
      @Bean
      public TilesConfigurer tilesConfigurer() {
        TilesConfigurer tiles = new TilesConfigurer();
        tiles.setDefinitions(new String[] {
            "/WEB-INF/layout/tiles.xml",
            "/WEB-INF/views/**/tiles.xml"
        });
        tiles.setCheckRefresh(true);
        return tiles;
      }

当配置TilesConfigurer的时候,所要设置的最重要的属性就是definitions这个属性接受一个String类型的数组,其中每个条目都指定一个Tile定义的XML文件。对于Spittr应用来讲,我们让它在“/WEB-INF/layout/”目录下查找tiles.xml。 其实我们还可以指定多个Tile定义文件,甚至能够在路径位置上使用通配符(例如使用了Ant风格的通配符(**)),当然在上例中我们没有使用该功能。例如,我们要 求TilesConfigurer加载“/WEB-INF/”目录下的所有名字为tiles.xml 的文件,那么可以按照如下的方式设置definitions属性。

之后配置TilesViewResolver bean(在webConfig之中)

      @Bean
      public ViewResolver viewResolverTile() {
        return new TilesViewResolver();
      }

 

或者把上面的bean配置在xml之中

TilesConfigurer会加载Tile定义并与Apache Tiles协作,而TilesViewResolver会将逻辑视图名称解析为引用Tile定义的视图

 3.2定义Tiles

Apache Tiles提供了一个文档类型定义(document type definition,DTD),用来在XML文件中指定Tile的定义。每个定义中需要包含一个<definition>元素,这个元素会有一个或多个<put-attribute>元素

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
    <definition name="base" template="/WEB-INF/layout/page.jsp">        定义bese Tiles
      <put-attribute name="header" value="/WEB-INF/layout/header.jsp"/>   扩展属性
      <put-attribute name="footer" value="/WEB-INF/layout/footer.jsp"/> 
    </definition>
    
<definition name="home" extends="base">                   扩展base Tiles
    <put-attribute name="body" value="/WEB-INF/views/home.jsp" />
  </definition>

  <definition name="registerForm" extends="base">
    <put-attribute name="body" value="/WEB-INF/views/registerForm.jsp" />
  </definition>

  <definition name="profile" extends="base">
    <put-attribute name="body" value="/WEB-INF/views/profile.jsp" />
  </definition>

  <definition name="spittles" extends="base">
    <put-attribute name="body" value="/WEB-INF/views/spittles.jsp" />
  </definition>

  <definition name="spittle" extends="base">
    <put-attribute name="body" value="/WEB-INF/views/spittle.jsp" />
  </definition>

</tiles-definitions>

 

每个<definition>元素都定义了一个Tile,它最终引用的是一个JSP模板。在名为base的Tile中,模板引用的是“/WEB-INF/layout/page.jsp”。某个Tile可能还会引用其他的JSP模板,使这些JSP模板嵌入到主模板中。对于base Tile来讲,它引用的是一个头部JSP模板和一个底部JSP模板。

base Tile所引用的page.jsp模板如下面程序清单所示。主布局模板:引用其他模板来创建视图  

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %>

<%@ page session="false" %>
<html>
  <head>
    <title>Spittr</title>
    <link rel="stylesheet" 
          type="text/css" 
          href="<s:url value="/resources/style.css" />" >
  </head>
  <body>
    <div id="header">
      <t:insertAttribute name="header" />
    </div>
    <div id="content">
      <t:insertAttribute name="body" />
    </div>
    <div id="footer">
      <t:insertAttribute name="footer" />
    </div>
  </body>
</html>

 

(注意:在写<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %>可能会报错,

需要在maven中写入:

<dependency>
  <groupId>org.apache.tiles</groupId>
  <artifactId>tiles-jsp</artifactId>
  <version>3.0.7</version>
</dependency>

) 

使用Tile标签库中的<t:insert Attribute> JSP标签来插入其他的模板。在这里,用它来插入名为header、body和footer的模板。

在这里,base Tile不会期望单独使用。它会作为基础定义(这是其名字的来历),供其他的Tile定义扩展。在程序清单6.2的其余内容中,我们可以看到其他的Tile定义都是扩展自base Tile。它意味着它们会继承其header和footer属性的设置(当然,Tile定义中也可以覆盖掉这些属性),但是每一个都设置了body属性,用来指定每个Tile特有的JSP模板。

现在,我们关注一下home Tile,它扩展了base。因为它扩展了base,因此它会继承base中的模板和所有的属性。尽管home Tile定义相对来说很简单,但是它实际上包含了如下的定义:

 

posted @ 2017-03-15 20:18  mslog  阅读(308)  评论(0编辑  收藏  举报