SpringMVC 视图解析器(View Resolver):InternalResourceViewResolver, Thymeleaf, Freemarker 等

SpringMVC 视图解析器:你的页面,我来搞定!

各位看官,大家好!今天咱们来聊聊SpringMVC里负责“抛头露面”的家伙——视图解析器(View Resolver)。 你想想啊,你辛辛苦苦写了个Controller,处理了一堆数据,总不能让用户看到一堆JSON或者XML吧? 那得有个东西把这些数据“化妆”成美美的HTML页面,呈现给用户才行啊! 这个“化妆师”就是我们的视图解析器。

SpringMVC的视图解析器,就像一个媒婆,它负责把Controller处理后的数据(Model)和真正的视图(View)撮合在一起,生成最终的响应页面。 SpringMVC提供了多种“媒婆”,每种“媒婆”擅长的“化妆术”不一样,对应着不同的视图技术。 咱们今天就来好好认识一下这些“媒婆”,看看它们各自的绝活。

一、初识视图解析器:何方神圣?

在SpringMVC的世界里,视图解析器的作用简单来说就是:

  1. 接收视图名称(View Name): Controller处理完请求后,会返回一个字符串,这个字符串就是视图名称。
  2. 找到对应的视图(View): 根据视图名称,视图解析器会找到对应的View对象。View对象负责渲染页面,将数据填充到模板中。
  3. 返回View对象: 将找到的View对象返回给DispatcherServlet,由DispatcherServlet调用View对象的render方法,生成最终的响应。

为了让大家更直观地理解,我们来看个简单的例子:

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, SpringMVC!");
        return "hello"; // 返回视图名称 "hello"
    }
}

在这个例子中,/hello请求的处理方法返回了字符串"hello"。 那么,SpringMVC怎么知道"hello"对应哪个页面呢? 这就是视图解析器发挥作用的地方了。 它会根据配置,将"hello"解析成一个真正的View对象,比如hello.jsp或者hello.html

二、常见的视图解析器:各显神通!

SpringMVC提供了多种视图解析器,每种解析器支持不同的视图技术。 我们来认识几个常用的“媒婆”:

  1. InternalResourceViewResolver: JSP的忠实粉丝!
  2. ThymeleafViewResolver: 新一代模板引擎的代表!
  3. FreeMarkerViewResolver: 老牌模板引擎,依然坚挺!
  4. ContentNegotiatingViewResolver: 灵活多变,能根据请求头选择合适的视图!

下面我们逐一介绍它们:

1. InternalResourceViewResolver:JSP的得力助手

InternalResourceViewResolver是最常用的视图解析器之一,它主要用于解析JSP页面。 它会在视图名称前面加上一个前缀(prefix),后面加上一个后缀(suffix),组成完整的JSP页面路径。

配置方式:

在SpringMVC的配置文件(例如spring-mvc.xml)中,添加如下配置:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

配置说明:

  • prefix:指定JSP页面存放的目录,例如/WEB-INF/views/
  • suffix:指定JSP页面的后缀名,例如.jsp

工作原理:

假设Controller返回的视图名称是"hello",那么InternalResourceViewResolver会将它解析成/WEB-INF/views/hello.jsp

示例:

  • Controller:
@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, JSP!");
        return "hello"; // 返回视图名称 "hello"
    }
}
  • JSP页面(/WEB-INF/views/hello.jsp):
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello JSP</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

优点:

  • 配置简单,使用方便。
  • 与JSP集成良好。

缺点:

  • 只能解析JSP页面。
  • JSP的性能相对较低。

2. ThymeleafViewResolver:新一代模板引擎的代表

Thymeleaf是一个现代化的服务器端Java模板引擎,它以其优雅的语法、强大的功能和良好的性能而备受青睐。 ThymeleafViewResolver负责将视图名称解析成Thymeleaf模板。

配置方式:

首先,需要在项目中引入Thymeleaf的依赖:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.15.RELEASE</version> <!-- 请使用最新版本 -->
</dependency>

然后,在SpringMVC的配置文件中,添加如下配置:

<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
    <property name="prefix" value="/WEB-INF/templates/"/>
    <property name="suffix" value=".html"/>
    <property name="templateMode" value="HTML"/>
    <property name="cacheable" value="false"/> <!-- 开发环境建议关闭缓存 -->
    <property name="characterEncoding" value="UTF-8"/>
</bean>

<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
    <property name="templateResolver" ref="templateResolver"/>
    <property name="enableSpringELCompiler" value="true"/>
</bean>

<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    <property name="templateEngine" ref="templateEngine"/>
    <property name="characterEncoding" value="UTF-8"/>
    <property name="order" value="1"/> <!-- 设置优先级,数值越小优先级越高 -->
</bean>

配置说明:

  • templateResolver:配置模板解析器,指定模板存放的目录、后缀名、模板模式等。
  • templateEngine:配置模板引擎,使用模板解析器来解析模板。
  • ThymeleafViewResolver:配置Thymeleaf视图解析器,使用模板引擎来渲染视图。

工作原理:

假设Controller返回的视图名称是"hello",那么ThymeleafViewResolver会将它解析成/WEB-INF/templates/hello.html

示例:

  • Controller:
@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, Thymeleaf!");
        return "hello"; // 返回视图名称 "hello"
    }
}
  • Thymeleaf模板(/WEB-INF/templates/hello.html):
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Hello Thymeleaf</title>
</head>
<body>
    <h1 th:text="${message}"></h1>
</body>
</html>

优点:

  • 语法优雅,易于学习和使用。
  • 功能强大,支持表达式、循环、条件判断等。
  • 性能良好,比JSP更高效。
  • 与Spring集成良好。

缺点:

  • 配置相对复杂。
  • 需要学习Thymeleaf的语法。

3. FreeMarkerViewResolver:老牌模板引擎,依然坚挺

FreeMarker也是一个流行的模板引擎,它以其灵活性和可扩展性而闻名。 FreeMarkerViewResolver负责将视图名称解析成FreeMarker模板。

配置方式:

首先,需要在项目中引入FreeMarker的依赖:

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version> <!-- 请使用最新版本 -->
</dependency>

然后,在SpringMVC的配置文件中,添加如下配置:

<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <property name="templateLoaderPath" value="/WEB-INF/templates/"/>
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="suffix" value=".ftl"/>
    <property name="order" value="2"/> <!-- 设置优先级,数值越小优先级越高 -->
    <property name="contentType" value="text/html;charset=UTF-8"/>
</bean>

配置说明:

  • freemarkerConfig:配置FreeMarkerConfigurer,指定模板存放的目录、默认编码等。
  • FreeMarkerViewResolver:配置FreeMarkerViewResolver,指定模板的后缀名、优先级、内容类型等。

工作原理:

假设Controller返回的视图名称是"hello",那么FreeMarkerViewResolver会将它解析成/WEB-INF/templates/hello.ftl

示例:

  • Controller:
@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, FreeMarker!");
        return "hello"; // 返回视图名称 "hello"
    }
}
  • FreeMarker模板(/WEB-INF/templates/hello.ftl):
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello FreeMarker</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

优点:

  • 灵活性高,可以自定义模板标签。
  • 可扩展性强,可以集成第三方库。
  • 适用于大型项目。

缺点:

  • 语法相对复杂。
  • 需要学习FreeMarker的语法。

4. ContentNegotiatingViewResolver:灵活多变,能根据请求头选择合适的视图!

ContentNegotiatingViewResolver是一个特殊的视图解析器,它不直接解析视图,而是根据客户端的请求头(Accept Header)来选择合适的视图解析器来处理请求。 它可以根据请求头返回HTML、JSON、XML等不同格式的数据。

配置方式:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
            <entry key="html" value="text/html"/>
        </map>
    </property>
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/views/"/>
                <property name="suffix" value=".jsp"/>
            </bean>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
        </list>
    </property>
</bean>

配置说明:

  • mediaTypes:配置媒体类型,将文件扩展名与MIME类型关联起来。
  • viewResolvers:配置视图解析器列表,指定ContentNegotiatingViewResolver使用的视图解析器。
  • defaultViews:配置默认的视图,当请求头中没有指定Accept Header时,使用默认的视图。

工作原理:

  1. 客户端发送请求,并在请求头中指定Accept Header,例如Accept: application/json
  2. ContentNegotiatingViewResolver根据Accept Header选择合适的视图解析器。
  3. 如果Accept Header中包含application/json,则选择MappingJackson2JsonView来处理请求,将数据转换成JSON格式。
  4. 如果Accept Header中包含text/html,则选择InternalResourceViewResolver来处理请求,将数据渲染成HTML页面。

示例:

  • Controller:
@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public User hello(Model model) {
        User user = new User();
        user.setName("张三");
        user.setAge(20);
        return user; // 返回User对象
    }
}
  • User类:
public class User {
    private String name;
    private int age;

    // 省略getter和setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

如果客户端发送请求时,在请求头中指定Accept: application/json,那么服务器将返回JSON格式的数据:

{
  "name": "张三",
  "age": 20
}

如果客户端发送请求时,没有指定Accept Header,或者指定了Accept: text/html,那么服务器将返回HTML页面(如果配置了InternalResourceViewResolver)。

优点:

  • 灵活多变,可以根据请求头返回不同格式的数据。
  • 方便构建RESTful API。

缺点:

  • 配置相对复杂。
  • 需要了解HTTP协议的Accept Header。

三、视图解析器的优先级:谁说了算?

当配置了多个视图解析器时,SpringMVC会按照优先级顺序来选择合适的视图解析器。 优先级由order属性来指定,数值越小优先级越高。

例如,如果同时配置了InternalResourceViewResolverThymeleafViewResolver,并且InternalResourceViewResolverorder属性设置为1,ThymeleafViewResolverorder属性设置为2,那么SpringMVC会优先使用InternalResourceViewResolver来解析视图。

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="1"/> <!-- 优先级最高 -->
</bean>

<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    <property name="templateEngine" ref="templateEngine"/>
    <property name="characterEncoding" value="UTF-8"/>
    <property name="order" value="2"/>
</bean>

四、总结:选择适合你的“媒婆”!

SpringMVC的视图解析器是负责将Controller处理后的数据渲染成最终页面的关键组件。 不同的视图解析器支持不同的视图技术,各有优缺点。 在选择视图解析器时,需要根据项目的实际情况进行选择。

  • 如果你喜欢使用JSP,那么InternalResourceViewResolver是一个不错的选择。
  • 如果你追求优雅的语法和强大的功能,那么ThymeleafViewResolver是一个更好的选择。
  • 如果你需要构建RESTful API,那么ContentNegotiatingViewResolver是必不可少的。

希望这篇文章能帮助你更好地理解SpringMVC的视图解析器,让你在开发Web应用时更加得心应手! 记住,选择合适的“媒婆”,才能让你心仪的数据找到最美的“归宿”!

最后,祝大家编程愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注