SpringMVC 视图解析器:你的页面,我来搞定!
各位看官,大家好!今天咱们来聊聊SpringMVC里负责“抛头露面”的家伙——视图解析器(View Resolver)。 你想想啊,你辛辛苦苦写了个Controller,处理了一堆数据,总不能让用户看到一堆JSON或者XML吧? 那得有个东西把这些数据“化妆”成美美的HTML页面,呈现给用户才行啊! 这个“化妆师”就是我们的视图解析器。
SpringMVC的视图解析器,就像一个媒婆,它负责把Controller处理后的数据(Model)和真正的视图(View)撮合在一起,生成最终的响应页面。 SpringMVC提供了多种“媒婆”,每种“媒婆”擅长的“化妆术”不一样,对应着不同的视图技术。 咱们今天就来好好认识一下这些“媒婆”,看看它们各自的绝活。
一、初识视图解析器:何方神圣?
在SpringMVC的世界里,视图解析器的作用简单来说就是:
- 接收视图名称(View Name): Controller处理完请求后,会返回一个字符串,这个字符串就是视图名称。
- 找到对应的视图(View): 根据视图名称,视图解析器会找到对应的View对象。View对象负责渲染页面,将数据填充到模板中。
- 返回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提供了多种视图解析器,每种解析器支持不同的视图技术。 我们来认识几个常用的“媒婆”:
- InternalResourceViewResolver: JSP的忠实粉丝!
- ThymeleafViewResolver: 新一代模板引擎的代表!
- FreeMarkerViewResolver: 老牌模板引擎,依然坚挺!
- 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时,使用默认的视图。
工作原理:
- 客户端发送请求,并在请求头中指定Accept Header,例如
Accept: application/json
。 ContentNegotiatingViewResolver
根据Accept Header选择合适的视图解析器。- 如果Accept Header中包含
application/json
,则选择MappingJackson2JsonView
来处理请求,将数据转换成JSON格式。 - 如果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
属性来指定,数值越小优先级越高。
例如,如果同时配置了InternalResourceViewResolver
和ThymeleafViewResolver
,并且InternalResourceViewResolver
的order
属性设置为1,ThymeleafViewResolver
的order
属性设置为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应用时更加得心应手! 记住,选择合适的“媒婆”,才能让你心仪的数据找到最美的“归宿”!
最后,祝大家编程愉快!