浅谈SpringWeb请求解析过程
字数 2804 2025-08-06 12:20:48
Spring Web请求解析过程详解
0x00 前言
Spring MVC框架中,DispatcherServlet是前端控制器设计模式的实现,作为Spring Web MVC的集中访问点,负责职责的分派。主要职责包括:
- 文件上传解析(通过
MultipartResolve处理multipart请求) - 通过
HandlerMapping将请求映射到处理器(返回HandlerExecutionChain,包含处理器和多个拦截器) - 通过
HandlerAdapter支持多种类型的处理器 - 通过
ViewReslver解析逻辑视图名到具体视图实现 - 本地化解析
- 渲染具体视图
- 异常处理(通过
HandlerExecutionResolver)
0x01 Spring Web解析过程
以spring-webmvc 5.3.9为例,请求处理流程:
- Servlet容器调用
DispatcherServlet的service方法(实现在父类FrameworkServlet中) - 获取请求类型,除PATCH方法外都通过
HttpServlet的service方法处理 - 根据请求方法调用
processRequest方法(如GET请求调用doGet) - 执行
doService方法后调用doDispatch处理请求
doDispatch方法处理流程:
- 对multipart请求进行处理
- 获取对应的
mappedHandler(通过getHandler方法) getHandler方法按顺序循环调用HandlerMapping的getHandler方法
常见的HandlerMapping实现:
RequestMappingHandlerMapping:处理注解配置的路由
getHandlerInternal方法:
- 从request对象获取请求path
- 根据path找到
handlerMethod - 通过
UrlPathHelper类进行路径处理
lookupHandlerMethod方法:
- 直接根据路径获取对应的Mapping
- 获取不到时调用
addMatchingMappings遍历所有RequestMappingInfo对象进行匹配
getMatchingCondition方法(版本差异):
- 高版本使用
PathPattern进行URL匹配 - 2.6之前使用
AntPathMatcher进行字符串模式匹配
0x02 工具类
2.1 路径处理帮助类UrlPathHelper
UrlPathHelper是Spring的帮助类,用于解析请求中的路径,主要方法:
resolveAndCacheLookupPath方法getPathWithinApplication方法:- 获取
ContextPath并进行解码操作 - 获取
requestUri(通过request.getRequestURI()) - 对URI进行解码、移除分号内容并清理斜线等处理
- 获取
decodeAndCleanUriString方法处理:
removeSemicolonContent:根据设置删除分号或JsessioniddecodeRequestString:解码操作getSanitizedPath:将//替换为/
getRemainingPath方法:将mapping字符与requestUri字符串匹配,忽略分号部分
alwaysUseFullPath属性:
- 决定是否经过
getPathWithinServletMapping方法处理 - Spring Boot ≤2.3.0.RELEASE默认为false
- Spring Boot ≥2.3.1.RELEASE默认为true
getPathWithinServletMapping方法:
- 调用
getPathWithinApplication处理 - 获取
ServletPath(通过request.getServletPath) - 对URI标准化处理(解码、处理跨目录等)
0x03 关键属性
3.1 SuffixPatternMatch/TrailingSlashMatch
SuffixPatternMatch(后缀匹配模式):
- 以
.xxx结尾的方式进行匹配 - 如
/hello和/hello.do匹配结果相同 - 5.3后
useSuffixPatternMatch默认值由true变为false
TrailingSlashMatch(尾部斜杠匹配):
- 为true时应用尾部
/匹配 - 如
/hello和/hello/匹配结果相同
3.2 alwaysUseFullPath
版本差异:
- ≤2.3.0.RELEASE:默认为false,调用
getPathWithinServletMapping - ≥2.3.1.RELEASE:默认为true,调用
getPathWithinApplication
区别:
getPathWithinServletMapping:对URI进行标准化处理getPathWithinApplication:不进行规范化处理
0x04 解析器
4.1 AntPathMatcher & PathPattern
版本差异:
- 2.6之前:默认使用
AntPathMatcher - 2.6及之后:默认使用
PathPattern
4.1.1 AntPathMatcher
匹配规则:
?:匹配任意单字符*:匹配0或任意数量字符**:匹配0或任意层级目录{spring:正则表达式}:匹配内容赋值给变量
解析过程:
tokenizePattern()将pattern分割成String数组tokenizePath()将path分割成string数组trimTokens属性(4.3.0+默认为false):消除path中的空格
4.1.2 PathPattern
新增{*spring}语法:
- 匹配剩余path路径并赋值给变量
- 类似
/**,但可获取动态匹配内容
解析过程:
- 根据
/将URL拆分成多个PathElement对象 - 逐个调用
PathElement的matches方法匹配 matchOptionalTrailingSeparator(默认为true):- Pattern尾部无斜杠时,请求路径有尾部斜杠也能匹配
4.1.3 两者区别
-
PathPattern:- 通配符只能定义在尾部
- 只支持
/和.两种分隔符 - 新增
{*spring}语法
-
AntPathMatcher:- 通配符可在中间
- 可自定义分隔符
- 不支持
{*spring}语法