一、什么是Spring视图解析器?
Spring MVC(Model View Controller)是 Spring 中一个重要的组成部分,而 Spring 视图和视图解析器则是 Spring MVC 中的组成部分。在介绍 Spring 视图和视图解析器前,我们先了解下在 Spring MVC 框架中,一个 Web 请求所需经历的六个阶段:
请求会首先被 Spring MVC 的前端请求分发器(Dispatcher)拦截。该拦截器是一个 Servlet, 需要在 web.xml 中配置,所有符合所配置的 URL 样式的访问请求,将都会被该拦截器拦截。Spring 提供了默认的分发器 org.springframework.web.servlet.DispatcherServlet,您可以根据需要,决定是否需要定制自己的分发器。
在接收到访问请求后,分发器会根据开发人员在 Spring 配置文件或代码中的注解(Annotation),来查找合适的控制器。
分发器在查找到合适的控制器后,将请求转交给该控制器处理。
通常,控制器会调用相应服务类来处理业务逻辑,在将请求处理后,控制器需返回处理后的结果数据模型(Model)以及下一个需要显示的视图名。
在控制器处理结束并返回模型和视图名之后,Spring 会依次调用 Spring 容器中所注册的视图解析器,来查找符合条件的视图。
在获得 Spring 视图后,Spring 会根据该视图的配置信息,显示该视图。
二、常用视图和视图解析器
XmlViewResolver
接口 ViewResolver 的实现,从 XML 配置文件中查找视图实现(默认 XML 配置文件为 /WEB-INF/views.xml)
ResourceBundleViewResolver
接口 ViewResolver 的实现,用于从 properties 文件中查找视图
UrlBasedViewResolver
接口 ViewResolver 的实现,用于根据请求的 URL 路径返回相应的视图,该视图需为抽象类 AbstractUrlBasedView 的实现,它还有些子类,如 InternalResourceView 和 JstlView 等 .
InternalResourceViewResolver
UrlBasedViewResolver 的子类,通常用于查找 JSP(类 InternalResourceView)和 JSTL(类 JstlView,InternalResourceView 的子类)等视图
VelocityViewResolver /FreeMarkerViewResolver
UrlBasedViewResolver 的子类分别用于支持 Velocity(类 VelocityView)和 FreeMark 视图(类 FreeMarkerView)
ContentNegotiatingViewResolver
接口 ViewResolver 的实现,用于根据请求文件的后缀名或请求的 header 中的 accept 字段查找视图
对于控制器的目标方法,无论其返回值是String、View、ModelMap或是ModelAndView,SpringMVC都会在内部将它们封装为一个ModelAndView对象进行返回。
Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是JSP也可是Excell、 JFreeChart等各种表现形式的视图。
三、SpringMVC的视图解析流程
SpringMVC的视图解析流程为:
1、调用目标方法,SpringMVC将目标方法返回的String、View、ModelMap或是ModelAndView都转换为一个ModelAndView对象;
2、然后通过视图解析器(ViewResolver)对ModelAndView对象中的View对象进行解析,将该逻辑视图View对象解析为一个物理视图View对象;
3、最后调用物理视图View对象的render()方法进行视图渲染,得到响应结果。
视图(View)
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
为了实现视图模型和具体实现技术的解耦,Spring在org.springframework.web.servlet包中定义了一个高度抽象的View接口。
视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题。所谓视图是无状态的,是指对于每一个请求,都会创建一个View对象。
JSP是最常见的视图技术。
视图解析器(ViewResolver)
视图解析器的作用是将逻辑视图转为物理视图,所有的视图解析器都必须实现ViewResolver接口。
SpringMVC为逻辑视图名的解析提供了不同的策略,可以在Spring WEB上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。程序员可以选择一种视图解析器或混用多种视图解析器。可以通过order属性指定解析器的优先顺序,order越小优先级越高,SpringMVC会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则抛出ServletException异常。
常用的视图解析器实现类:
以下是通过InternalResourceViewResolver作为视图解析器解析,将逻辑视图解析为JSP视图的实例:
若项目中使用了JSTL,则SpringMVC会自动把视图由InternalResourceView转为JstlView。
示例:
我用断点测试演示一下:
这是我简单写的一个登录页面
在我的spring-web.xml文件中配置视图:
1、在登录的页面随便输用户名和密码,这个没有加校验的
2、点击提交之后,它会先到我写的拦截器中,我这里判断前端传来的参数略简单。
3、再下一步就会跳到这个我写好的控制器中
我这里直接给的视图的名称
InternalResourceViewResolver会给它加上定义好的前缀和后缀,我定义的前缀是"/" ,后缀是 .jsp 组成“/welcome.jsp”的形式,然后把它当做一个InternalResourceView的url新建一个InternalResourceView对象返回。
返回页面查看:
空控制台获取的数据:
4、如果继续往下执行就会到你的业务逻辑层中去,通过业务逻辑层到你的数据访问层中,我这里没往后面测试了,控制层结束之后直接返回了一个welcome.jsp 页面
这里再说一下:我这里我的Spring-web.xml文件中,配置视图直接用的前缀是”/", 一般我们的jsp页面是放在WEB-INF下面的,可以这样理解:
InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。比如在InternalResourceViewResolver中定义了prefix=/WEB-INF/,suffix=.jsp,然后请求的Controller处理器方法返回的视图名称为welcome,那么这个时候InternalResourceViewResolver就会把welcome解析为一个InternalResourceView对象,先把返回的模型属性都存放到对应的HttpServletRequest属性中,然后利用RequestDispatcher在服务器端把请求forword到/WEB-INF/welcome.jsp。
这就是InternalResourceViewResolver一个非常重要的特性,我们都知道存放在/WEB-INF/下面的内容是不能直接通过request请求的方式请求到的,为了安全性考虑,我们通常会把jsp文件放在WEB-INF目录下,而InternalResourceView在服务器端跳转的方式可以很好的解决这个问题。
四、关于重定向
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理,但如果返回的字符串中带forward:或redirect:前缀时,SpringMVC会对它们进行特殊处理:将forward: 和redirect: 当成指示符,其后的字符串作为URL 来处理。示例如下:
index.jsp:
controller:
即可重定向到index.jsp。也可在redirect:/后添加控制器方法的映射路径,重定向到该目标方法。