Spring MVC使用篇(四)—— 视图解析器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_36378917/article/details/83622846

1、视图解析器简介

  在Spring MVC的流程中最终返回给用户的视图为具体的View对象,并且View对象中包含了model中的反馈数据。而视图解析器ViewResolver的作用就是,把一个逻辑上的视图名称解析为一个真正的视图,即将逻辑视图的名称解析为具体的View对象,让View对象去处理视图,并将带有返回数据的视图反馈给客户端。

2、演示案例环境搭建

  本文仍以之前的水果商城显示全部水果信息为例,具体环境搭建分为以下几步:

  • 第一步,在web.xml中配置前端控制器(DispatcherServlet),具体配置信息如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

    <!--post中文乱码过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>

    <!--该配置表示,名为CharacterEncodingFilter的过滤器对所有请求进行过滤,然后该过滤器会
    以encoding指定的编码格式对请求数据进行统一编码-->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  • 第二步,在核心配置文件springmvc.xml中利用基于注解的方式,配置处理器映射器和适配器,并配置自动扫描,具体配置信息如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--基于注解的方式配置处理器映射器和适配器方法二-->
    <!--注解映射器-->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />-->
    <!--注解适配器-->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />-->

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <!-- 添加接下来的各种视图解析器配置 -->
</beans>
  • 第三步,基于注解的控制器Handler代码如下:
package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用@Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {

    private FruitsService fruitsService = new FruitsService();

    //@RequestMapping实现对方法和url进行映射,一个方法对应一个url
    //一般建议将url和方法写成一样的
    @RequestMapping("/queryAllFruits.action")
    public String queryAllFruits(Model model){
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        //将结果放到model中传到显示页面中
        model.addAttribute("fruitsList",fruitsList);
        return "/fruits/fruitsList";
    }
}

class FruitsService{
    public List<Fruits> queryFruitsList(){
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}
  • 第四步,jsp页面的编写,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  <title>水果列表</title>  
</head>  
<body>
  <h3>水果列表</h3>
  <table width="300px;" border=1>  
    <tr>
      <td>编号</td>
      <td>名称</td>  
      <td>价格</td>    
      <td>产地</td> 
   </tr>  
   <c:if test="${fruitsList==null}">
      <b>水果商品信息为空!</b>
   </c:if>
   <c:forEach items="${fruitsList}" var="fruit">
     <tr>
       <td>${fruit.id }</td>
       <td>${fruit.name }</td>  
       <td>${fruit.price }</td>    
       <td>${fruit.producing_area }</td>  
     </tr>  
    </c:forEach>  
   </table>   
</body>
</html> 

3、AbstractCa chingViewResolver

  该类作为一个抽象类,实现了该抽象类的视图解析器会将其曾经解析过的视图进行缓存,当再次解析视图的时候,它会首先在缓存中寻找该视图,如果找到,就返回相应的视图对象,如果没有在缓存中找到,就创建一个新的视图对象,在返回的同时,将其放置到存放缓存数据的map对象中。实现该抽象类的视图解析器类,视图解析的能力会大大提高。

4、UrlBasedViewResolver

  该类是对ViewResolver的一种简单实现,它继承了抽象类AbstractCachingViewResolver(也就是说它具有对已解析视图进行缓存的功能)。

   UrlBasedViewResolver是一种通过拼接资源文件的URI路径来展示视图的一种解析器。

  • 它通过prefix属性指定视图资源所在路径的前缀信息;
  • 通过suffix属性指定视图资源所在路径的后缀信息(一般是视图文件的格式);
  • 当ModelAndView对象返回具体的View名称时,它会将前缀prefix与后缀suffix与具体视图名称拼接,得到一个视图资源文件的具体加载路径,从而加载真正的视图文件并反馈给用户。

   例如前缀属性prefix配置的值为“、WEB-INF/jsp”,后缀属性suffix配置的值为“.jsp”,ModelAndView中View视图的名称为“/user/login”,那么UrlBasedViewResolver最终解析出来的视图资源文件的加载路径就为“/WEB-INF/jsp/user/login/jsp”。需要注意的是,默认的prefix与suffix都为空值。

   UrlBasedViewResolver支持返回的视图名称中含有“redirect:”及“forward:”前缀,即支持视图的“重定向”和“内部跳转”设置。例如,当视图名称为“redirect:login.action”时,UrlBasedViewResolver会把返回的视图名称前缀“redirect:”去掉,取后面的login.action组成一个RedirectView,在RedirectView中把请求返回的model模型属性组合成查询参数的形式,组合到redirect的URL后面,然后调用HttpServletRequest对象的sendRedirect方法进行重定向。而如果名称中包含“forward:”,视图名称会被封装成一个InternalResourceView对象,然后在服务器端利用RequestDispatcher的forward方式跳转到指定地址。

  使用UrlBasedViewResolver除了要配置前缀属性prefix和后缀属性suffix之外,还要配置一个“viewClass”,表示解析成哪种视图。若展示JSP页面,出于安全性考虑,jsp文件通常放在WEB-INF目录下(该目录下内容是不能直接通过request请求的方式请求到的),而InternalResourceView在服务器端以跳转的方式可以很好的解决该问题。

注意:要使用jstl标签展现数据,就要使用JstlView。

  在springmvc.xml中配置UrlBasedViewResolver视图解析器显示水果商城全部水果商品信息,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置UrlBasedViewResolver视图解析器-->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="prefix" value="/WEB-INF/jsp" />
        <property name="suffix" value=".jsp" />
        <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView" />
    </bean>

</beans>

  将项目部署到Tomcat上,运行后结果如下,说明UrlBasedViewResolver视图解析器配置正确,正常运行:
在这里插入图片描述

5、InternalResourceViewResolver

  InternalResourceViewResolver名为“内部资源视图解析器”,是在日常开发中最常用的视图解析器类型。它是UrlBasedViewResolver的子类,拥有UrlBasedViewResolver的一切特性。

  InternalResourceViewResolver自身的特点是:它会把返回的视图名称自动解析为InternalResourceView类型的对象,而InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求重定向到目标URL。也就是说,InternalResourceViewResolver视图解析的时候,无须在单独执行viewClass属性了。

  在springmvc.xml中配置InternalResourceViewResolver视图解析器显示水果商城全部水果商品信息,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp"/>
        <property name="suffix" value=".jsp"/>
    </bean>  
</beans>

  上面配置实现了,当一个被请求的Controller处理器方法返回一个名为“/fruits/fruitsList”的视图时,InternalResourceViewResolver会将“/fruits/fruitsList”解析成一个nternalResourceView的对象,然后将返回的model模型属性信息存放到对应的HttpServletRequest属性中,最后利用RequestDispatcher在服务器端把请求forward到“/WEB-INF/jsp/fruits/fruitsList.jsp”上。

  将项目部署到Tomcat上,运行后结果如下,说明InternalResourceViewResolver视图解析器配置正确,正常运行:
在这里插入图片描述

6、XmlViewResolver

  该视图解析器也继承了AbstractCachingViewResolver抽象类(具有缓存视图页面的能力)。

  使用XmlViewResolver需要添加一个xml配置文件,用于定义视图的bean对象。当获得Controller方法返回的视图名称后,XmlViewResolver会到指定的配置文件中寻找对应name名称的视图bean配置,解析并处理该视图。

  如果不指定XmlViewResolver的配置文件,那么默认配置文件为/WEB-INF/views.xml,如果不想使用默认值,可以在springmvc.xml的配置文件中配置XmlViewResolver时,指定其location属性,在value中指定配置文件所在的位置。

  在springmvc.xml中配置XmlViewResolver视图解析器显示水果商城全部水果商品信息,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.XmlViewResolver">
        <property name="location" value="/WEB-INF/config/views.xml" />
        <property name="order" value="1" />
    </bean>
</beans>

  在上面的配置中,设置了一个属性“order”,它的作用是,在配置有多重类型的视图解析器的情况下(即使有ViewResolver链),order会指定该视图解析器的处理视图的优先级,order的值越小优先级越高。特别要说明的是,order属性在 所有实现Ordered接口的视图解析器中都适用。

  视图XML配置文件views.xml的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- Controller中方法的返回值返回该视图的id -->
    <bean id="fruitsList" class="org.springframework.web.servlet.view.InternalResourceView">
        <property name="url" value="/WEB-INF/jsp/fruits/fruitsList.jsp" />
    </bean>

</beans>

  views.xml配置文件遵循的DTD规则和Spring的bean工厂配置文件相同,所以bean中的标签规范与springmvc.xml中的bean相关的规范相同。在上面的配置中添加了一个id为“fruitsList”的InternalResourceView视图类型的bean配置,其中配置了url的映射参数。当Controller返回一个名为“fruitsList”的视图时,XmlViewResolver会在views.xml配置文件中寻找相关的bean配置中包含的id的视图配置,并遵循bean配置的View视图类型进行视图的解析,将最终的视图页面显示给用户。因此,对于之前的FruitsController中的queryAllFruits方法的返回值稍作修改,具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用@Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {

    private FruitsService fruitsService = new FruitsService();

    //@RequestMapping实现对方法和url进行映射,一个方法对应一个url
    //一般建议将url和方法写成一样的
    @RequestMapping("/queryAllFruits.action")
    public String queryAllFruits(Model model){
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        //将结果放到model中传到显示页面中
        model.addAttribute("fruitsList",fruitsList);
        
        return "fruitsList";	/**这里与之前的不同**/
    }   
}

class FruitsService{
    public List<Fruits> queryFruitsList(){
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  将项目部署到Tomcat上,运行后结果如下,说明XmlViewResolver视图解析器配置正确,正常运行:
在这里插入图片描述

7、BeanNameViewResolver

  该视图解析器与XmlViewResolver解析器的配置模式类似,也是让返回的逻辑视图名称去匹配配置好的bean配置。与XmlViewResolver解析器不同的是,XmlViewResolver是将bean配置文件配置在外部的XML文件中,而BeanNameViewResolver将视图的bean配置信息仪器配置在Spring MVC的核心配置文件springmvc.xml中。

  在springmvc.xml中配置BeanNameViewResolver视图解析器显示水果商城全部水果商品信息,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->  
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="1" />
    </bean>
    <!-- Controller中方法的返回值返回该视图的id -->
    <bean id="fruitsList" class="org.springframework.web.servlet.view.InternalResourceView">
        <property name="url" value="/WEB-INF/jsp/fruits/fruitsList.jsp" />
    </bean>
</beans>

  与之前的XmlViewResolver视图解析器同理,需要对之前的FruitsController中的queryAllFruits方法的返回值稍作修改,具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用@Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {

    private FruitsService fruitsService = new FruitsService();

    //@RequestMapping实现对方法和url进行映射,一个方法对应一个url
    //一般建议将url和方法写成一样的
    @RequestMapping("/queryAllFruits.action")
    public String queryAllFruits(Model model){
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        //将结果放到model中传到显示页面中
        model.addAttribute("fruitsList",fruitsList);
        return "fruitsList";
    }    
}

class FruitsService{
    public List<Fruits> queryFruitsList(){
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  将项目部署到Tomcat上,运行后结果如下,说明BeannameViewResolver视图解析器配置正确,正常运行:
在这里插入图片描述
注意:BeannameViewResolver不会对视图进行缓存

8、ResourceBundleViewResolver

  该视图解析器与XmlViewResolver解析器一样,继承了AbstractCachingViewResolver抽象类,并且也需要有一个配置文件来定义逻辑视图名称和真正的View对象的对应关系。与XmlViewResolver不同的是,ResourceBundleViewResolver的配置文件并不是XML文件,而是一个properties属性文件,且必须放置在classpath根目录下

  默认情况下,配置文件为classpath根目录下的view.properties,如果不想使用默认的文件,则可以在Spring MVC配置文件中定义ResourceBundleViewResolver的bean信息时,指定baseName为自定义的properties文件名称。或者为baseName属性指定一个模糊文件头信息,凡是包含该文件头的都可以被加载(如指定baseName的名称为view,那么view.properties、viewSource.properties等一切以view开头的properties都会被加载)。

  首先在classpath根目录创建一个名为“viewResource”的属性文件,具体配置如下:

aaa.(class)=org.springframework.web.servlet.view.InternalResourceView
aaa.url=/WEB-INF/jsp/fruits/fruitsList.jsp
bbb.(class)=org.springframework.web.servlet.view.InternalResourceView
bbb.url=/WEB-INF/jsp/fruits/fruitsList.jsp

  然后在Spring MVC的核心配置文件springmvc.xml中添加ResourceBundleViewResolver的bean配置,具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->    
    <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        <property name="basename">
            <value>viewResource</value>
        </property>
        <property name="order" value="1" />
    </bean>

</beans>

  接着在FruitsController中添加对ResourceBundleViewResolver视图解析器的测试方法,具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用@Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {

    private FruitsService fruitsService = new FruitsService();

   //测试视图解析器ResourceBundleViewResolver
    @RequestMapping("/testResourceBundleViewResolver1.action")
    public String testResourceBundleViewResolver1(Model model){
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        //将结果放到model中传到显示页面中
        model.addAttribute("fruitsList",fruitsList);
        return "aaa";
    }
    
    @RequestMapping("/testResourceBundleViewResolver2.action")
    public String testResourceBundleViewResolver2(Model model){
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        //将结果放到model中传到显示页面中
        model.addAttribute("fruitsList",fruitsList);
        return "bbb";
    }
}

class FruitsService{
    public List<Fruits> queryFruitsList(){
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  最后将项目部署到Tomcat上,在浏览器上分别访问链接 “http://localhost:8080/query/testResourceBundleViewResolver1.action”和“http://localhost:8080/query/testResourceBundleViewResolver2.action”, 得到如下结果,说明ResourceBundleViewResolver视图解析器配置正确,正常运行:
在这里插入图片描述
在这里插入图片描述
:ResourceBundleViewResolver也支持解析多种不同类型的View。

9、FreeMarkerViewResolver与VelocityViewResolver

  一般来说,FreeMarkerResolver会将Controller返回的逻辑视图信息解析为FreeMarkerView类型,而VelocityViewResolver会将逻辑视图信息解析为VelocityView。

  FreeMarkerResolver与VelocityViewResolver有一个共同点,就是他们都是UrlBasedViewResolver的子类,可以通过prefix属性指定视图资源所在路径的前缀信息,通过suffix属性指定视图资源所在路径的后缀信息。两者都不需要再指定viewClass属性,因为在ViewResolver中已经指定了viewClass的类型。

  以FreeMarkerResolver为例,FreeMarkerResolver最终会解析逻辑视图配置,返回一种Freemarker模板,该模板负责将数据模型中的数据合并到模板中,从而生成标准输出(可以生成各种文本,包括HTML、XML、RTF、Java源代码等)。

  首先,在使用FreeMarkerResolver视图解析器时,必须添加支持FreeMarker的freemarker.2.3.28.jar文件。
在这里插入图片描述
  接着在Spring MVC的核心配置文件springmvc.xml中添加FreeMarkerResolver的bean配置以及前后缀和优先级。除此之外,还需要指定FreeMarkerView类型最终生成的实体视图(模板文件)的路径以及其他配置,所以需要给FreeMarkerResolver设置一个FreeMarkerConfig的bean对象来定义FreeMarker的配置信息。具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="prefix" value="fm_" />
        <property name="suffix" value=".ftl" />
        <property name="contentType" value="text/html;charset=UTF-8"/>
        <property name="order" value="1" />
    </bean>
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/freemarker/template" />
        <!-- 设置页面中文乱码问题 -->
        <property name="freemarkerSettings">
            <props>
                <prop key="defaultEncoding">UTF-8</prop>
            </props>
        </property>
    </bean>
</beans>

  定义了templateLoaderPath属性后,Spring可以通过该属性找到FreeMarker的模板文件的具体路径。当有模板位于不同的路径时,可以配置templateLoaderPath属性,在其中指定多个资源路径。

  然后在FruitsController中定义一个方法testFreeMarkerViewResolver,让其返回时定义一些返回参数和视图信息,具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用@Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {
    private FruitsService fruitsService = new FruitsService();     
    @RequestMapping("/testFreeMarkerViewResolver.action")
    public String testFreeMarkerViewResolver(Model model){
        model.addAttribute("username","张三");
        return "freemarker";
    }
}

class FruitsService{
    public List<Fruits> queryFruitsList(){
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  当FreeMarkerViewResolver解析逻辑视图信息时,会生成一个URL为“前缀+视图名+后缀”(这里即“fm_freemaeker.ftl”)的FreeMarkerView对象,然后通过FreeMarkerConfigurer的配置找到templateLoaderPath对应的文本文件的路径,在该路径下找到该文本文件,从而FreeMarkerView就可以利用该模板文件进行视图的渲染,并将model数据封装到即将要显示页面上,最终展示给用户。这里需要特别注意的就是,当model对象中带有中文时,一定要注意解决中文乱码的配置

  最后,还要在“/WEB-INF/freemarker/template”文件夹下创建一个名为“fm_freemarker.ftl”的文本文件,具体内容如下:

<html>
    <head>
        <title>FreeMarkerTest</title>
    </head>
    <body>
        <h1>My Page</h1>
        <b>Welcome!</b><i> ${username} </i>
    </body>
</html>

  由上面的代码可以看出,在ftl格式的文件中也可以使用ongl方式获取在model中封装的数据。最终返回给用户的视图效果如下图所示:
在这里插入图片描述
小贴士:使用FreeMarkerViewResolver可以生成FreeMarker模板,次模板十分强大,你可以根据模板规则,合并数据模型中的数据生成各种类型的文本。如HTML、XML、RTF等。

10、ViewResolver链

  原则上说,是可以在Spring MVC的核心配置文件springmvc.xml中配置多个视图解析器(ViewResolver)的,将这些ViewResolver配置在一起使用,就形成了一个ViewResolver链。这些视图解析器之间并不会冲突,因为所有的ViewResolver都实现了Ordered接口,只需要通过order属性为他们指定优先级即可(即按照哪种顺序去调用视图解析器)。order属性是Integer类型,order越小,对应的ViewResolver将有越高的解析视图的优先级。

  当Controller返回一个逻辑视图名称时,ViewResolver链将根据其中ViewResolver的优先级来对逻辑视图进行处理,如果高优先级的ViewResolver没有解析出视图,说明该视图类型并不为此ViewResolver所兼容,此时就会让下一个优先级的ViewResolver去解析该视图。如果定义的所有ViewResolver都不能解析该视图,就抛出异常。

  注意:建议在ViewResolver中,将InternalResourceViewResolver解析器优先级设置为最低,因为该解析器能解析所有类型的视图,并返回一个不为空的View对象。

猜你喜欢

转载自blog.csdn.net/weixin_36378917/article/details/83622846
今日推荐