【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(中)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(中)

HandlerAdapter


因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就ok,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情。


Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人


public interface HandlerAdapter {
  //当前 HandlerAdapter 是否支持这个 Handler
  boolean supports(Object handler);
  //调用handle处理这个请求,然后返回ModelAndView 对象
  @Nullable
  ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  long getLastModified(HttpServletRequest request, Object handler);
}


因为它和HandlerMapping联系紧密,因此且听下文分解


HandlerAdapter可以有多个


HandlerExceptionResolver


其它组件都是用来干活的。在干活的过程中难免会出现问题,出问题后怎么办呢?这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。具体来说,此组件的作用是根据异常设置ModelAndView,之后再交给render方法进行渲染。


以前我们可以用web.xml的<error-page>标签来捕获状态码500 400的异常,但是这个已经out了,现在全局的异常都可以交给HandlerExceptionResolver去捕获处理

public interface HandlerExceptionResolver {
  @Nullable
  ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}


这个接口捕获的是所有异常,而官方推荐的是使用@ExceptionHandler注解去捕获固定的异常


这个类建议交给Spring子容器管理(我们可以多实现),因为它就像一个特殊的controller


关于这块Spring MVC的全局异常的处理的一些技巧(比如页面、get、post、ajax等),请关注后面博文

RequestToViewNameTranslator


Spring MVC是通过ViewName来找到对应的视图的,而此接口的作用就是从request中获取viewName。

public interface RequestToViewNameTranslator {
  @Nullable
  String getViewName(HttpServletRequest request) throws Exception;
}


它只有一个实现,默认实现:DefaultRequestToViewNameTranslator:


  @Override
  public String getViewName(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    return (this.prefix + transformPath(lookupPath) + this.suffix);
  }
  @Nullable
  protected String transformPath(String lookupPath) {
    String path = lookupPath;
    if (this.stripLeadingSlash && path.startsWith(SLASH)) {
      path = path.substring(1);
    }
    if (this.stripTrailingSlash && path.endsWith(SLASH)) {
      path = path.substring(0, path.length() - 1);
    }
    if (this.stripExtension) {
      path = StringUtils.stripFilenameExtension(path);
    }
    if (!SLASH.equals(this.separator)) {
      path = StringUtils.replace(path, SLASH, this.separator);
    }
    return path;
  }


主要实现就是调用UrlPathHelper的getLookupPathForRequest的方法获取一个looup路径。transformPath方法主要是对获取的路径字符串再做个简单处理罢了。

所以核心是UrlPathHelper的getLookupPathForRequest的实现:

(解析路径这块,这里就不做太多的解释了,自己读读源码,相对来说比较简单)

ViewResolver


ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作


ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。


public interface ViewResolver {
  @Nullable
  View resolveViewName(String viewName, Locale locale) throws Exception;
}


image.png

1.AbstractCachingViewResolver 基于缓存的抽象视图解析器


2.UrlBasedViewResolver 实现了缓存 提供了prefix suffix拼接的url视图解析器。


3.InternalResourceViewResolver 基于url 的内部资源视图解析器。


4.XmlViewResolver 基于xml的缓存视图解析器


5.BeanNameViewResolver beanName来自容器,并且不支持缓存。


6.ResourceBundleViewResolver 这个有点复杂


7.reeMarkerViewResolver、VolocityViewResolver 都基于url 但会解析成特定的view

实现类也非常的多,在Spring MVC里是一个非常非常重要的概念(比如什么时候返回页面,什么时候返回json呢?),因此后面会有专门的文章进行深入解读


ViewResolverComposite简单来说就是使用简单的List来保存你配置使用的视图解析器。


ViewResolvers可以有多个

FlashMapManager


用来管理FlashMap的,FlashMap主要用在redirect中传递参数。

public interface FlashMapManager {
    @Nullable
    FlashMap retrieveAndUpdate(HttpServletRequest var1, HttpServletResponse var2);
    void saveOutputFlashMap(FlashMap var1, HttpServletRequest var2, HttpServletResponse var3);
}


image.png


可以看出结构图非常简单,抽象类采用模板模式定义整个流程,具体实现类用SessionFlashMapManager通过模板方法提供了具体操作FlashMap的功能。

功能说明:


  • 实际的Session中保存的FlashMap是List类型,也就是说一个Session可以保存多个FlashMap,一个FlashMap保存着一套Redirect转发所传递的参数
  • FlashMap继承自HashMap,除了用于HashMap的功能和设置有效期,还可以保存Redirect后的目标路径和通过url传递的参数,这两项内容主要用来从Session保存的多个FlashMap中查找当前的FalshMap


具体请持续关注吧,后面再详说


至此,SpringMVC中的9大组件也就简单地概述了一遍。通过对此9大组件的宏观认识,对分析SpringMVC的设计、原理与实现都会有很大的帮助作用。


onRefresh(wac) / initStrategies(wac)详解

这可以说是DisparcherServlet初始化时的核心逻辑


initMultipartResolver

  private void initMultipartResolver(ApplicationContext context) {
    try {
      this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
    } catch (NoSuchBeanDefinitionException ex) {
      this.multipartResolver = null;
    }
  }


这个很简单,若我们向容器里配置了此Bean就有,否则默认是不支持文件上传的

备注:注意配置此些配型Bean的名称,都是有固定值的,请必须保证一样,否则你的配置将不生效。下同

相关文章
|
28天前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
1月前
|
前端开发 JavaScript 开发者
Web组件:一种新的前端开发范式
【10月更文挑战第9天】Web组件:一种新的前端开发范式
38 2
|
17天前
|
消息中间件 监控 Kafka
Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面
随着大数据技术的发展,Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面,方便管理和监控 Kafka 集群。本文详细介绍了 Kafka Manager 的部署步骤和基本使用方法,包括配置文件的修改、启动命令、API 示例代码等,帮助你快速上手并有效管理 Kafka 集群。
39 0
|
1月前
|
前端开发 JavaScript Go
前端开发趋势:从响应式设计到Web组件的探索
【10月更文挑战第1天】前端开发趋势:从响应式设计到Web组件的探索
38 3
|
30天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
65 0
|
2月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
119 3
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
100 3
|
15天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
101 44
|
11天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
26 1
|
13天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。