spring 视图解析 ——InternalResourceViewResolver

原文:https://www.cnblogs.com/lyj-gyq/p/8963885.html

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

首先将会介绍 InternalResourceViewResolver,这个视图解析器一般会用来 解析JSP视图。

 1.  Spring提供了两种支持JSP视图的方式: 

  • InternalResourceViewResolver会将视图名解析为JSP文 件。另外,如果在你的JSP页面中使用了JSP标准标签库 (JavaServer Pages Standard Tag Library,JSTL)的 话,InternalResourceViewResolver能够将视图名解析为 JstlView形式的JSP文件,从而将JSTL本地化和资源bundle变量暴 露给JSTL的格式化(formatting)和信息(message)标签。
  • Spring提供了两个JSP标签库,一个用于表单到模型的绑定,另一 个提供了通用的工具类特性。

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

 

当使用@Bean注解的时候,我们可以按照如下的方式配 置Internal-ResourceView Resolver,使其在解析视图时,遵 循上述的约定。

复制代码
1     @Bean // 配置JSP视图解析器
2     public ViewResolver viewResolver() {
3         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
4         resolver.setPrefix("/WEB-INF/views/");
5         resolver.setSuffix(".jsp");
6         resolver.setExposeContextBeansAsAttributes(true);
7         return resolver;
8     }
复制代码

2.  解析JSTL视图

如果在JSP中使用JSTL标签来处理格式化和信息的话,那么就会让InternalResourceViewResolver将视图解析为JstlView。 JSTL的格式化标签需要一个Locale对象,以便于恰当地格式化地域 相关的值,如日期和货币。信息标签可以借助Spring的信息资源和 Locale,从而选择适当的信息渲染到HTML之中。通过解析 JstlView,JSTL能够获得Locale对象以及Spring中配置的信息资 源。 

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

复制代码
1     @Bean // 配置JSP视图解析器
2     public ViewResolver viewResolver() {
3         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
4         resolver.setPrefix("/WEB-INF/views/");
5         resolver.setSuffix(".jsp");
6         resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
7         resolver.setExposeContextBeansAsAttributes(true);
8         return resolver;
9     }
复制代码

3.  Spring的JSP库 

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

3.1  将表单绑定到模型上

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

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

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

需要注意,将前缀指定为“sf”,但通常也可能使用“form”前缀。 在声明完表单绑定标签库之后,就可以使用14个相关的标签了。如下图所示:

重写registerForm.jsp,程序如下:

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>
 3 <%
 4 String path = request.getContextPath();
 5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 6 %>
 7 
 8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 9 <html>
10   <head>
11     <base href="<%=basePath%>">
12     
13     <title>注册</title>
14     
15     <meta http-equiv="pragma" content="no-cache">
16     <meta http-equiv="cache-control" content="no-cache">
17     <meta http-equiv="expires" content="0">    
18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
19     <meta http-equiv="description" content="This is my page">
20     <!--
21     <link rel="stylesheet" type="text/css" href="styles.css">
22     -->
23 
24   </head>
25   
26   <body>
27         <sf:form method="POST" modelAttribute="spitter">
28             First Name:<sf:input path="firstName"/>
29             Last Name:<sf:input path="lastName"/>
30             Email:<sf:input path="email"/>
31             UserName:<sf:input path="username"/>
32             Password:<sf:password path="password"/>
33             <input type="submit" value="注册">
34         </sf:form>
35   </body>
36 </html>
复制代码

<sf:form>会渲染会一个HTML <form>标签,但它也会通过 commandName属性构建针对某个模型对象的上下文信息。在其他的 表单绑定标签中,会引用这个模型对象的属性。 

将commandName属性设置为spitter。因 此,在模型中必须要有一个key为spitter的对象,否则的话,表单 不能正常渲染(会出现JSP错误)。这意味着需要修改一 下SpitterController,以确保模型中存在以spitter为key的 Spitter对象:

1     @RequestMapping(value = "/register", method = RequestMethod.GET) // 处理对“/spitter/register”的GET请求
2     public String showRegistrationForm(Model model) {
3         model.addAttribute(new Spitter());
4         return "registerForm";
5     }

修改后的showRegistrationForm()方法中,新增了一 个Spitter实例到模型中。

3.2  展现错误

相对于标准的HTML标签,使用Spring的表单绑定标签能够带来一定 的功能提升,在校验失败后,表单中会预先填充之前输入的值。但 是,这依然没有告诉用户错在什么地方。为了指导用户矫正错误,需要使用<sf:errors>。 

如果存在校验错误的话,请求中会包含错误的详细信息,这些信息是 与模型数据放到一起的。我们所需要做的就是到模型中将这些数据抽 取出来,并展现给用户。<sf:errors>能够让这项任务变得很简 单。 

1 <sf:errors path="firstName">
2             <span id="firstName.errors">必须大于2个字符</span>
3         </sf:errors>

将<sf:errors>用到First Name输入域的场景,它的path属性设置成了firstName,也就是指定了要显示Spitter 模型对象中哪个属性的错误。如果firstName属性没有错误的话, 那么<sf:errors>不会渲染任何内容。但如果有校验错误的话,那 么它将会在一个HTML <span>标签中显示错误信息。 

4.  Spring通用的标签库

除了表单绑定标签库之外,Spring还提供了更为通用的JSP标签库。要使用Spring通用的标签库,我们必须要在页面上对其进行声明:

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

标签库声明之后,我们就可以使用下表中的十个JSP标签了。

 

4.1  展现国际化信息

对于渲染文本来说,是很好的方案,文本能够位于一个或多个属性文 件中。借助<s:message>,我们可以将硬编码的欢迎信息替换为如 下的形式:

按照这里的方式,<s:message>将会根据key为spittr.welcome 的信息源来渲染文本。因此,如果我们希望<s:message>能够正常 完成任务的话,就需要配置一个这样的信息源。 

Spring有多个信息源的类,它们都实现了MessageSource接口。在 这些类中,更为常见和有用的 是ResourceBundleMessageSource。它会从一个属性文件中加 载信息,这个属性文件的名称是根据基础名称(base name)衍生而来 的。如下的@Bean方法配置了 ResourceBundleMessageSource:

1     @Bean
2     public MessageSource messageSource() {
3         ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
4         messageSource.setBasename("message");
5         return messageSource;
6     }

在这个bean声明中,核心在于设置basename属性。你可以将其设置 为任意的值,在这里,我将其设置为message。将其设置 为message后,ResourceBundle-MessageSource就会试图在根 路径的属性文件中解析信息,这些属性文件的名称是根据这个基础名 称衍生得到的。

另外的可选方案是使 用ReloadableResourceBundleMessageSource,它的工作方 式与ResourceBundleMessageSource非常类似,但是它能够重 新加载信息属性,而不必重新编译或重启应用。如下是配 置ReloadableResourceBundle-MessageSource的样例:

复制代码
1     @Bean
2     public MessageSource messageSource2() {
3         ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
4         messageSource.setBasename("file:///etc/spittr/message");
5         messageSource.setCacheSeconds(10);
6         return messageSource;
7     }
复制代码

这里的关键区别在于basename属性设置为在应用的外部查找(而不 是像ResourceBundleMessageSource那样在类路径下查 找)。basename属性可以设置为在类路径下(以“classpath:”作 为前缀)、文件系统中(以“file:”作为前缀)或Web应用的根路径 下(没有前缀)查找属性。在这里,我将其配置为在服务器文件系统 的“/etc/spittr”目录下的属性文件中查找信息,并且基础的文件名 为“message”。

这两个bean放在WebConfig.java中

创建属性文件:message.properties 位置:src下,类的根目录

1 spittr.welcome=Welcome to Spittr\! 

4.2  创建URL 

<s:url>是一个很小的标签。它主要的任务就是创建URL,然后将其 赋值给一个变量或者渲染到响应中。它是JSTL中<c:url>标签的替 代者,但是它具备几项特殊的技巧。

按照其最简单的形式,<s:url>会接受一个相对于Servlet上下文的 URL,并在渲染的时候,预先添加上Servlet上下文路径。例如,考虑 如下<s:url>的基本用法:

如果应用的Servlet上下文名为spittr,那么在响应中将会渲染如下 的HTML:

这样,在创建URL的时候,就不必再担心Servlet上下文路径是什 么了,<s:url>将会负责这件事。 

另外,还可以使用<s:url>创建URL,并将其赋值给一个变量供 模板在稍后使用:

默认情况下,URL是在页面作用域内创建的。但是通过设置scope属 性,我们可以让<s:url>在应用作用域内、会话作用域内或请求作 用域内创建URL:

如果希望在URL上添加参数的话,那么可以使用<s:param>标 签。比如,如下的<s:url>使用两个内嵌的<s:param>标签,来设 置“/spittles”的max和count参数:

重点:创建带有路径 (path)参数的URL

当href属性中的占位符匹配<s:param>中所指定的参数时,这个参 数将会插入到占位符的位置中。如果<s:param>参数无法匹配href 中的任何占位符,那么这个参数将会作为查询参数。 

posted @ 2019-05-12 16:35  S3c0ldW4ng  阅读(2240)  评论(0编辑  收藏  举报