WebMvcConfigurationSupport
WebMvcConfigurationSupport
是Spring MVC框架中的一个核心配置支持类。这个类提供了Spring MVC配置的许多默认设置,并允许开发者自定义这些设置。
类定义
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware
这个类实现了ApplicationContextAware
和ServletContextAware
接口,这意味着它可以在运行时被注入Spring的ApplicationContext
和Servlet容器的ServletContext
。
这允许WebMvcConfigurationSupport
访问Spring应用上下文和Servlet上下文,进而可以进行更复杂的配置。
静态属性
这些属性是静态的,并且用于检测某些库是否存在于类路径中,从而确定是否启用某些特性。
romePresent
: 检测 Rome 库(用于处理RSS和Atom feeds)是否可用。jaxb2Present
: 检测 JAXB 2 库(用于XML绑定)是否可用。jackson2Present
: 检测 Jackson 2 库(用于JSON处理)是否可用。jackson2XmlPresent
: 检测 Jackson 2 XML 库是否可用。jackson2SmilePresent
: 检测 Jackson 2 Smile 格式支持是否可用。jackson2CborPresent
: 检测 Jackson 2 CBOR 格式支持是否可用。gsonPresent
: 检测 Gson 库(用于JSON处理)是否可用。jsonbPresent
: 检测 JSON-B 库是否可用。kotlinSerializationCborPresent
: 检测 Kotlin 序列化 CBOR 支持是否可用。kotlinSerializationJsonPresent
: 检测 Kotlin 序列化 JSON 支持是否可用。kotlinSerializationProtobufPresent
: 检测 Kotlin 序列化 Protocol Buffers 支持是否可用。
实例属性
这些属性是实例级别的,它们用于存储配置设置和组件。
applicationContext
: 存储Spring的ApplicationContext
,通过ApplicationContextAware
接口注入。servletContext
: 存储Servlet容器的ServletContext
,通过ServletContextAware
接口注入。interceptors
: 存储自定义的HandlerInterceptor
,用于请求处理过程中的拦截。pathMatchConfigurer
: 用于配置路径匹配选项,如是否启用后缀模式匹配。contentNegotiationManager
: 用于配置内容协商策略,比如根据请求的Accept头部选择不同的响应内容类型。argumentResolvers
: 存储自定义的HandlerMethodArgumentResolver
,用于解析控制器方法参数。returnValueHandlers
: 存储自定义的HandlerMethodReturnValueHandler
,用于处理控制器方法返回值。messageConverters
: 存储自定义的HttpMessageConverter
,用于转换HTTP请求和响应。corsConfigurations
: 存储跨域资源共享(CORS)的配置。asyncSupportConfigurer
: 用于配置异步请求处理。
功能
WebMvcConfigurationSupport
提供了许多配置方法,允许开发者定制Spring MVC的各个方面的行为,包括:
- 路径匹配和URL映射。
- 视图解析和视图控制器。
- 静态资源处理。
- 拦截器注册。
- 异步请求支持。
- 内容协商。
- 消息转换器配置。
- CORS配置。
DispatcherServlet
类
DispatcherServlet
是 Spring MVC 框架中的核心类,它负责处理 HTTP 请求和响应,并根据请求内容执行相应的控制器方法。这个类扩展了 FrameworkServlet
类,后者是 Spring 框架中的一个抽象类,用于提供 Servlet 的通用功能。
类定义
public class DispatcherServlet extends FrameworkServlet
DispatcherServlet
继承自 FrameworkServlet
,提供了处理 HTTP 请求和响应的机制。
重要属性
defaultStrategies
: 这是一个静态的Properties
对象,可能用于存储默认的策略配置。multipartResolver
: 一个MultipartResolver
对象,用于处理多部分请求(如文件上传)。localeResolver
: 一个LocaleResolver
对象,用于解析客户端的语言环境。handlerMappings
: 一个HandlerMapping
对象的列表,用于存储处理器映射器。handlerAdapters
: 一个HandlerAdapter
对象的列表,用于存储处理器适配器。handlerExceptionResolvers
: 一个HandlerExceptionResolver
对象的列表,用于存储处理器异常解析器。viewNameTranslator
: 一个RequestToViewNameTranslator
对象,用于将请求转换为视图名称。flashMapManager
: 一个FlashMapManager
对象,用于管理闪存映射。viewResolvers
: 一个ViewResolver
对象的列表,用于存储视图解析器。parseRequestPath
: 一个布尔值,表示是否解析请求路径。
重要方法
doService
方法
源码
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.parseAndCache(request);
}
try {
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
doService
方法是DispatcherServlet
的核心处理逻辑,它被调用以处理每个进入的HTTP请求。
日志记录与属性快照:
logRequest(request);
调用一个日志方法来记录请求的细节。- 如果请求是一个包含请求(即在服务器端由另一个请求触发的),则保存当前请求的所有属性到一个快照中。这是为了在处理完包含请求后恢复这些属性,确保它们不会被后续请求覆盖或修改。
框架对象注入:
- 注入各种框架组件到请求中,如
ApplicationContext
、LocaleResolver
、ThemeResolver
等,这些组件对处理请求和渲染视图非常重要。
- 注入各种框架组件到请求中,如
Flash Map管理:
- 如果启用了Flash Map功能,从请求中恢复并更新Flash Map,用于存储跨请求的数据(例如,重定向时的数据)。同时,在请求中设置输出Flash Map和Flash Map Manager,以便在响应完成后更新Flash Map。
请求路径解析:
- 如果配置了请求路径解析,将解析请求路径并缓存结果,这有助于URL映射和请求分发。
实际请求分发:
- 调用
doDispatch
方法,这是真正处理请求的地方。它会查找匹配的处理器(Handler)、调用拦截器(Interceptors)、执行处理器、调用适配器(Adapter)处理请求,并最终选择和渲染视图。
- 调用
清理工作:
- 在请求处理完成之后,如果异步处理没有开始,则恢复之前保存的属性快照,确保请求的隔离性。
- 如果解析了请求路径,需要恢复原始的解析结果,以防该请求作为包含请求的一部分。
总的来说,doService
方法是Spring MVC框架中处理请求的核心流程控制点,它确保了所有必要的框架组件正确地初始化和使用,同时也处理了请求的生命周期管理和资源清理。
doDispatch
方法
源码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new ServletException("Handler dispatch failed: " + err, err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new ServletException("Handler processing failed: " + err, err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
这个方法是Spring MVC框架中的核心方法,用于处理HTTP请求并将其分派到相应的处理器进行处理。
- 首先,检查请求是否为multipart类型(如文件上传),如果是,则对其进行解析。
- 根据请求确定对应的处理器(Handler)。如果没有找到处理器,则返回404错误。
- 确定处理器适配器(HandlerAdapter),用于处理当前请求的处理器。
- 如果请求方法是GET或HEAD,检查处理器支持的最后修改时间,如果资源未被修改,则返回304状态码。
- 在处理器执行前调用preHandle方法,如果返回false,则终止处理器执行。
- 实际调用处理器的handle方法,处理请求并返回ModelAndView对象。
- 如果异步处理已经开始,则直接返回。
- 应用默认视图名称(如果有的话)。
- 调用处理器的postHandle方法,对请求和响应进行后处理。
- 处理处理器执行结果,包括异常处理、视图渲染等。
- 如果在处理器执行过程中发生异常,触发afterCompletion方法进行清理工作。
- 最后,如果使用了异步处理,则调用applyAfterConcurrentHandlingStarted方法;否则,清理multipart请求相关的资源。
doService和doDispatch的区别
doService 方法
doService
方法是DispatcherServlet
实现HttpServlet
接口中的service
方法时重写的方法。它在整个请求处理流程中起到一个“总调度者”的作用,负责整个请求的生命周期管理。主要职责包括:
- 初始化处理:日志记录,快照保存,框架对象注入,Flash Map管理等准备工作。
- 请求路径解析:如果启用,解析请求路径并缓存其结果。
- 核心分发:调用
doDispatch
方法进行实际的请求分发。 - 清理工作:如果异步处理未启动,则恢复之前的属性快照,确保请求隔离;如果解析了请求路径,需要恢复原始的解析结果。
doDispatch 方法
doDispatch
方法是doService
方法内部调用的,它更专注于请求的实际处理流程,是请求分发的核心。它的主要任务包括:
- Handler映射:根据请求找到合适的Handler(控制器)。
- Handler适配:确定如何调用找到的Handler。
- 预处理:调用任何注册的拦截器的
preHandle
方法。 - Handler执行:调用Handler处理请求。
- 视图解析:解析返回的ModelAndView对象,得到视图名和模型数据。
- 渲染视图:使用得到的视图名和模型数据渲染视图。
- 后处理:调用任何注册的拦截器的
postHandle
和afterCompletion
方法。
简而言之,doService
方法负责整个请求处理流程的宏观管理,包括初始化、调用doDispatch
进行核心处理以及最后的清理工作;而doDispatch
方法则深入到请求处理的具体细节,包括找到并调用正确的控制器和渲染视图。
静态资源处理
在WebMvcConfigurationSupport
类中,静态资源处理主要通过个下面的方法:
addResourceHandlers(ResourceHandlerRegistry registry)
这个方法负责添加资源处理器(Resource Handlers),用于处理静态资源的请求。
Spring MVC通过ResourceHandlerRegistry
类来注册资源处理器,可以通过重写这个方法来添加自定义的静态资源映射。
以下是一个例子,展示了如何重写addResourceHandlers
方法来添加一个资源处理器,将位于/resources/**
的URL映射到类路径下的/static
目录:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/static/");
}
ResourceHandlerRegistry
类
ResourceHandlerRegistry
类负责管理静态资源处理器的注册,并允许开发者指定哪些URL路径应该映射到静态资源处理器。
属性
servletContext
: 类型为ServletContext
,表示关联的Servlet上下文,用于访问Web应用的信息。applicationContext
: 类型为ApplicationContext
,表示Spring应用上下文,用于访问Spring管理的Bean。contentNegotiationManager
: 类型为ContentNegotiationManager
,用于确定如何根据请求选择合适的响应内容类型。pathHelper
: 类型为UrlPathHelper
,用于解析请求路径。registrations
: 类型为List<ResourceHandlerRegistration>
,存储了所有注册的资源处理器。order
: 类型为int
,定义了资源处理器映射的顺序,相对于其他HandlerMapping
。
方法
addResourceHandler(String... pathPatterns)
: 添加一个资源处理器,用于处理与指定路径模式匹配的请求。返回一个ResourceHandlerRegistration
实例,允许进一步配置资源位置和缓存设置。hasMappingForPattern(String pathPattern)
: 检查是否已经为给定的路径模式注册了资源处理器。setOrder(int order)
: 设置资源处理器映射的顺序。getHandlerMapping()
: 返回一个HandlerMapping
实例,它包含了所有注册的资源处理器。如果没有注册任何处理器,则返回null
。
ResourceHandlerRegistry
类的主要功能是通过addResourceHandler
方法注册资源处理器。开发者可以指定一个或多个路径模式,如"/resources/**"
,来匹配静态资源的请求。然后,通过返回的ResourceHandlerRegistration
对象,可以添加资源位置(例如,类路径下的目录或Web应用的目录)以及设置资源的缓存周期。
ResourceHttpRequestHandler
类
ResourceHttpRequestHandler
类是 Spring MVC 中用于处理静态资源请求的核心类。它实现了多个接口,以提供静态资源(如图片、CSS、JavaScript 文件等)的 HTTP 请求处理。
源码
public class ResourceHttpRequestHandler extends WebContentGenerator implements HttpRequestHandler, EmbeddedValueResolverAware, InitializingBean, CorsConfigurationSource {
private static final Log logger = LogFactory.getLog(ResourceHttpRequestHandler.class);
private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset=";
private final List<String> locationValues = new ArrayList(4);
private final List<Resource> locationResources = new ArrayList(4);
private final List<Resource> locationsToUse = new ArrayList(4);
private final Map<Resource, Charset> locationCharsets = new HashMap(4);
private final List<ResourceResolver> resourceResolvers = new ArrayList(4);
private final List<ResourceTransformer> resourceTransformers = new ArrayList(4);
@Nullable
private ResourceResolverChain resolverChain;
@Nullable
private ResourceTransformerChain transformerChain;
@Nullable
private ResourceHttpMessageConverter resourceHttpMessageConverter;
@Nullable
private ResourceRegionHttpMessageConverter resourceRegionHttpMessageConverter;
@Nullable
private ContentNegotiationManager contentNegotiationManager;
private final Map<String, MediaType> mediaTypes = new HashMap(4);
@Nullable
private CorsConfiguration corsConfiguration;
@Nullable
private UrlPathHelper urlPathHelper;
private boolean useLastModified = true;
@Nullable
private Function<Resource, String> etagGenerator;
private boolean optimizeLocations = false;
@Nullable
private StringValueResolver embeddedValueResolver;
// ...
}
类定义
public class ResourceHttpRequestHandler extends WebContentGenerator implements HttpRequestHandler, EmbeddedValueResolverAware, InitializingBean, CorsConfigurationSource
extends WebContentGenerator
:ResourceHttpRequestHandler
继承自WebContentGenerator
,它提供了HTTP内容生成的基础功能,例如设置HTTP缓存头。implements HttpRequestHandler
: 标识这个类可以处理 HTTP 请求。implements EmbeddedValueResolverAware
: 允许类通过setEmbeddedValueResolver
方法注入字符串解析器,用于解析占位符和表达式。implements InitializingBean
: 提供了afterPropertiesSet
方法,在所有属性设置后进行初始化。implements CorsConfigurationSource
: 允许类提供 CORS(跨源资源共享)配置。
属性
- locationValues: 存储静态资源路径的字符串列表。
- locationResources: 存储实际的
Resource
对象列表,这些对象表示静态资源的位置。 - locationsToUse: 最终确定要使用的静态资源位置列表。
- locationCharsets: 存储每个静态资源位置对应的字符集映射。
- resourceResolvers: 存储
ResourceResolver
对象的列表,用于解析静态资源的路径。 - resourceTransformers: 存储
ResourceTransformer
对象的列表,用于转换静态资源(例如压缩或缓存)。 - resolverChain:
ResourceResolverChain
对象,用于按顺序应用多个ResourceResolver
。 - transformerChain:
ResourceTransformerChain
对象,用于按顺序应用多个ResourceTransformer
。 - resourceHttpMessageConverter:
ResourceHttpMessageConverter
对象,用于将静态资源转换为 HTTP 消息。 - resourceRegionHttpMessageConverter:
ResourceRegionHttpMessageConverter
对象,用于处理分段传输的文件(如视频流)。 - contentNegotiationManager:
ContentNegotiationManager
对象,用于根据客户端请求的内容类型进行内容协商。 - mediaTypes: 存储媒体类型的映射,用于响应头中的 "Content-Type" 字段。
- corsConfiguration:
CorsConfiguration
对象,用于配置跨域资源共享(CORS)策略。 - urlPathHelper:
UrlPathHelper
对象,用于帮助解析 URL 路径。 - useLastModified: 布尔值,指示是否使用最后修改时间作为缓存验证机制。
- etagGenerator: 函数接口,用于生成资源的 ETag(实体标签),用于缓存验证。
- optimizeLocations: 布尔值,指示是否优化静态资源位置的处理。
- embeddedValueResolver:
StringValueResolver
对象,用于解析嵌入的值(例如模板引擎中的变量)。
功能
ResourceHttpRequestHandler
类提供了以下功能:
- 处理静态资源的 HTTP 请求,如返回图片、CSS 或 JavaScript 文件。
- 解析资源路径,并将它们转换为
Resource
对象。 - 应用资源解析器和转换器链,以支持资源的自定义解析和转换。
- 设置 HTTP 响应头,如缓存控制和 ETag,以优化资源加载。
- 支持 CORS 配置,允许跨源请求。
- 在初始化时检查必要的属性是否已设置。
方法
handleRequest
方法
源码
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Resource resource = this.getResource(request);
if (resource == null) {
logger.debug("Resource not found");
throw new NoResourceFoundException(HttpMethod.valueOf(request.getMethod()), getPath(request));
} else if (HttpMethod.OPTIONS.matches(request.getMethod())) {
response.setHeader("Allow", this.getAllowHeader());
} else {
this.checkRequest(request);
String eTagValue = this.getEtagGenerator() != null ? (String)this.getEtagGenerator().apply(resource) : null;
long lastModified = this.isUseLastModified() ? resource.lastModified() : -1L;
if ((new ServletWebRequest(request, response)).checkNotModified(eTagValue, lastModified)) {
logger.trace("Resource not modified");
} else {
this.prepareResponse(response);
MediaType mediaType = this.getMediaType(request, resource);
this.setHeaders(response, resource, mediaType);
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
if (request.getHeader("Range") == null) {
Assert.state(this.resourceHttpMessageConverter != null, "Not initialized");
if (HttpMethod.HEAD.matches(request.getMethod())) {
this.resourceHttpMessageConverter.addDefaultHeaders(outputMessage, resource, mediaType);
outputMessage.flush();
} else {
this.resourceHttpMessageConverter.write(resource, mediaType, outputMessage);
}
} else {
Assert.state(this.resourceRegionHttpMessageConverter != null, "Not initialized");
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(request);
try {
List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
response.setStatus(206);
this.resourceRegionHttpMessageConverter.write(HttpRange.toResourceRegions(httpRanges, resource), mediaType, outputMessage);
} catch (IllegalArgumentException var11) {
response.setHeader("Content-Range", "bytes */" + resource.contentLength());
response.sendError(416);
}
}
}
}
}
handleRequest
方法是 ResourceHttpRequestHandler
类的核心方法,它负责处理 HTTP 请求并返回相应的静态资源。
获取资源: 通过调用
getResource(request)
方法来获取客户端请求的资源。如果找不到资源,则抛出NoResourceFoundException
异常。处理 OPTIONS 请求: 如果请求方法是 OPTIONS,那么设置响应头 "Allow",表示允许哪些 HTTP 方法。
检查请求: 调用
checkRequest(request)
方法对请求进行一些基本的验证。生成 ETag: 如果提供了
etagGenerator
,则使用它生成资源的 ETag(实体标签),用于缓存控制。检查资源是否被修改: 使用
ServletWebRequest
类的checkNotModified()
方法检查资源是否已被修改。如果没有修改,则直接返回 304 Not Modified 状态码。准备响应: 调用
prepareResponse(response)
方法准备响应对象。确定媒体类型: 调用
getMediaType(request, resource)
方法来确定响应的媒体类型。设置响应头: 调用
setHeaders(response, resource, mediaType)
方法设置响应头,包括内容类型、字符集等。写入响应体: 根据请求是否包含 Range 头部,选择使用
resourceHttpMessageConverter
或resourceRegionHttpMessageConverter
来写入响应体。如果是 HEAD 请求,只添加默认头部;否则,将资源转换为适当的格式并写入响应。- 如果请求包含 Range 头部,表示客户端请求的是资源的某个范围,此时需要使用
resourceRegionHttpMessageConverter
来处理分段传输。首先解析 Range 头部,然后根据范围将资源转换为ResourceRegion
对象,最后将其写入响应。 - 如果请求不包含 Range 头部,直接使用
resourceHttpMessageConverter
将资源转换为适当的格式并写入响应。
- 如果请求包含 Range 头部,表示客户端请求的是资源的某个范围,此时需要使用
处理错误: 如果在处理过程中出现错误(例如无效的 Range 请求),则设置适当的响应头和状态码,并发送错误信息。
这个方法的主要目的是根据客户端的请求,找到对应的静态资源并将其作为 HTTP 响应返回给客户端。它还处理了缓存控制、内容协商、分段传输等高级功能,以提供更好的性能和用户体验。
总结
Spring MVC框架处理静态资源的过程可以总结为以下:
配置注册:
ResourceHandlerRegistry
用于保存服务静态资源如图片、css文件或其他文件的资源处理器的注册信息。- 当在WebMvcConfigurer实现类中重写
addResourceHandlers
方法进行静态资源配置时,实际上就是在向ResourceHandlerRegistry
中注册ResourceHandlerRegistration
对象。 DispatcherServlet
在启动时会自动读取这些注册信息,并构建出对应的ResourceHttpRequestHandler
实例来处理匹配到的静态资源请求。
请求处理:
- 当一个HTTP请求到来时,
DispatcherServlet
首先会根据HandlerMapping
的配置来找到对应的处理器(Handler
)来处理这个请求。 - 如果请求是针对静态资源的,那么专门处理静态资源的
ResourceHttpRequestHandler
就会接手这个请求。 ResourceHttpRequestHandler
会利用ResourceHandlerRegistry
中的信息来定位和返回请求的静态资源。
- 当一个HTTP请求到来时,
分派处理器
HandlerMapping
的作用是将到来的HTTP请求映射到相应的处理器(Handler
),这里也包括了静态资源的处理器ResourceHttpRequestHandler
。DispatcherServlet
使用HandlerMapping
来确定由哪个Handler
来处理请求,确保每个请求都被准确且有效地处理。