当前位置: 首页 > news >正文

Spring MVC 九大组件源码深度剖析(七):ViewResolver - 视图解析的智慧

文章目录

      • 一、视图解析的核心价值
      • 二、核心接口设计
      • 三、五大核心实现类源码解析
        • 1. InternalResourceViewResolver(JSP核心解析器)
        • 2. XmlViewResolver(XML配置视图解析器)
        • 3. ResourceBundleViewResolver(属性文件配置)
        • 4. ContentNegotiatingViewResolver(内容协商解析器)
        • 5. AbstractTemplateViewResolver(模板引擎抽象基类)
      • 四、视图解析链工作机制
        • Ordered接口控制优先级:
      • 五、内容协商机制深度解析
        • 1. 协商策略
        • 2. 支持的协商策略
        • 3. 视图内容协商流程
      • 六、现代模板引擎集成
        • 1. Thymeleaf集成原理
        • 2. FreeMarker集成原理
        • 3. Velocity集成原理
      • 七、视图解析性能优化
        • 1. 视图缓存机制
        • 2. 模板预编译
        • 3. 静态资源优化
      • 八、高级应用场景
        • 1. 多主题支持
        • 2. 设备自适应视图
        • 3. 动态视图选择
      • 九、设计思想总结

本文是Spring MVC九大组件解析系列第七篇,我们将深入探索视图解析的核心机制,揭开逻辑视图名到物理视图的转换奥秘,分析模板引擎集成原理,以及ViewResolver如何支持多视图技术统一抽象。Spring MVC整体设计核心解密参阅:Spring MVC设计精粹:源码级架构解析与实践指南

一、视图解析的核心价值

在Web应用中,视图解析是连接控制器与展示层的关键桥梁:

  • 呈现分离:将业务逻辑与展示逻辑完全解耦
  • 多视图支持:同一数据模型支持多种呈现方式(HTML/JSON/XML等)
  • 灵活扩展:支持各种模板引擎和技术栈的无缝集成
  • 国际化:根据地域和语言动态选择视图资源

Spring MVC通过ViewResolver组件实现四大核心功能:

  1. 视图定位:将逻辑视图名映射到物理视图资源
  2. 技术抽象:统一不同视图技术的访问接口
  3. 内容协商:根据客户端需求选择最佳视图呈现方式
  4. 链式解析:支持多个解析器协同工作

二、核心接口设计

源码位置org.springframework.web.servlet.ViewResolver
核心源码
在这里插入图片描述
源码位置org.springframework.web.servlet.View
核心源码
在这里插入图片描述
设计哲学:通过统一的接口抽象各种视图技术,实现策略模式的可扩展架构。

三、五大核心实现类源码解析

1. InternalResourceViewResolver(JSP核心解析器)

功能:支持JSP、JSTLServlet容器原生视图技术
源码位置org.springframework.web.servlet.view.InternalResourceViewResolver
核心源码
在这里插入图片描述
在这里插入图片描述

配置示例

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"/><property name="suffix" value=".jsp"/><property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
</bean>
2. XmlViewResolver(XML配置视图解析器)

功能:通过XML文件定义视图bean
源码位置org.springframework.web.servlet.view.XmlViewResolver
核心源码
在这里插入图片描述
在这里插入图片描述
XML视图定义

<beans><bean id="userList" class="org.springframework.web.servlet.view.JstlView"><property name="url" value="/WEB-INF/views/user/list.jsp"/></bean><bean id="productDetail" class="org.springframework.web.servlet.view.JstlView"><property name="url" value="/WEB-INF/views/product/detail.jsp"/></bean>
</beans>
3. ResourceBundleViewResolver(属性文件配置)

功能:通过properties文件配置视图映射
源码位置org.springframework.web.servlet.view.ResourceBundleViewResolver
核心源码
在这里插入图片描述
在这里插入图片描述
属性文件配置(views.properties):

userList.(class)=org.springframework.web.servlet.view.JstlView
userList.url=/WEB-INF/views/user/list.jspproductDetail.(class)=org.springframework.web.servlet.view.JstlView
productDetail.url=/WEB-INF/views/product/detail.jsp
4. ContentNegotiatingViewResolver(内容协商解析器)

功能:根据客户端请求选择最佳视图
源码位置org.springframework.web.servlet.view.ContentNegotiatingViewResolver
核心源码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. AbstractTemplateViewResolver(模板引擎抽象基类)

功能:为各种模板引擎提供统一抽象
源码位置org.springframework.web.servlet.view.AbstractTemplateViewResolver
核心源码
在这里插入图片描述
在这里插入图片描述

四、视图解析链工作机制

Spring MVC支持多个ViewResolver组成解析链:
在这里插入图片描述

Ordered接口控制优先级:
@Configuration
public class ViewResolverConfig {@Bean@Order(1)public ViewResolver contentNegotiatingViewResolver() {return new ContentNegotiatingViewResolver();}@Bean@Order(2)public ViewResolver thymeleafViewResolver() {return new ThymeleafViewResolver();}@Bean@Order(3)public ViewResolver jspViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");return resolver;}
}

五、内容协商机制深度解析

1. 协商策略

在这里插入图片描述

2. 支持的协商策略
策略类型实现类检测方式
路径扩展PathExtensionContentNegotiationStrategy.html, .json, .xml
参数指定ParameterContentNegotiationStrategy?format=json
请求头HeaderContentNegotiationStrategyAccept: application/json
固定类型FixedContentNegotiationStrategy默认配置
3. 视图内容协商流程

在这里插入图片描述

六、现代模板引擎集成

1. Thymeleaf集成原理
// 关键源码:org.thymeleaf.spring5.view.ThymeleafViewResolver
// 试图加载
protected View loadView(String viewName, Locale locale) throws Exception {// 构建ThymeleafViewThymeleafView view = new ThymeleafView(viewName);view.setTemplateEngine(this.templateEngine);view.setLocale(locale);return view;
}// 视图渲染
public class ThymeleafView extends AbstractView {protected void renderMergedOutputModel(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {// 创建Thymeleaf上下文WebContext context = new WebContext(request, response, request.getServletContext(), getLocale(), model);// 渲染模板this.templateEngine.process(this.viewName, context, response.getWriter());}
}
2. FreeMarker集成原理
// 关键源码:org.springframework.web.servlet.view.freemarker.FreeMarkerView
// 视图渲染
protected void doRender(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {// 暴露Spring宏支持if (this.exposeSpringMacroHelpers) {model.put("spring", SpringMacroRequestContext(request, response));}// 渲染FreeMarker模板getTemplate().process(model, response.getWriter());
}
3. Velocity集成原理
// 关键源码:org.springframework.web.servlet.view.velocity.VelocityView
// 视图渲染
protected void doRender(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {// 创建Velocity上下文VelocityContext velocityContext = createVelocityContext(model, request, response);// 合并模板mergeTemplate(getTemplate(), velocityContext, response);
}

七、视图解析性能优化

1. 视图缓存机制
// 关键源码:org.springframework.web.servlet.view.AbstractCachingViewResolver
public View resolveViewName(String viewName, Locale locale) throws Exception {// 生成缓存键Object cacheKey = getCacheKey(viewName, locale);// 检查缓存View view = this.viewAccessCache.get(cacheKey);if (view == null) {synchronized (this.viewCreationCache) {view = this.viewCreationCache.get(cacheKey);if (view == null) {// 创建新视图并缓存view = createView(viewName, locale);if (view != null) {this.viewCreationCache.put(cacheKey, view);this.viewAccessCache.put(cacheKey, view);}}}}return view;
}
2. 模板预编译
@Configuration
public class TemplatePrecompilationConfig {@PostConstructpublic void precompileTemplates() {// 启动时预编译常用模板String[] templates = {"index", "user/list", "product/detail"};for (String template : templates) {precompileTemplate(template);}}private void precompileTemplate(String templateName) {try {// 触发模板编译Template template = templateEngine.getTemplate(templateName);// 缓存编译结果templateCache.put(templateName, template);} catch (Exception e) {logger.warn("Failed to precompile template: " + templateName, e);}}
}
3. 静态资源优化
@Configuration
public class ResourceHandlingConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 启用资源版本控制和缓存registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/").setCachePeriod(3600).resourceChain(true).addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));}@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {// 启用视图缓存registry.jsp("/WEB-INF/views/", ".jsp").cache(true);}
}

八、高级应用场景

1. 多主题支持
public class ThemeAwareViewResolver extends InternalResourceViewResolver {@Overrideprotected View loadView(String viewName, Locale locale) throws Exception {// 获取当前主题String theme = ThemeContextHolder.getCurrentTheme();// 构建主题化视图路径String themedViewName = "/themes/" + theme + viewName;return super.loadView(themedViewName, locale);}
}
2. 设备自适应视图
public class DeviceAwareViewResolver extends ContentNegotiatingViewResolver {@Overrideprotected View getBestView(List<View> candidateViews, List<MediaType> requestedMediaTypes,ServerWebExchange exchange) {// 检测设备类型Device device = DeviceUtils.getCurrentDevice();// 优先选择设备适配视图for (View view : candidateViews) {if (view.supportsDevice(device)) {return view;}}return super.getBestView(candidateViews, requestedMediaTypes, exchange);}
}
3. 动态视图选择
@Controller
public class DynamicViewController {@GetMapping("/content/{id}")public String getContent(@PathVariable String id, HttpServletRequest request) {// 根据业务逻辑动态选择视图ContentType type = contentService.getContentType(id);switch (type) {case ARTICLE:return "articleTemplate";case VIDEO:return "videoTemplate";case GALLERY:return "galleryTemplate";default:return "defaultTemplate";}}
}

九、设计思想总结

  1. 策略模式扩展
    多种视图解析策略满足不同技术栈需求

  2. 链式职责分配
    多个ViewResolver组成处理链,各司其职

  3. 内容协商智能
    根据客户端能力自动选择最佳视图呈现方式

  4. 缓存性能优化
    视图缓存和模板预编译大幅提升渲染性能

  5. 统一抽象架构
    为各种视图技术提供一致的编程模型


下一篇预告
九大组件源码剖析(八):RequestToViewNameTranslator - 视图名转换的奥秘
我们将深入分析默认视图名生成机制,揭秘如何从请求路径自动推导视图名称。


思考题:在前后端分离架构下,ViewResolver的角色发生了怎样的演变?如何设计一套同时支持服务器端渲染和客户端渲染的混合视图解析方案?


文章转载自:

http://SZxkHFRi.wfpmt.cn
http://MlW7LSbF.wfpmt.cn
http://LJma9oWM.wfpmt.cn
http://8DyPwZ49.wfpmt.cn
http://Ag2bBjlh.wfpmt.cn
http://PNkcnmUv.wfpmt.cn
http://FUirjT0Y.wfpmt.cn
http://1e0yHj0X.wfpmt.cn
http://9J7ITIu5.wfpmt.cn
http://GWYVYXaf.wfpmt.cn
http://j9mi4Wwt.wfpmt.cn
http://D1Rv6Vkm.wfpmt.cn
http://43xnFfbt.wfpmt.cn
http://a9ZPKgKN.wfpmt.cn
http://FgBpqGZi.wfpmt.cn
http://epso1juX.wfpmt.cn
http://kIXYdRST.wfpmt.cn
http://Ul9C5alf.wfpmt.cn
http://gPpltRuM.wfpmt.cn
http://F6tE89AK.wfpmt.cn
http://9YGFP1iD.wfpmt.cn
http://kHB5lxcg.wfpmt.cn
http://6zBVC6iO.wfpmt.cn
http://F8POKgmL.wfpmt.cn
http://6ekhjZmo.wfpmt.cn
http://rIvqomAa.wfpmt.cn
http://SRPz2PWq.wfpmt.cn
http://XFCo5rSU.wfpmt.cn
http://WynSCW2c.wfpmt.cn
http://NwE9vwwk.wfpmt.cn
http://www.dtcms.com/a/383868.html

相关文章:

  • 【左程云算法09】栈的入门题目-最小栈
  • java设计模式三、创建者模式
  • 出现次数最多的字符 字符串处理
  • 根据IP获取用户信息和天气信息的方法
  • Paxos协议
  • 上网行为二层部署案例
  • XLua教程之热补丁技术
  • Linux 基本命令超详细解释第一期 | cd | pwd | ls | mkdir | rmdir
  • 如何查找 Linux 中 `dm-X` 设备对应的真实磁盘或虚拟机?
  • 线性稳压器LDO原理
  • 大模型浪潮来袭
  • 第6课:安全性与权限控制
  • 如何用 Rust 重写 SQLite 数据库(二):是否有市场空间?
  • pgsql 特有字段记录
  • Leetcode第165场双周赛题目详解+复盘
  • rt1180 rt1180处理器ethercat具体技术介绍
  • Sugov 关于频率变化
  • 多语言编码Agent解决方案(6)-部署和使用指南
  • React 原理篇 - React 新架构深度解析
  • Flowgorith,一款图形化编程入门工具
  • LeetCode 674.最长连续递增序列
  • 贪心算法在AGV无人车路径规划中的应用
  • Week 16: 深度学习补遗:集成学习进阶与量子计算概念入门
  • HTTP 协议的基本格式
  • 深入理解 Java 异常处理机制
  • AI产品经理面试宝典第93天:Embedding技术选型与场景化应用指南
  • commons-csv
  • 【C++】类和对象1
  • MySQL学习笔记01-连接 数据模型
  • 高等教育学