本章简介

视图(View)和视图解析器(ViewResolver)的工作流程:

当请求处理方法处理完请求之后,会返回String、ModelAndView或View对象,如return “success”;但返回值最终都会被SpringMVC统一转为ModelAndView对象并返回;随后Spring就会用ViewResolver,把返回的ModelAndView对象中的View渲染给用户看(即返回给浏览器),如图,

图28-01

28.1 视图View

视图View的作用是渲染数据,将数据以JSP、PDF、EXCEL等形式呈现给用户。SpringMVC通过View接口来支持视图,该接口提供了各种各样的视图,并且可以让用户自定义视图。

在客户端的每一次请求时,视图解析器ViewResolver都会产生一个新的视图View对象。

视图View接口的实现类及部分简介如下

图28-02

视图类型 简介
URL视图资源图 InternalResourceView 将JSP或其他资源封装成一个视图。被视图解析器InternalResourceViewResolver默认使用。
JstlView InternalResourceView的子类。如果JSP中使用了JSTL的国际化标签,就需要使用该视图类。
文档视图 AbstractExcelView Excel文档视图的抽象类。
AbstractPdfView PDF文档视图的抽象类
报表视图 ConfigurableJasperReportsView 常用的JasperReports报表视图
JasperReportsHtmlView
JasperReportsPdfView
JasperReportsXlsView
JSON视图 MappingJackson2JsonView 将数据通过Jackson框架的ObjectMapper对象,以JSON方式输出

28.2 视图解析器ViewResolver

SpringMVC提供了一个视图解析器的上级接口ViewResolver,所有具体的视图解析器必须实现该接口。

常用的视图解析器实现类及简介如下

图28-03

视图解析器类型 简介
解析为bean BeanNameViewResolver 将视图解析后,映射成一个bean,视图的名字就是bean的id。
解析为映射文件 InternalResourceViewResolver 将视图解析后,映射成一个资源文件。例如将一个视图名为字符串“success.jsp”的视图解析后,映射成一个名为success的JSP文件。
JasperReportsViewResolver 将视图解析后,映射成一个报表文件。
解析为模板文件 FreeMarkerViewResolver 将视图解析后,映射成一个FreeMarker模板文件。
VelocityViewResolver 将视图解析后,映射成一个Velocity模板文件。
VelocityLayoutViewResolver

InternalResourceViewResolver是JSP最常用的视图解析器,可以通过prefix给响应字符串加上前缀,通过suffix加上后缀。例如我们之前曾在springMVC的配置文件中配置了一个视图解析器InternalResourceViewResolver,如下:

springmvc.xml

复制
  1. <beans …>
  2. <!-- 配置视图解析器:把handler处理类的返回值,加工成最终的视图路径-->
  3. <bean class="org.springframework.web.servlet.view
  4. .InternalResourceViewResolver">
  5. <property name="prefix" value="/views/"></property>
  6. <property name="suffix" value=".jsp"></property>
  7. </bean>
  8. </beans>

此外,视图解析器还可以通过解析JstlView进而实现国际化、通过解析<mvc:view-controller>进而指定请求的跳转路径、通过“redirect:”和“forward:”指定跳转方式等等。

(1)通过解析JstlView实现国际化

JstlViewInternalResourceView的子类。如果在JSP中使用了JSTL,那么InternalResourceViewResolver就会自动将默认使用的InternalResourceView视图类型转变为JstlView类型。

以下,在SpringMVC中使用JSTL的fmt标签来实现国际化:

所谓“国际化”,就是指同一个程序,对于不同地区/国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。例如,同一个用JSP开发的欢迎页面,中国地区访问时显示“欢迎您”,而美国地区访问时则显示“Welcome”。以下是实现国际化的具体步骤:

①对于不同地区/国家,创建不同的资源文件

将程序中的提示信息、错误信息等放在资源文件中,为不同地区/国家编写对应资源文件。这些资源文件使用共同的基名,通过在基名后面添加语言代码、国家及地区代码来区分不同地域的访问者。如下是一些常见的资源文件命名方式及简介:

资源文件名 简介
基名_en.properties 所有英文语言的资源
基名_en_US.properties 针对美国地区、英文语言的资源
基名_zh.properties 所有的中文语言的资源
基名_zh_CN.properties 针对中国大陆的、中文语言的资源
基名_zh_HK.properties 针对中国香港的、中文语言的资源
基名.properties 默认资源文件。如果请求相应语言的资源文件不存在,将使用此资源文件。例如,若是中国大陆地区用户,应该访问“基名_zh_CN.properties”,而如果不存在此文件,就会去访问默认的“基名.properties”。

例如,如果访问此项目的用户来自美国和中国两个国家,就需要创建美国和中国两个地区的资源文件:在项目的src目录中,新建美国地区的资源文件i18n_en_US.properties,和中国内地的资源文件i18n_ zh_CN.properties,如下:

美国地区的资源文件:i18n_en_US.properties

复制
  1. resource.welcome=WELCOME
  2. resource.exist=EXIST

中国内地的资源文件:i18n_ zh_CN.properties

复制
  1. resource.welcome=\u6B22\u8FCE\u60A8
  2. resource.exist=\u9000\u51FA

说明:

在中文使用的i18n_ zh_CN.properties中,用户输入的原文是:

resource.welcome=欢迎您

resource.exist=退出

但Eclipse会自动将“欢迎您”等汉字自动转为相应的ASCII,供属性文件使用。 如果读者使用的Eclipse版本不能自动的将汉字转为ASCII,也可以使用JDK安装目录中bin中的native2ascii.exe工具进行转换。

不同资源文件的基名必须保持一致(如i18n),并且资源文件的内容是由很多key-value对组成,key必须一致(如resource.welcome),value随语言/国家地区不同而不同(如美国是“WELCOME”,中国是“欢迎您”)。

本例使用的基名i18n是internationalization(国际化)的缩写。internationalization的首尾字母i和n中间有18个字母,所以简称i18n。

②在SpringMVC的配置文件中,加载国际化资源文件

springmvc.xml

复制
  1. <beans …>
  2. <bean id="messageSource" class="org.springframework
  3. .context.support.ResourceBundleMessageSource">
  4. <property name="basename" value="i18n" />
  5. </bean>
  6. </beans>

Spring容器在初始化时,会自动加载id“messageSource”,且类型为org.springframework.context.MessageSourceBean,并加载该Bean中通过basename属性指定基名的国际化资源文件。

③使用JSTL标签实现国际化显示

先导入JSTL依赖的2个JAR:jstl.jarstandard.jar,再在显示页success.jsp中导入JSTL用于支持国际化的库,并使用<fmt:message …>实现国际化显示,如下:

显示页success.jsp

复制
  1. <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
  2. <body>
  3. <fmt:message key="resource.welcome"></fmt:message>
  4. <br><br>
  5. <fmt:message key="resource.exist"></fmt:message>
  6. <br><br>
  7. </body>

fmt标签的key值会根据浏览器的语言环境去匹配资源文件中的key,若匹配则会显示相应资源文件中key对应的value值。例如,中国内陆地区下载的火狐浏览器默认的语言是中文,所以会在i18n_zh_CN.properties中寻找key为“resource.welcome”、“resource.exist”的value值,并显示到页面上,如下:

发送请求页index.jsp

<a href="FirstSpringDemo/testI18n">testI18n</a><br/>

请求处理类:FirstSpringDemo.java

复制
  1. @Controller
  2. @RequestMapping(value = "/FirstSpringDemo")
  3. public class FirstSpringDemo
  4. {
  5. @RequestMapping("/testI18n")
  6. public String testI18n(){
  7. return "success";
  8. }
  9. }

显示页面:success.jsp

复制
  1. <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
  2. <body>
  3. <fmt:message key="resource.welcome"></fmt:message>
  4. <br>
  5. <fmt:message key="resource.exist"></fmt:message>
  6. </body>

执行index.jsp中的超链接,运行结果:

图28-04

如果将火狐浏览器的语言切换为英文,如下:

图28-05

再次执行index.jsp中的超链接,运行结果:

图28-06

以上就实现了国际化的显示操作,JSP页面会根据浏览器的语言环境自动寻找相应的资源文件,并依据key值进行显示。

注意:就本例来说,国际化显示标签必须在success.jsp中才会起作用,而如果将放在index.jsp中则无法实现国际化。这是因为在springmvc.xml中配置的MessageSource(具体是ResourceBundleMessageSource实现类)是用来处理响应的,也就是说只有在请求处理方法返回String、View或ModelAndView对象以后执行响应时,才会通过MessageSource来执行国际化操作。而如果直接在index.jsp中执行<fmt:message ..>,因为此时还没有“处理响应”这一过程,所以就不会涉及到MessageSource,也就不会根据basename属性来指定的资源文件基名,因此本例的index.jsp中不能直接实现国际化显示。

(2)<mvc:view-controller>

我们之前使用SpringMVC的流程大致都是

请求页index.jsp—>使用@RequestMapping标识的请求处理类FirstSpringDemo.java中的方法–>结果显示页success.jsp

除此以外,我们还可以省略②,让流程简化为①—>③,即省略请求处理方法。简化的方法是在springmvc.xml中配置<mvc:view-controller…/>,如下:

springmvc.xml

复制
  1. <beans …>
  2. <mvc:view-controller path="/testViewController"
  3. view-name="success"/>
  4. </beans>

其中path用来匹配请求路径(类似于@RequestMappingvalue值),view-name用来指定响应跳转的页面(类似于请求处理方法中的return “success”)。以上配置,就表示凡是请求路径为“testViewController”的,就会被直接跳转到“success”页面(“success”会加上InternalResourceViewResolver中设置的前缀和后缀)。如下:

index.jsp(请求路径是:<mvc:view-controller…/>path指定的testViewController)

<a href="testViewController">testViewController</a><br/>

点击此超链接后,就会直接跳转到view-name指定的success页面(/view/success.jsp),即略过了@RequestMapping标识的请求处理方法。

但是,此时如果我们再点击index.jsp中之前编写的其他超链接,就都会报“HTTP Status 404”异常。解决办法就是再在springmvc.xml中加入<mvc:annotation-driven></mvc:annotation-driven>,如下:

springmvc.xml

复制
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. <mvc:view-controller path="/testViewController"
  4. view-name="success"/>
  5. <mvc:annotation-driven></mvc:annotation-driven>
  6. </beans>

一般情况,在使用<mvc:view-controller…/>的同时,也需要加入<mvc:annotation-driven…/>标签。

(3)页面跳转方式

当请求处理方法的返回值是字符串时,视图解析器InternalResourceViewResolver会给返回值加上前缀、后缀,然后默认以请求转发的方式进行页面跳转。此外,我们还可以通过给返回值加上“forward:”“redirect:”来指定跳转方式为请求转发或重定向。

①通过“forward:”指定跳转方式为请求转发

复制
  1. @RequestMapping("/testForward")
  2. public String testForward(){
  3. return "forward:/views/success.jsp";
  4. }

②通过“redirect:”指定跳转方式为重定向

复制
  1. @RequestMapping("/testRedirect")
  2. public String testRedirect(){
  3. return "redirect:/views/success.jsp";
  4. }

需要注意,加上“forward:”“redirect:”后,视图解析器将不会再给返回值加上前缀、后缀,需要我们自己写上完整的响应地址。

28.3 处理静态资源

如果我们在项目的WebContent目录下新建imgs目录,并存放一张图片logo.png,如图,

图28-07

然后启动tomcat服务来访问此图片http://localhost:8888/SpringMVCDemo/imgs/logo.png,就会看到浏览器显示“HTTP Status 404”异常。这是因为我们之前在web.xml中配置了DispatcherServlet,如下:

web.xml

复制
  1. <servlet>
  2. <servlet-name>springDispatcherServlet</servlet-name>
  3. <servlet-class>
  4. org.springframework.web.servlet.DispatcherServlet
  5. </servlet-class>
  6. <init-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:springmvc.xml</param-value>
  9. </init-param>
  10. <load-on-startup>1</load-on-startup>
  11. </servlet>
  12. <servlet-mapping>
  13. <servlet-name>springDispatcherServlet</servlet-name>
  14. <url-pattern>/</url-pattern>
  15. </servlet-mapping>

DispatcherServlet的url-pattern是“/”,表示会拦截所有请求。因此,当访问图片、js文件、视频等静态资源时,也会被DispatcherServlet所拦截并去尝试匹配相应的@RequestMapping方法,但静态资源一般不会有相应的@RequestMapping,因此会报404异常。为了解决此异常,以便能够访问静态资源,可以在springmvc.xml中加上<mvc:default-servlet-handler/><mvc:annotation-driven></mvc:annotation-driven>,如下:

springmvc.xml

复制
  1. <beans …>
  2. <mvc:default-servlet-handler/>
  3. <mvc:annotation-driven></mvc:annotation-driven>
  4. </beans>

之后,就可以成功访问到项目中的静态资源。

<mvc:default-servlet-handler/>标签的作用是:此标签会在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler,它会对所有DispatcherServlet处理的请求进行筛查,如果发现某个请求没有相应的@RequestMapping进行处理(如请求的是图片等静态资源),就会将该请求交给WEB服务器(如Tomcat)默认的Servlet处理,而默认Servlet就会直接去访问该静态资源。

说明:

Tomcat默认的Servlet是在“tomcat安装目录\conf\web.xml”中定义的,如下

复制
  1. <servlet>
  2. <servlet-name>default</servlet-name>
  3. <servlet-class>
  4. org.apache.catalina.servlets.DefaultServlet
  5. </servlet-class>
  6. </servlet>

配置了<mvc:default-servlet-handler/>之后,就可以解决访问静态资源时产生的异常。而加入<mvc:annotation-driven></mvc:annotation-driven>的目的是为了在访问静态资源的同时,也能正常的访问其他非静态资源。如果只加<mvc:default-servlet-handler/>而不加<mvc:annotation-driven></mvc:annotation-driven>,就会造成只能访问静态资源,而无法访问非静态资源。

SpringMVC--视图的更多相关文章

  1. SpringMVC视图解析器

    SpringMVC视图解析器 前言 在前一篇博客中讲了SpringMVC的Controller控制器,在这篇博客中将接着介绍一下SpringMVC视 图解析器.当我们对SpringMVC控制的资源发起 ...

  2. SpringMVC视图机制详解[附带源码分析]

    目录 前言 重要接口和类介绍 源码分析 编码自定义的ViewResolver 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门bl ...

  3. SpringMVC视图解析器(转)

    前言 在前一篇博客中讲了SpringMVC的Controller控制器,在这篇博客中将接着介绍一下SpringMVC视图解析器.当我们对SpringMVC控制的资源发起请求时,这些请求都会被Sprin ...

  4. SpringMVC视图

    SpringMVC视图机制详解[附带源码分析] 目录 前言 重要接口和类介绍 源码分析 编码自定义的ViewResolver 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一 ...

  5. SpringMVC 视图解析器

    SpringMVC 视图解析器 还记得SpringMVC 快速入门中,dispatcher-servlet.xml 配置的视图解析器么.它是SpringMVC 的核心知识点.本章节比较简单,明白视图解 ...

  6. Spring Boot实践——SpringMVC视图解析

    一.注解说明 在spring-boot+spring mvc 的项目中,有些时候我们需要自己配置一些项目的设置,就会涉及到这三个,那么,他们之间有什么关系呢? 首先,@EnableWebMvc=Web ...

  7. springmvc视图解析

    SpringMVC 视图解析的几种方式: 在视图解析的过程中,需要知道逻辑view的名字,model的名字以访问model和view. 使用jsp进行解析,InternalResourceViewRe ...

  8. SPRINGMVC 视图介绍

    SpringMVC视图解析器 前言 在前一篇博客中讲了SpringMVC的Controller控制器,在这篇博客中将接着介绍一下SpringMVC视图解析器.当我们对SpringMVC控制的资源发起请 ...

  9. SpringMVC 视图和视图解析器&表单标签

    视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它 ...

  10. springmvc视图解析流程

    无论目标方法返回String.VIew或者是ModelAndView,springmvc都会转化成ModelAndView 然后通过视图解析器(如InternalResouceViewResolver ...

随机推荐

  1. javascript中所谓的“坑”收录

    坑一: // 反例myname = "global"; // 全局变量function func() { alert(myname); // "undefined&quo ...

  2. Windows10系统下安装python2和python3双版本

    Windows10系统下安装Python3的步骤已经演示过(详见:https://www.cnblogs.com/schut/p/8399195.html),此处不再赘述Python的下载,主要介绍在 ...

  3. springboot+shiro+jwt

    1.添加依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-sp ...

  4. Go structs、slices、maps

    [Go structs.slices.maps] 1.定义时*在变量名后面,使用时*在变量名前面. 2.定义struct,type在前,struct关键字在后. 3.指针可以指定struct. 4.A ...

  5. Grapher

    [Grapher] You use Grapher to visualize and analyze implicit and explicit equations. You can graph eq ...

  6. xshell评估过期解决办法

    1.登录网景官网的下载页面: https://www.netsarang.com/download/down_form.html?code=522 2.直接在页面中有红色*号的地方输入个人信息,lic ...

  7. Liunx下如何使用kettle

    在windows下完成所有操作, 把xxx.ktr上传到liunx, Pan.sh xxx.ktr 就完成了

  8. C# 与 Java Rsa加密与解密互通

    Rsa 加密标准的制定已经过去了十多年了. 这两天在看rsa 加密的文章,基本上都是在说 .net 与 java 之间的 rsa加密是不能互通的.因为项目有用到,所以花了点时间对rsa加密做了一点点了 ...

  9. Excel应用程序如何创建数据透视表

    原文作者:andreww 原文链接: http://blogs.msdn.com/andreww/archive/2008/07/25/creating-a-pivottable-programmat ...

  10. 递归,回溯和DFS的区别

    递归是一种算法结构,回溯是一种算法思想一个递归就是在函数中调用函数本身来解决问题回溯就是通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”,意思就是对已经知道错误的结果没必 ...