Spring MVC 视图解析器 (ViewResolver) 如何配置? Spring Boot 是如何自动配置常见视图解析器的?

我们来详细分析一下视图解析器 (ViewResolver) 的配置以及 Spring Boot 是如何自动配置它们的。

视图解析器 (ViewResolver) 是什么?

在 Spring MVC 中,当控制器 (Controller) 方法处理完请求并返回一个逻辑视图名 (String) 时,DispatcherServlet 会使用注册的 ViewResolver 来将这个逻辑视图名解析为一个实际的 View 对象。这个 View 对象负责渲染最终的响应(例如,生成 HTML)。

1. 如何手动配置视图解析器?

可以手动配置 ViewResolver,在 Spring 的配置类(使用 @Configuration 注解)中完成。

核心接口是 org.springframework.web.servlet.ViewResolver

以下是一些常见的视图解析器及其手动配置示例:

a. InternalResourceViewResolver (通常用于 JSP)

这是最常用的 JSP 视图解析器。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView; // 如果使用 JSTL@Configuration
@EnableWebMvc // 如果不是 Spring Boot,通常需要这个
public class MvcConfig implements WebMvcConfigurer { // 实现 WebMvcConfigurer 以便自定义MVC配置@Beanpublic ViewResolver jspViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setViewClass(JstlView.class); // 如果使用JSTL标签库resolver.setPrefix("/WEB-INF/jsp/");   // 视图文件的前缀路径resolver.setSuffix(".jsp");            // 视图文件的后缀resolver.setOrder(1); // 如果有多个解析器,设置顺序return resolver;}// 可以配置其他 ViewResolver// @Bean// public ViewResolver thymeleafViewResolver() { ... }
}
  • prefix: 视图文件在 Web 应用中的路径前缀。
  • suffix: 视图文件的扩展名。
  • viewClass: 指定要使用的视图类,例如 JstlView (用于JSP + JSTL)。
  • order: 如果有多个视图解析器,order 属性决定了它们的查找顺序,值越小优先级越高。

b. ThymeleafViewResolver (用于 Thymeleaf 模板引擎)

需要先配置 SpringTemplateEngineTemplateResolver

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring6.SpringTemplateEngine; // Spring 6, Spring 5 用 spring5
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;@Configuration
@EnableWebMvc
public class ThymeleafConfig implements WebMvcConfigurer {private ApplicationContext applicationContext;public ThymeleafConfig(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Beanpublic SpringResourceTemplateResolver templateResolver() {SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();templateResolver.setApplicationContext(this.applicationContext);templateResolver.setPrefix("classpath:/templates/"); // Thymeleaf 模板通常放在 classpath 下templateResolver.setSuffix(".html");templateResolver.setTemplateMode(TemplateMode.HTML);templateResolver.setCharacterEncoding("UTF-8");templateResolver.setCacheable(false); // 开发时关闭缓存return templateResolver;}@Beanpublic SpringTemplateEngine templateEngine() {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver());templateEngine.setEnableSpringELCompiler(true); // 推荐开启SpringEL编译器// 可以添加额外的 Dialect,例如 SpringSecurityDialectreturn templateEngine;}@Beanpublic ViewResolver thymeleafViewResolver() {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(templateEngine());resolver.setCharacterEncoding("UTF-8");resolver.setOrder(0); // 优先级高return resolver;}
}

c. FreeMarkerViewResolver (用于 FreeMarker 模板引擎)

需要配置 FreeMarkerConfigurer

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;@Configuration
@EnableWebMvc
public class FreeMarkerConfig implements WebMvcConfigurer {@Beanpublic FreeMarkerConfigurer freeMarkerConfigurer() {FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();configurer.setTemplateLoaderPath("classpath:/templates/freemarker/"); // FreeMarker模板路径configurer.setDefaultEncoding("UTF-8");return configurer;}@Beanpublic ViewResolver freeMarkerViewResolver() {FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();resolver.setCache(true); // 生产环境建议开启缓存resolver.setPrefix(""); // 前缀通常在 FreeMarkerConfigurer 中设置resolver.setSuffix(".ftl");resolver.setContentType("text/html;charset=UTF-8");resolver.setOrder(0);return resolver;}
}

d. ContentNegotiatingViewResolver

这是一个特殊的视图解析器,它本身不解析视图,而是委托给一个或多个其他的视图解析器。它会根据请求的媒体类型 (Media Type,例如通过 Accept HTTP头或URL后缀) 来选择合适的 ViewResolver (进而选择合适的 View) 来渲染响应。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
// ... 其他 ViewResolver importsimport java.util.ArrayList;
import java.util.List;@Configuration
@EnableWebMvc
public class ContentNegotiationMvcConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorParameter(true) // 是否通过请求参数(默认为format)来确定媒体类型.parameterName("mediaType") // 请求参数名.ignoreAcceptHeader(false) // 是否忽略Accept请求头.defaultContentType(MediaType.TEXT_HTML) // 默认媒体类型.mediaType("html", MediaType.TEXT_HTML).mediaType("json", MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML);}@Beanpublic ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();resolver.setContentNegotiationManager(manager);List<ViewResolver> resolvers = new ArrayList<>();// 添加你想要委托的 ViewResolverresolvers.add(jsonViewResolver()); // 假设有一个处理 JSON 的 ViewResolverresolvers.add(jspViewResolver());   // 上面定义的 JSP ViewResolver// ... 其他resolver.setViewResolvers(resolvers);resolver.setOrder(0); // CNVR 通常优先级最高return resolver;}// 示例:一个简单的 JSON ViewResolver (通常会使用 MappingJackson2JsonView)// @Bean// public ViewResolver jsonViewResolver() { ... }@Beanpublic ViewResolver jspViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/jsp/");resolver.setSuffix(".jsp");return resolver;}
}

2. Spring Boot 是如何自动配置常见视图解析器的?

Spring Boot 的核心思想是“约定优于配置” (Convention over Configuration)。它通过自动配置 (Auto-configuration) 机制,根据我们项目中添加的依赖来自动配置应用程序的各个方面,包括视图解析器。

自动配置的触发条件:

  1. 类路径检测:Spring Boot 会检查类路径下是否存在特定的类。例如,如果检测到 Thymeleaf 的相关类,它就会尝试配置 Thymeleaf。
  2. @ConditionalOnClass / @ConditionalOnMissingBean:自动配置类通常使用这些注解。
    • @ConditionalOnClass: 只有当指定的类存在于类路径上时,配置才会生效。
    • @ConditionalOnMissingBean: 只有当用户没有自己定义同类型的 Bean 时,Spring Boot 的自动配置 Bean 才会生效。

常见视图解析器的自动配置:

Spring Boot 为多种模板引擎提供了自动配置支持。这些配置通常在 spring-boot-autoconfigure.jar 中的 org.springframework.boot.autoconfigure.web.servlet (针对Servlet Web) 或 org.springframework.boot.autoconfigure.web.reactive (针对Reactive WebFlux) 包下。

a. Thymeleaf (spring-boot-starter-thymeleaf)

  • 依赖:添加 spring-boot-starter-thymeleaf 依赖时,相关的 Thymeleaf 类会被引入。
  • 自动配置类ThymeleafAutoConfiguration
  • 行为
    • 会自动配置 SpringResourceTemplateResolverSpringTemplateEngineThymeleafViewResolver
    • 默认模板位置:classpath:/templates/
    • 默认模板后缀:.html
    • 默认编码:UTF-8
    • 可以通过 application.propertiesapplication.yml 修改这些默认值:
      spring.thymeleaf.prefix=classpath:/templates/
      spring.thymeleaf.suffix=.html
      spring.thymeleaf.mode=HTML
      spring.thymeleaf.encoding=UTF-8
      spring.thymeleaf.cache=true # 生产环境建议 true,开发环境 false
      

b. FreeMarker (spring-boot-starter-freemarker)

  • 依赖:添加 spring-boot-starter-freemarker
  • 自动配置类FreeMarkerAutoConfiguration
  • 行为
    • 会自动配置 FreeMarkerConfigurerFreeMarkerViewResolver
    • 默认模板位置:classpath:/templates/ (注意,FreeMarker 传统上有一个自己的路径,但 Spring Boot 会配置 FreeMarkerConfigurertemplateLoaderPathspring.freemarker.template-loader-path 的值,默认为 classpath:/templates/)。
    • 默认模板后缀:.ftlh (FreeMarker Template Language HTML,也可以是 .ftl)
    • 可以通过 application.propertiesapplication.yml 修改:
      spring.freemarker.template-loader-path=classpath:/templates/freemarker/
      spring.freemarker.suffix=.ftl
      spring.freemarker.charset=UTF-8
      spring.freemarker.cache=true
      # 更多配置...
      

c. Groovy Templates (spring-boot-starter-groovy-templates)

  • 依赖:添加 spring-boot-starter-groovy-templates
  • 自动配置类GroovyTemplateAutoConfiguration
  • 行为
    • 会自动配置 GroovyMarkupConfigurerGroovyMarkupViewResolver
    • 默认模板位置:classpath:/templates/
    • 默认模板后缀:.tpl
    • 可以通过 application.propertiesapplication.yml 修改:
      spring.groovy.template.prefix=classpath:/templates/
      spring.groovy.template.suffix=.tpl
      # 更多配置...
      

d. JSP (特殊情况)

  • 依赖:JSP 通常不需要特定的 Spring Boot starter 来“启用”,而是依赖于 Servlet 容器(如 Tomcat, Jetty, Undertow)对 JSP 的支持。如果使用嵌入式容器,需要确保它支持 JSP。例如,对于 Tomcat,tomcat-embed-jasper 是必需的,它通常由 spring-boot-starter-web 间接引入。
  • 自动配置类WebMvcAutoConfiguration 内部有一个内部类 WebMvcAutoConfigurationAdapter,它会尝试配置 InternalResourceViewResolver
  • 行为
    • 如果 Spring Boot 检测到 javax.servlet.jsp.JspPage (或 Jakarta EE 9+ 的 jakarta.servlet.jsp.JspPage) 在类路径上,并且没有其他更专门的视图解析器(如 Thymeleaf 的)被配置,它可能会配置一个 InternalResourceViewResolver
    • 重要:JSP 在使用 Spring Boot 的可执行 JAR (fat JAR) 方式打包和运行时存在一些限制,因为 JSP 需要编译。它们更适合传统的 WAR 包部署。
    • 可以通过 application.propertiesapplication.yml 修改(如果 InternalResourceViewResolver 被自动配置):
      spring.mvc.view.prefix=/WEB-INF/jsp/
      spring.mvc.view.suffix=.jsp
      
      但通常,如果使用了像 Thymeleaf 这样的模板引擎,Spring Boot 会优先配置它们的 ViewResolver,而 InternalResourceViewResolver 的自动配置优先级较低。

e. ContentNegotiatingViewResolver (自动配置)

  • Spring Boot 默认会自动配置 ContentNegotiatingViewResolver (WebMvcAutoConfiguration 的一部分)。
  • 它会智能的包装所有其他已配置的(包括自动配置和用户自定义的)ViewResolver
  • 它使得应用可以根据请求(如 Accept 头)返回不同格式的响应(HTML, JSON, XML 等),而控制器代码无需改变。

f. BeanNameViewResolver (自动配置)

  • Spring Boot 也会自动配置 BeanNameViewResolver
  • 如果控制器返回的逻辑视图名与 Spring 应用上下文中某个 View bean 的名称匹配,则会使用该 View bean。它的 order 值较高(优先级较低),通常在 InternalResourceViewResolver 之后。

g. WelcomePageHandlerMapping 和静态资源

  • 虽然不是严格的 ViewResolver,但 Spring Boot 也会自动配置对 index.html 作为欢迎页面的支持 (WelcomePageHandlerMapping) 以及从 classpath:/static/, classpath:/public/, classpath:/resources/, classpath:/META-INF/resources/ 等位置提供静态资源的服务。

如何覆盖或禁用自动配置?

  1. 提供自己的 Bean:如果定义了与自动配置相同类型的 Bean (例如,你自己定义了一个 ThymeleafViewResolver Bean),那么 Spring Boot 的自动配置版本将不会生效 (因为 @ConditionalOnMissingBean)。
  2. 使用 application.properties:对于大多数自动配置的属性,我们可以通过 application.propertiesapplication.yml 来覆盖默认值。
  3. 排除自动配置类:如果想完全禁用某个自动配置,可以使用 @SpringBootApplication (或 @EnableAutoConfiguration) 的 exclude 属性:
    @SpringBootApplication(exclude = ThymeleafAutoConfiguration.class)
    public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
    }
    

总结:

  • 手动配置:给予完全的控制权,适用于非 Spring Boot 项目或需要深度定制的场景。
  • Spring Boot 自动配置:极大的简化了常见视图技术的集成。通过添加相应的 starter 依赖,Spring Boot 会根据约定自动配置好视图解析器,并允许通过属性文件进行简单的定制。如果需要更复杂的定制,仍然可以提供自己的 Bean 来覆盖自动配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理解网站导航文件:robots.txt、sitemap.xml与LLMs.txt的全面解析

在当今数字化时代&#xff0c;网站不仅需要为人类用户提供良好的浏览体验&#xff0c;还需要考虑搜索引擎和人工智能系统的可访问性。本文将深入探讨三种关键的网站导航文件&#xff1a;传统的robots.txt和sitemap.xml&#xff0c;以及新兴的LLMs.txt&#xff0c;分析它们的功能…

leetcode 349. Intersection of Two Arrays

题目描述 题目限制0 < nums1[i], nums2[i] < 1000&#xff0c;所以可以开辟一个1001个元素的数组来做哈希表。 class Solution { public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> table(1001,0…

【软件工程】软件多缺陷定位方法总结

软件多缺陷定位(Multi-Fault Localization)是软件工程中的一个重要研究方向,旨在同时定位代码中存在的多个缺陷(Bug)。由于多个缺陷可能相互干扰(如掩盖错误行为),导致传统单缺陷定位方法效果下降,因此需要针对多缺陷场景的特殊性设计方法。以下是常见的多缺陷定位方法…

【数据结构入门训练DAY-30】数的划分

文章目录 前言一、题目二、解题思路结语 前言 本次训练内容 训练DFS。训练解题思维。 一、题目 将整数n分成k份&#xff0c;且每份不能为空&#xff0c;任意两份不能相同(不考虑顺序)。 例如&#xff1a;n7&#xff0c;k3&#xff0c;下面三种分法被认为是相同的。 {1&a…

OpenCV进阶操作:图像直方图、直方图均衡化

文章目录 一、图像直方图二、图像直方图的作用三、使用matplotlib方法绘制直方图2.使用opencv的方法绘制直方图&#xff08;划分16个小的子亮度区间&#xff09;3、绘制彩色图像的直方图 四、直方图均衡化1、绘制原图的直方图2、绘制经过直方图均衡化后的图片的直方图3、自适应…

Open CASCADE学习|Geom2d_BezierCurve 类

概述 Open CASCADE 提供了几何建模的强大工具集,其中 Geom2d_BezierCurve 类用于表示二维贝塞尔曲线。贝塞尔曲线在计算机图形学和计算机辅助设计(CAD)中具有广泛应用,本文将详细介绍 Geom2d_BezierCurve 类及其使用方法。 贝塞尔曲线简介 贝塞尔曲线是一种参数曲线,广泛…

muduo源码解析

1.对类进行禁止拷贝 class noncopyable {public:noncopyable(const noncopyable&) delete;void operator(const noncopyable&) delete;protected:noncopyable() default;~noncopyable() default; }; 2.日志 使用枚举定义日志等级 enum LogLevel{TRACE,DEBUG,IN…

互联网大厂Java面试实录:Spring Boot与微服务架构在电商场景中的应用解析

&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通 &#x1f601; 2. 毕业设计专栏&#xff0c;毕业季咱们不慌忙&#xff0c;几百款毕业设计等你选。 ❤️ 3. Python爬虫专栏…

关于汇编语言与程序设计——单总线温度采集与显示的应用

一、实验要求 (1)握码管的使用方式 (2)掌握DS18B20温度传感器的工作原理 (3)掌握单总线通信方式实现 MCU与DS18B20数据传输 二、设计思路 1.整体思路 通过编写数码管显示程序和单总线温度采集程序&#xff0c;结合温度传感报警&#xff0c;利用手指触碰传感器&#xff0c;当…

用html+js+css实现的战略小游戏

效果图: 兄弟们&#xff0c;话不多说&#xff0c;直接上代码 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

Navicat BI 数据分析功能上线 | 数据洞察新方法

Navicat 17.2 版本一经发布&#xff0c;便以 AI 助手赋能智能交互、Snowflake 支持拓展数据连接版图、拓展对关系型、维度以及数据仓库 2.0 建模方法的支持等新特性与功能抓住了用户的目光&#xff0c;但其中一项低调且实用的更新 - 在 BI 数据预览中深度集成数据分析工具&…

【ts】defineProps数组的类型声明

第一种&#xff1a;使用Record<string, unknown> Record<string, unknown>表示一个对象&#xff0c;键是string类型&#xff0c;值是未知的 import { defineProps, PropType } from vue;const props defineProps({dataList: {type: Array as PropType<Record…

OpenCv实战笔记(4)基于opencv实现ORB特征匹配检测

一、原理作用 ORB 原理&#xff08;Oriented FAST and Rotated BRIEF&#xff09;&#xff1a; 特征点检测&#xff1a;使用 FAST 算法检测角点&#xff08;关键点&#xff09;。 方向计算&#xff1a;为每个关键点分配主方向&#xff0c;增强旋转不变性。 特征描述&#xff1a…

Unreal 从入门到精通之VR常用操作

文章目录 前言1.如何设置VRPawn视角的位置。2.如何播放视频3.如何播放VR全景视频。4.如何打开和关闭VR模式。前言 我们使用Unreal5 开发VR 项目的时候,会遇到很多常见问题。 比如: 1.如何设置VRPawn视角的位置。 2.如何播放视频。 3.如何播放VR全景视频。 4.如何打开和关闭V…

[论文阅读]Deep Cross Network for Ad Click Predictions

摘要 特征工程是许多预测模型成功的关键。然而&#xff0c;这个过程是困难的&#xff0c;甚至需要手动特征工程或穷举搜索。DNN能够自动学习特征交互&#xff1b;然而&#xff0c;它们隐式地生成所有的交互&#xff0c;并且不一定有效地学习所有类型的交叉特征。在本文中&…

数据库(MySQL)基础

一、登录数据库 在linux系统中登录数据库的指令 mysql -h 127.48.0.236 -P 3306 -u root -p -h&#xff1a;填写IP地址&#xff0c;指明要连接的主机。如果不加该字段表示本地主机-P&#xff1a;填写端口号&#xff0c;指明进程。 如果不加该字段会使用默认的端口号。-u&…

远程调试---在电脑上devtools调试运行在手机上的应用

1、启动项目–以vite项目为例:先ipconfig查看ip地址 ,然后在vite中配置host为ip地址 2、手机上查看项目:保证手机和电脑在同一局域网, 在手机浏览器打开我们vite启动的项目地址, 3、使用chii进行远程调试 (1) 安装 npm install chii -g (2)启动 chii start -p 8080 (3)在…

【程序员AI入门:开发】11.从零构建智能问答引擎:LangChain + RAG 实战手册

1、技术选型 组件推荐方案说明文本嵌入模型sentence-transformers/all-MiniLM-L6-v2轻量级且效果较好的开源模型向量数据库FAISS高效的本地向量检索库大语言模型GPT-3.5/开源LLM&#xff08;如ChatGLM3&#xff09;根据资源选择云端或本地模型文档处理框架LangChain简化RAG流程…

【Linux基础】文件查找和文本处理指令

目录 grep命令 find命令 tar命令 head命令 tail命令 wc命令 tee命令 grep命令 作用&#xff1a;在文件中搜索匹配特定模式的文本行&#xff0c;并将结果输出到标准输出&#xff08;通常是终端&#xff09;。 基本用法&#xff1a; grep [选项] 搜索模式 [文件名] 常用…

云轴科技ZStack入选赛迪顾问2025AI Infra平台市场发展报告代表厂商

DeepSeek凭借低成本、高性能、开源优势带来的蝴蝶效应依然在持续影响企业AI应用部署。尤其在数据安全备受关注的背景下&#xff0c;私有化部署已经成为企业应用AI大模型的优选方案。赛迪顾问在近期发布的《2025中国AI Infra平台市场发展研究报告》中认为&#xff0c;在推理算力…